| author | |
| committer | |
| log | 3ba916584db5485c38ebf2390e8d22bc6d81bf8e |
| tree | cacae3c81235699d5271d2244cc1dfbe7f07be10 |
| parent | 4e2a960b523070c7f8fddf0ea9b6e2a94e31dafe |
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 | ||
| 2 | License for Berkeley SoftFloat Release 3e | |
| 3 | ||
| 4 | John R. Hauser | |
| 5 | 2018 January 20 | |
| 6 | ||
| 7 | The following applies to the whole of SoftFloat Release 3e as well as to | |
| 8 | each source file individually. | |
| 9 | ||
| 10 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the | |
| 11 | University of California. All rights reserved. | |
| 12 | ||
| 13 | Redistribution and use in source and binary forms, with or without | |
| 14 | modification, 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 | ||
| 27 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 28 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 29 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 30 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 31 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 32 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 33 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 34 | ON 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 | |
| 36 | THIS 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> | |
| 13 | John R. Hauser<BR> | |
| 14 | 2018 January 20<BR> | |
| 15 | </P> | |
| 16 | ||
| 17 | <P> | |
| 18 | Berkeley SoftFloat is a software implementation of binary floating-point that | |
| 19 | conforms to the IEEE Standard for Floating-Point Arithmetic. | |
| 20 | SoftFloat is distributed in the form of C source code. | |
| 21 | Building the SoftFloat sources generates a library file (typically | |
| 22 | <CODE>softfloat.a</CODE> or <CODE>libsoftfloat.a</CODE>) containing the | |
| 23 | floating-point subroutines. | |
| 24 | </P> | |
| 25 | ||
| 26 | <P> | |
| 27 | The 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> | |
| 45 | Other 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 | ||
| 2 | Package Overview for Berkeley SoftFloat Release 3e | |
| 3 | ||
| 4 | John R. Hauser | |
| 5 | 2018 January 20 | |
| 6 | ||
| 7 | Berkeley SoftFloat is a software implementation of binary floating-point | |
| 8 | that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat | |
| 9 | is distributed in the form of C source code. Building the SoftFloat sources | |
| 10 | generates a library file (typically "softfloat.a" or "libsoftfloat.a") | |
| 11 | containing the floating-point subroutines. | |
| 12 | ||
| 13 | The SoftFloat package is documented in the following files in the "doc" | |
| 14 | subdirectory: | |
| 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 | ||
| 20 | Other 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> | |
| 13 | John R. Hauser<BR> | |
| 14 | 2018 January 20<BR> | |
| 15 | </P> | |
| 16 | ||
| 17 | ||
| 18 | <H3>Release 3e (2018 January)</H3> | |
| 19 | ||
| 20 | <UL> | |
| 21 | ||
| 22 | <LI> | |
| 23 | Changed 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> | |
| 27 | Modified the behavior of rounding mode <CODE>odd</CODE> when rounding to an | |
| 28 | integer value (either conversion to an integer format or a | |
| 29 | &lsquo;<CODE>roundToInt</CODE>&rsquo; function). | |
| 30 | Previously, for those cases only, rounding mode <CODE>odd</CODE> acted the same | |
| 31 | as rounding to minimum magnitude. | |
| 32 | Now all operations are rounded consistently. | |
| 33 | ||
| 34 | <LI> | |
| 35 | Fixed some errors in the specialization code modeling Intel x86 floating-point, | |
| 36 | specifically the integers returned on invalid operations and the propagation of | |
| 37 | NaN payloads in a few rare cases. | |
| 38 | ||
| 39 | <LI> | |
| 40 | Added specialization code modeling ARM floating-point, conforming to VFPv2 or | |
| 41 | later. | |
| 42 | ||
| 43 | <LI> | |
| 44 | Added an example target for ARM processors. | |
| 45 | ||
| 46 | <LI> | |
| 47 | Fixed a minor bug whereby function <CODE>f16_to_ui64</CODE> might return a | |
| 48 | different integer than expected in the case that the floating-point operand is | |
| 49 | negative. | |
| 50 | ||
| 51 | <LI> | |
| 52 | Added example target-specific optimization for GCC, employing GCC instrinsics | |
| 53 | and support for <NOBR>128-bit</NOBR> integer arithmetic. | |
| 54 | ||
| 55 | <LI> | |
| 56 | Made other minor improvements. | |
| 57 | ||
| 58 | </UL> | |
| 59 | ||
| 60 | ||
| 61 | <H3>Release 3d (2017 August)</H3> | |
| 62 | ||
| 63 | <UL> | |
| 64 | ||
| 65 | <LI> | |
| 66 | Fixed bugs in the square root functions for <NOBR>64-bit</NOBR> | |
| 67 | double-precision, <NOBR>80-bit</NOBR> double-extended-precision, and | |
| 68 | <NOBR>128-bit</NOBR> quadruple-precision. | |
| 69 | For <NOBR>64-bit</NOBR> double-precision (<CODE>f64_sqrt</CODE>), the result | |
| 70 | could sometimes be off by <NOBR>1 unit</NOBR> in the last place | |
| 71 | (<NOBR>1 ulp</NOBR>) from what it should be. | |
| 72 | For the larger formats, the square root could be wrong in a large portion of | |
| 73 | the 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> | |
| 84 | Added optional rounding mode <CODE>odd</CODE> (round to odd, also known as | |
| 85 | <EM>jamming</EM>). | |
| 86 | ||
| 87 | <LI> | |
| 88 | Corrected 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> | |
| 99 | Implemented the common <NOBR>16-bit</NOBR> &ldquo;half-precision&rdquo; | |
| 100 | floating-point format (<CODE>float16_t</CODE>). | |
| 101 | ||
| 102 | <LI> | |
| 103 | Made the integer values returned on invalid conversions to integer formats | |
| 104 | be determined by the port-specific specialization instead of being the same for | |
| 105 | all ports. | |
| 106 | ||
| 107 | <LI> | |
| 108 | Added preprocessor macro <CODE>THREAD_LOCAL</CODE> to allow the floating-point | |
| 109 | state (modes and exception flags) to be made per-thread. | |
| 110 | ||
| 111 | <LI> | |
| 112 | Modified the provided Makefiles to allow some options to be overridden from the | |
| 113 | <CODE>make</CODE> command. | |
| 114 | ||
| 115 | <LI> | |
| 116 | Made other minor improvements. | |
| 117 | ||
| 118 | </UL> | |
| 119 | ||
| 120 | ||
| 121 | <H3>Release 3a (2015 October)</H3> | |
| 122 | ||
| 123 | <UL> | |
| 124 | ||
| 125 | <LI> | |
| 126 | Replaced 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> | |
| 136 | Complete rewrite, funded by the University of California, Berkeley, and | |
| 137 | consequently having a different use license than earlier releases. | |
| 138 | Major changes included renaming most types and functions, upgrading some | |
| 139 | algorithms, restructuring the source files, and making SoftFloat into a true | |
| 140 | library. | |
| 141 | ||
| 142 | <LI> | |
| 143 | Added 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> | |
| 148 | Added functions for fused multiply-add, for all supported floating-point | |
| 149 | formats except <NOBR>80-bit</NOBR> double-extended-precision. | |
| 150 | ||
| 151 | <LI> | |
| 152 | Added support for a fifth rounding mode, <CODE>near_maxMag</CODE> (round to | |
| 153 | nearest, with ties to maximum magnitude, away from zero). | |
| 154 | ||
| 155 | <LI> | |
| 156 | Dropped the <CODE>timesoftfloat</CODE> program (now part of the Berkeley | |
| 157 | TestFloat package). | |
| 158 | ||
| 159 | </UL> | |
| 160 | ||
| 161 | ||
| 162 | <H3>Release 2c (2015 January)</H3> | |
| 163 | ||
| 164 | <UL> | |
| 165 | ||
| 166 | <LI> | |
| 167 | Fixed mistakes affecting some <NOBR>64-bit</NOBR> processors. | |
| 168 | ||
| 169 | <LI> | |
| 170 | Further improved the documentation and the wording for the legal restrictions | |
| 171 | on 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> | |
| 182 | Made minor updates to the documentation, including improved wording for the | |
| 183 | legal restrictions on using SoftFloat. | |
| 184 | ||
| 185 | </UL> | |
| 186 | ||
| 187 | ||
| 188 | <H3>Release 2a (1998 December)</H3> | |
| 189 | ||
| 190 | <UL> | |
| 191 | ||
| 192 | <LI> | |
| 193 | Added functions to convert between <NOBR>64-bit</NOBR> integers | |
| 194 | (<CODE>int64</CODE>) and all supported floating-point formats. | |
| 195 | ||
| 196 | <LI> | |
| 197 | Fixed 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 | |
| 200 | be. | |
| 201 | (Bug discovered by Paul Donahue.) | |
| 202 | ||
| 203 | <LI> | |
| 204 | Improved the Makefiles. | |
| 205 | </UL> | |
| 206 | ||
| 207 | ||
| 208 | <H3>Release 2 (1997 June)</H3> | |
| 209 | ||
| 210 | <UL> | |
| 211 | ||
| 212 | <LI> | |
| 213 | Created the <NOBR>64-bit</NOBR> (<CODE>bits64</CODE>) version, adding the | |
| 214 | <CODE>floatx80</CODE> and <CODE>float128</CODE> formats. | |
| 215 | ||
| 216 | <LI> | |
| 217 | Changed the source directory structure, splitting the sources into a | |
| 218 | <CODE>bits32</CODE> and a <CODE>bits64</CODE> version. | |
| 219 | Renamed <CODE>environment.h</CODE> to <CODE>milieu.h</CODE> to avoid confusion | |
| 220 | with environment variables. | |
| 221 | ||
| 222 | <LI> | |
| 223 | Fixed a small error that caused <CODE>float64_round_to_int</CODE> often to | |
| 224 | round the wrong way in nearest/even mode when the operand was between | |
| 225 | 2<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> | |
| 235 | Corrected a mistake that caused borderline underflow cases not to raise the | |
| 236 | underflow flag when they should have. | |
| 237 | (Problem reported by Doug Priest.) | |
| 238 | ||
| 239 | <LI> | |
| 240 | Added the <CODE>float_detect_tininess</CODE> variable to control whether | |
| 241 | tininess is detected before or after rounding. | |
| 242 | ||
| 243 | </UL> | |
| 244 | ||
| 245 | ||
| 246 | <H3>Release 1 (1996 July)</H3> | |
| 247 | ||
| 248 | <UL> | |
| 249 | ||
| 250 | <LI> | |
| 251 | Original release, based on work done for the International Computer Science | |
| 252 | Institute (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> | |
| 13 | John R. Hauser<BR> | |
| 14 | 2018 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> | |
| 52 | This document gives information needed for compiling and/or porting Berkeley | |
| 53 | SoftFloat, a library of C functions implementing binary floating-point | |
| 54 | conforming to the IEEE Standard for Floating-Point Arithmetic. | |
| 55 | For basic documentation about SoftFloat refer to | |
| 56 | <A HREF="SoftFloat.html"><NOBR><CODE>SoftFloat.html</CODE></NOBR></A>. | |
| 57 | </P> | |
| 58 | ||
| 59 | <P> | |
| 60 | The source code for SoftFloat is intended to be relatively machine-independent | |
| 61 | and should be compilable with any ISO-Standard C compiler that also supports | |
| 62 | <NOBR>64-bit</NOBR> integers. | |
| 63 | SoftFloat 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. | |
| 70 | Changes to the interface of SoftFloat functions are documented in | |
| 71 | <A HREF="SoftFloat.html"><NOBR><CODE>SoftFloat.html</CODE></NOBR></A>. | |
| 72 | The current version of SoftFloat is <NOBR>Release 3e</NOBR>. | |
| 73 | </P> | |
| 74 | ||
| 75 | ||
| 76 | <H2>2. Limitations</H2> | |
| 77 | ||
| 78 | <P> | |
| 79 | SoftFloat 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> | |
| 85 | SoftFloat is written in C and is designed to work with other C code. | |
| 86 | The C compiler used must conform at a minimum to the 1989 ANSI standard for the | |
| 87 | C language (same as the 1990 ISO standard) and must in addition support basic | |
| 88 | arithmetic on <NOBR>64-bit</NOBR> integers. | |
| 89 | Earlier releases of SoftFloat included implementations of <NOBR>32-bit</NOBR> | |
| 90 | single-precision and <NOBR>64-bit</NOBR> double-precision floating-point that | |
| 91 | did not require <NOBR>64-bit</NOBR> integers, but this option is not supported | |
| 92 | starting with <NOBR>Release 3</NOBR>. | |
| 93 | Since 1999, ISO standards for C have mandated compiler support for | |
| 94 | <NOBR>64-bit</NOBR> integers. | |
| 95 | A compiler conforming to the 1999 C Standard or later is recommended but not | |
| 96 | strictly 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 | |
| 102 | integer types. | |
| 103 | If these headers are not supplied with the C compiler, minimal substitutes must | |
| 104 | be provided. | |
| 105 | SoftFloat&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> | |
| 107 | and <CODE>&lt;stdint.h&gt;</CODE></I>. | |
| 108 | </P> | |
| 109 | ||
| 110 | ||
| 111 | <H2>3. Acknowledgments and License</H2> | |
| 112 | ||
| 113 | <P> | |
| 114 | The SoftFloat package was written by me, <NOBR>John R.</NOBR> Hauser. | |
| 115 | <NOBR>Release 3</NOBR> of SoftFloat was a completely new implementation | |
| 116 | supplanting earlier releases. | |
| 117 | The project to create <NOBR>Release 3</NOBR> (now <NOBR>through 3e</NOBR>) was | |
| 118 | done in the employ of the University of California, Berkeley, within the | |
| 119 | Department of Electrical Engineering and Computer Sciences, first for the | |
| 120 | Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab. | |
| 121 | The work was officially overseen by Prof. Krste Asanovic, with funding provided | |
| 122 | by 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> | |
| 132 | Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery | |
| 133 | (Award #DIG07-10227), with additional support from Par Lab affiliates Nokia, | |
| 134 | NVIDIA, Oracle, and Samsung. | |
| 135 | </TD> | |
| 136 | </TR> | |
| 137 | <TR> | |
| 138 | <TD VALIGN=TOP><NOBR>ASPIRE Lab:</NOBR></TD> | |
| 139 | <TD></TD> | |
| 140 | <TD> | |
| 141 | DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from | |
| 142 | ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA, | |
| 143 | Oracle, and Samsung. | |
| 144 | </TD> | |
| 145 | </TR> | |
| 146 | </TABLE> | |
| 147 | </BLOCKQUOTE> | |
| 148 | </P> | |
| 149 | ||
| 150 | <P> | |
| 151 | The following applies to the whole of SoftFloat <NOBR>Release 3e</NOBR> as well | |
| 152 | as to each source file individually. | |
| 153 | </P> | |
| 154 | ||
| 155 | <P> | |
| 156 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the | |
| 157 | University of California. | |
| 158 | All rights reserved. | |
| 159 | </P> | |
| 160 | ||
| 161 | <P> | |
| 162 | Redistribution and use in source and binary forms, with or without | |
| 163 | modification, are permitted provided that the following conditions are met: | |
| 164 | <OL> | |
| 165 | ||
| 166 | <LI> | |
| 167 | <P> | |
| 168 | Redistributions of source code must retain the above copyright notice, this | |
| 169 | list of conditions, and the following disclaimer. | |
| 170 | </P> | |
| 171 | ||
| 172 | <LI> | |
| 173 | <P> | |
| 174 | Redistributions in binary form must reproduce the above copyright notice, this | |
| 175 | list of conditions, and the following disclaimer in the documentation and/or | |
| 176 | other materials provided with the distribution. | |
| 177 | </P> | |
| 178 | ||
| 179 | <LI> | |
| 180 | <P> | |
| 181 | Neither the name of the University nor the names of its contributors may be | |
| 182 | used to endorse or promote products derived from this software without specific | |
| 183 | prior written permission. | |
| 184 | </P> | |
| 185 | ||
| 186 | </OL> | |
| 187 | </P> | |
| 188 | ||
| 189 | <P> | |
| 190 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS &ldquo;AS IS&rdquo;, | |
| 191 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 192 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 193 | DISCLAIMED. | |
| 194 | IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
| 195 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 196 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 197 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 198 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE | |
| 199 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
| 200 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 201 | </P> | |
| 202 | ||
| 203 | ||
| 204 | <H2>4. SoftFloat Package Directory Structure</H2> | |
| 205 | ||
| 206 | <P> | |
| 207 | Because SoftFloat is targeted to multiple platforms, its source code is | |
| 208 | slightly scattered between target-specific and target-independent directories | |
| 209 | and files. | |
| 210 | The supplied directory structure is as follows: | |
| 211 | <BLOCKQUOTE> | |
| 212 | <PRE> | |
| 213 | doc | |
| 214 | source | |
| 215 | include | |
| 216 | 8086 | |
| 217 | 8086-SSE | |
| 218 | ARM-VFPv2 | |
| 219 | ARM-VFPv2-defaultNaN | |
| 220 | build | |
| 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> | |
| 232 | The majority of the SoftFloat sources are provided in the <CODE>source</CODE> | |
| 233 | directory. | |
| 234 | The <CODE>include</CODE> subdirectory contains several header files | |
| 235 | (unsurprisingly), while the other subdirectories of <CODE>source</CODE> contain | |
| 236 | source files that specialize the floating-point behavior to match particular | |
| 237 | processor families: | |
| 238 | <BLOCKQUOTE> | |
| 239 | <DL> | |
| 240 | <DT><CODE>8086</CODE></DT> | |
| 241 | <DD> | |
| 242 | Intel&rsquo;s older, 8087-derived floating-point, extended to all supported | |
| 243 | floating-point types | |
| 244 | </DD> | |
| 245 | <DT><CODE>8086-SSE</CODE></DT> | |
| 246 | <DD> | |
| 247 | Intel&rsquo;s x86 processors with Streaming SIMD Extensions (SSE) and later | |
| 248 | compatible extensions, having 8087 behavior for <NOBR>80-bit</NOBR> | |
| 249 | double-extended-precision (<CODE>extFloat80_t</CODE>) and SSE behavior for | |
| 250 | other floating-point types | |
| 251 | </DD> | |
| 252 | <DT><CODE>ARM-VFPv2</CODE></DT> | |
| 253 | <DD> | |
| 254 | ARM&rsquo;s VFPv2 or later floating-point, with NaN payload propagation | |
| 255 | </DD> | |
| 256 | <DT><CODE>ARM-VFPv2-defaultNaN</CODE></DT> | |
| 257 | <DD> | |
| 258 | ARM&rsquo;s VFPv2 or later floating-point, with the &ldquo;default NaN&rdquo; | |
| 259 | option | |
| 260 | </DD> | |
| 261 | </DL> | |
| 262 | </BLOCKQUOTE> | |
| 263 | If other specializations are attempted, these would be expected to be other | |
| 264 | subdirectories of <CODE>source</CODE> alongside the ones listed above. | |
| 265 | Specialization is covered later, in <NOBR>section 5.2</NOBR>, <I>Specializing | |
| 266 | Floating-Point Behavior</I>. | |
| 267 | </P> | |
| 268 | ||
| 269 | <P> | |
| 270 | The <CODE>build</CODE> directory is intended to contain a subdirectory for each | |
| 271 | target platform for which a build of the SoftFloat library may be created. | |
| 272 | For each build target, the target&rsquo;s subdirectory is where all derived | |
| 273 | object files and the completed SoftFloat library (typically | |
| 274 | <CODE>softfloat.a</CODE> or <CODE>libsoftfloat.a</CODE>) are created. | |
| 275 | The two <CODE>template</CODE> subdirectories are not actual build targets but | |
| 276 | contain sample files for creating new target directories. | |
| 277 | (The meaning of <CODE>FAST_INT64</CODE> will be explained later.) | |
| 278 | </P> | |
| 279 | ||
| 280 | <P> | |
| 281 | Ignoring the <CODE>template</CODE> directories, the supplied target directories | |
| 282 | are intended to follow a naming system of | |
| 283 | <NOBR><CODE>&lt;<I>execution-environment</I>&gt;-&lt;<I>compiler</I>&gt;</CODE></NOBR>. | |
| 284 | For 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> | |
| 295 | All of the supplied target directories are merely examples that may or may not | |
| 296 | be correct for compiling on any particular system. | |
| 297 | Despite requests, there are currently no plans to include and maintain in the | |
| 298 | SoftFloat package the build files needed for a great many users&rsquo; | |
| 299 | compilation environments, which can span a huge range of operating systems, | |
| 300 | compilers, and other tools. | |
| 301 | </P> | |
| 302 | ||
| 303 | <P> | |
| 304 | As supplied, each target directory contains two files: | |
| 305 | <BLOCKQUOTE> | |
| 306 | <PRE> | |
| 307 | Makefile | |
| 308 | platform.h | |
| 309 | </PRE> | |
| 310 | </BLOCKQUOTE> | |
| 311 | The provided <CODE>Makefile</CODE> is written for GNU <CODE>make</CODE>. | |
| 312 | A 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. | |
| 314 | A completely different build tool can be used if an appropriate | |
| 315 | <CODE>Makefile</CODE> equivalent is created. | |
| 316 | </P> | |
| 317 | ||
| 318 | <P> | |
| 319 | The <CODE>platform.h</CODE> header file exists to provide a location for | |
| 320 | additional C declarations specific to the build target. | |
| 321 | Every C source file of SoftFloat contains a <CODE>#include</CODE> for | |
| 322 | <CODE>platform.h</CODE>. | |
| 323 | In many cases, the contents of <CODE>platform.h</CODE> can be as simple as one | |
| 324 | or two lines of code. | |
| 325 | At the other extreme, to get maximal performance from SoftFloat, it may be | |
| 326 | desirable to include in header <CODE>platform.h</CODE> (directly or via | |
| 327 | <CODE>#include</CODE>) declarations for numerous target-specific optimizations. | |
| 328 | Such possibilities are discussed in the next section, <I>Issues for Porting | |
| 329 | SoftFloat to a New Target</I>. | |
| 330 | If the target&rsquo;s compiler or library has bugs or other shortcomings, | |
| 331 | workarounds for these issues may also be possible with target-specific | |
| 332 | declarations in <CODE>platform.h</CODE>, avoiding the need to modify the main | |
| 333 | SoftFloat 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> | |
| 342 | The SoftFloat sources make use of standard headers | |
| 343 | <CODE>&lt;stdbool.h&gt;</CODE> and <CODE>&lt;stdint.h&gt;</CODE>, which have | |
| 344 | been part of the ISO C Standard Library since 1999. | |
| 345 | With any recent compiler, these standard headers are likely to be supported, | |
| 346 | even if the compiler does not claim complete conformance to the latest ISO C | |
| 347 | Standard. | |
| 348 | For older or nonstandard compilers, substitutes for | |
| 349 | <CODE>&lt;stdbool.h&gt;</CODE> and <CODE>&lt;stdint.h&gt;</CODE> may need to be | |
| 350 | created. | |
| 351 | SoftFloat depends on these names from <CODE>&lt;stdbool.h&gt;</CODE>: | |
| 352 | <BLOCKQUOTE> | |
| 353 | <PRE> | |
| 354 | bool | |
| 355 | true | |
| 356 | false | |
| 357 | </PRE> | |
| 358 | </BLOCKQUOTE> | |
| 359 | and on these names from <CODE>&lt;stdint.h&gt;</CODE>: | |
| 360 | <BLOCKQUOTE> | |
| 361 | <PRE> | |
| 362 | uint16_t | |
| 363 | uint32_t | |
| 364 | uint64_t | |
| 365 | int32_t | |
| 366 | int64_t | |
| 367 | UINT64_C | |
| 368 | INT64_C | |
| 369 | uint_least8_t | |
| 370 | uint_fast8_t | |
| 371 | uint_fast16_t | |
| 372 | uint_fast32_t | |
| 373 | uint_fast64_t | |
| 374 | int_fast8_t | |
| 375 | int_fast16_t | |
| 376 | int_fast32_t | |
| 377 | int_fast64_t | |
| 378 | </PRE> | |
| 379 | </BLOCKQUOTE> | |
| 380 | </P> | |
| 381 | ||
| 382 | ||
| 383 | <H3>5.2. Specializing Floating-Point Behavior</H3> | |
| 384 | ||
| 385 | <P> | |
| 386 | The IEEE Floating-Point Standard allows for some flexibility in a conforming | |
| 387 | implementation, particularly concerning NaNs. | |
| 388 | The SoftFloat <CODE>source</CODE> directory is supplied with some | |
| 389 | <I>specialization</I> subdirectories containing possible definitions for this | |
| 390 | implementation-specific behavior. | |
| 391 | For example, the <CODE>8086</CODE> and <NOBR><CODE>8086-SSE</CODE></NOBR> | |
| 392 | subdirectories have source files that specialize SoftFloat&rsquo;s behavior to | |
| 393 | match that of Intel&rsquo;s x86 line of processors. | |
| 394 | The files in a specialization subdirectory must determine: | |
| 395 | <UL> | |
| 396 | <LI> | |
| 397 | whether tininess for underflow is detected before or after rounding by default; | |
| 398 | <LI> | |
| 399 | how signaling NaNs are distinguished from quiet NaNs; | |
| 400 | <LI> | |
| 401 | what (if anything) special happens when exceptions are raised; | |
| 402 | <LI> | |
| 403 | the default generated quiet NaNs; | |
| 404 | <LI> | |
| 405 | how NaNs are propagated from function inputs to output; and | |
| 406 | <LI> | |
| 407 | the integer results returned when conversions to integer type raise the | |
| 408 | <I>invalid</I> exception. | |
| 409 | </UL> | |
| 410 | </P> | |
| 411 | ||
| 412 | <P> | |
| 413 | As provided, the build process for a target expects to involve exactly | |
| 414 | <EM>one</EM> specialization directory that defines <EM>all</EM> of these | |
| 415 | implementation-specific details for the target. | |
| 416 | A specialization directory such as <CODE>8086</CODE> is expected to contain a | |
| 417 | header file called <CODE>specialize.h</CODE>, together with whatever other | |
| 418 | source files are needed to complete the specialization. | |
| 419 | </P> | |
| 420 | ||
| 421 | <P> | |
| 422 | A new build target may use an existing specialization, such as the ones | |
| 423 | provided by the <CODE>8086</CODE> and <NOBR><CODE>8086-SSE</CODE></NOBR> | |
| 424 | subdirectories. | |
| 425 | If a build target needs a new specialization, different from any existing ones, | |
| 426 | it is recommended that a new specialization directory be created for this | |
| 427 | purpose. | |
| 428 | The <CODE>specialize.h</CODE> header file from any of the provided | |
| 429 | specialization subdirectories can be used as a model for what definitions are | |
| 430 | needed. | |
| 431 | </P> | |
| 432 | ||
| 433 | ||
| 434 | <H3>5.3. Macros for Build Options</H3> | |
| 435 | ||
| 436 | <P> | |
| 437 | The SoftFloat source files adapt the floating-point implementation according to | |
| 438 | several C preprocessor macros: | |
| 439 | <BLOCKQUOTE> | |
| 440 | <DL> | |
| 441 | <DT><CODE>LITTLEENDIAN</CODE> | |
| 442 | <DD> | |
| 443 | Must be defined for little-endian machines; must not be defined for big-endian | |
| 444 | machines. | |
| 445 | <DT><CODE>INLINE</CODE> | |
| 446 | <DD> | |
| 447 | Specifies the sequence of tokens used to indicate that a C function should be | |
| 448 | inlined. | |
| 449 | If macro <CODE>INLINE_LEVEL</CODE> is defined with a value of 1 or higher, this | |
| 450 | macro must be defined; otherwise, this macro is ignored and need not be | |
| 451 | defined. | |
| 452 | For compilers that conform to the C Standard&rsquo;s rules for inline | |
| 453 | functions, this macro can be defined as the single keyword <CODE>inline</CODE>. | |
| 454 | For 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> | |
| 459 | Can be defined to a sequence of tokens that, when appearing at the start of a | |
| 460 | variable declaration, indicates to the C compiler that the variable is | |
| 461 | <I>per-thread</I>, meaning that each execution thread gets its own separate | |
| 462 | instance of the variable. | |
| 463 | This macro is used in header <CODE>softfloat.h</CODE> in the declarations of | |
| 464 | variables <CODE>softfloat_roundingMode</CODE>, | |
| 465 | <CODE>softfloat_detectTininess</CODE>, <CODE>extF80_roundingPrecision</CODE>, | |
| 466 | and <CODE>softfloat_exceptionFlags</CODE>. | |
| 467 | If macro <CODE>THREAD_LOCAL</CODE> is left undefined, these variables will | |
| 468 | default to being ordinary global variables. | |
| 469 | Depending 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> | |
| 475 | Can 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> | |
| 481 | Can be defined to an integer to determine the degree of inlining requested of | |
| 482 | the compiler. | |
| 483 | Larger numbers request that more inlining be done. | |
| 484 | If this macro is not defined or is defined to a value less <NOBR>than 1</NOBR> | |
| 485 | (zero or negative), no inlining is requested. | |
| 486 | The maximum effective value is no higher <NOBR>than 5</NOBR>. | |
| 487 | Defining 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> | |
| 491 | Can be defined to indicate that the build target&rsquo;s implementation of | |
| 492 | <NOBR>64-bit</NOBR> arithmetic is efficient. | |
| 493 | For newer <NOBR>64-bit</NOBR> processors, this macro should usually be defined. | |
| 494 | For very small microprocessors whose buses and registers are <NOBR>8-bit</NOBR> | |
| 495 | or <NOBR>16-bit</NOBR> in size, this macro should usually not be defined. | |
| 496 | Whether this macro should be defined for a <NOBR>32-bit</NOBR> processor may | |
| 497 | depend on the target machine and the applications that will use SoftFloat. | |
| 498 | <DT><CODE>SOFTFLOAT_FAST_DIV32TO16</CODE> | |
| 499 | <DD> | |
| 500 | Can be defined to indicate that the target&rsquo;s division operator | |
| 501 | <NOBR>in C</NOBR> (written as <CODE>/</CODE>) is reasonably efficient for | |
| 502 | dividing a <NOBR>32-bit</NOBR> unsigned integer by a <NOBR>16-bit</NOBR> | |
| 503 | unsigned integer. | |
| 504 | Setting this macro may affect the performance of function <CODE>f16_div</CODE>. | |
| 505 | <DT><CODE>SOFTFLOAT_FAST_DIV64TO32</CODE> | |
| 506 | <DD> | |
| 507 | Can be defined to indicate that the target&rsquo;s division operator | |
| 508 | <NOBR>in C</NOBR> (written as <CODE>/</CODE>) is reasonably efficient for | |
| 509 | dividing a <NOBR>64-bit</NOBR> unsigned integer by a <NOBR>32-bit</NOBR> | |
| 510 | unsigned integer. | |
| 511 | Setting this macro may affect the performance of division, remainder, and | |
| 512 | square root operations other than <CODE>f16_div</CODE>. | |
| 513 | </DL> | |
| 514 | </BLOCKQUOTE> | |
| 515 | </P> | |
| 516 | ||
| 517 | <P> | |
| 518 | Following the usual custom <NOBR>for C</NOBR>, for most of these macros (all | |
| 519 | except <CODE>INLINE</CODE>, <CODE>THREAD_LOCAL</CODE>, and | |
| 520 | <CODE>INLINE_LEVEL</CODE>), the content of any definition is irrelevant; | |
| 521 | what matters is a macro&rsquo;s effect on <CODE>#ifdef</CODE> directives. | |
| 522 | </P> | |
| 523 | ||
| 524 | <P> | |
| 525 | It is recommended that any definitions of macros <CODE>LITTLEENDIAN</CODE>, | |
| 526 | <CODE>INLINE</CODE>, and <CODE>THREAD_LOCAL</CODE> be made in a build | |
| 527 | target&rsquo;s <CODE>platform.h</CODE> header file, because these macros are | |
| 528 | expected to be determined inflexibly by the target machine and compiler. | |
| 529 | The other five macros select options and control optimization, and thus might | |
| 530 | be 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> | |
| 537 | In the <CODE>build</CODE> directory, two <CODE>template</CODE> subdirectories | |
| 538 | provide models for new target directories. | |
| 539 | Two different templates exist because different functions are needed in the | |
| 540 | SoftFloat library depending on whether macro <CODE>SOFTFLOAT_FAST_INT64</CODE> | |
| 541 | is defined. | |
| 542 | If macro <CODE>SOFTFLOAT_FAST_INT64</CODE> will be defined, | |
| 543 | <NOBR><CODE>template-FAST_INT64</CODE></NOBR> is the template to use; | |
| 544 | otherwise, <NOBR><CODE>template-not-FAST_INT64</CODE></NOBR> is the appropriate | |
| 545 | template. | |
| 546 | A new target directory can be created by copying the correct template directory | |
| 547 | and editing the files inside. | |
| 548 | To avoid confusion, it would be wise to refrain from editing the files within a | |
| 549 | template directory directly. | |
| 550 | </P> | |
| 551 | ||
| 552 | ||
| 553 | <H3>5.5. Target-Specific Optimization of Primitive Functions</H3> | |
| 554 | ||
| 555 | <P> | |
| 556 | Header file <CODE>primitives.h</CODE> (in directory | |
| 557 | <CODE>source/include</CODE>) declares macros and functions for numerous | |
| 558 | underlying arithmetic operations upon which many of SoftFloat&rsquo;s | |
| 559 | floating-point functions are ultimately built. | |
| 560 | The SoftFloat sources include implementations of all of these functions/macros, | |
| 561 | written as standard C code, so a complete and correct SoftFloat library can be | |
| 562 | created using only the supplied code for all functions. | |
| 563 | However, for many targets, SoftFloat&rsquo;s performance can be improved by | |
| 564 | substituting target-specific implementations of some of the functions/macros | |
| 565 | declared in <CODE>primitives.h</CODE>. | |
| 566 | </P> | |
| 567 | ||
| 568 | <P> | |
| 569 | For 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 | |
| 572 | integer&rsquo;s most-significant bits that are zeros. | |
| 573 | While the SoftFloat sources include an implementation of this function written | |
| 574 | in <NOBR>standard C</NOBR>, many processors can perform this same function | |
| 575 | directly in only one or two machine instructions. | |
| 576 | An alternative, target-specific implementation that maps to those instructions | |
| 577 | is likely to be more efficient than the generic C code from the SoftFloat | |
| 578 | package. | |
| 579 | </P> | |
| 580 | ||
| 581 | <P> | |
| 582 | A 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 | |
| 584 | target&rsquo;s <CODE>platform.h</CODE> header file. | |
| 585 | For this purpose, it may be helpful for <CODE>platform.h</CODE> to | |
| 586 | <CODE>#include</CODE> header file <CODE>primitiveTypes.h</CODE>, which defines | |
| 587 | types used for arguments and results of functions declared in | |
| 588 | <CODE>primitives.h</CODE>. | |
| 589 | When a desired replacement implementation is a function, not a macro, it is | |
| 590 | sufficient 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> | |
| 596 | where <NOBR><CODE>&lt;<I>function-name</I>&gt;</CODE></NOBR> is the name of the | |
| 597 | function. | |
| 598 | This technically defines <NOBR><CODE>&lt;<I>function-name</I>&gt;</CODE></NOBR> | |
| 599 | as a macro, but one that resolves to the same name, which may then be a | |
| 600 | function. | |
| 601 | (A preprocessor that conforms to the C Standard is required to limit recursive | |
| 602 | macro expansion from being applied more than once.) | |
| 603 | </P> | |
| 604 | ||
| 605 | <P> | |
| 606 | The supplied header file <CODE>opts-GCC.h</CODE> (in directory | |
| 607 | <CODE>source/include</CODE>) provides an example of target-specific | |
| 608 | optimization for the GCC compiler. | |
| 609 | Each GCC target example in the <CODE>build</CODE> directory has | |
| 610 | <BLOCKQUOTE> | |
| 611 | <CODE>#include "opts-GCC.h"</CODE> | |
| 612 | </BLOCKQUOTE> | |
| 613 | in its <CODE>platform.h</CODE> header file. | |
| 614 | Before <CODE>opts-GCC.h</CODE> is included, the following macros must be | |
| 615 | defined (or not) to control which features are invoked: | |
| 616 | <BLOCKQUOTE> | |
| 617 | <DL> | |
| 618 | <DT><CODE>SOFTFLOAT_BUILTIN_CLZ</CODE></DT> | |
| 619 | <DD> | |
| 620 | If 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> | |
| 626 | If defined, SoftFloat makes use of GCC&rsquo;s nonstandard <NOBR>128-bit</NOBR> | |
| 627 | integer type <CODE>__int128</CODE>. | |
| 628 | </DD> | |
| 629 | </DL> | |
| 630 | </BLOCKQUOTE> | |
| 631 | On 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 | |
| 633 | other functions receive less dramatic boosts, or none at all. | |
| 634 | Results can vary greatly across different platforms. | |
| 635 | </P> | |
| 636 | ||
| 637 | ||
| 638 | <H2>6. Testing SoftFloat</H2> | |
| 639 | ||
| 640 | <P> | |
| 641 | SoftFloat can be tested using the <CODE>testsoftfloat</CODE> program by the | |
| 642 | same author. | |
| 643 | This program is part of the Berkeley TestFloat package available at the Web | |
| 644 | page | |
| 645 | <A HREF="http://www.jhauser.us/arithmetic/TestFloat.html"><NOBR><CODE>http://www.jhauser.us/arithmetic/TestFloat.html</CODE></NOBR></A>. | |
| 646 | The TestFloat package also has a program called <CODE>timesoftfloat</CODE> that | |
| 647 | measures 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> | |
| 654 | Header file <CODE>softfloat.h</CODE> defines the SoftFloat interface as seen by | |
| 655 | clients. | |
| 656 | If the SoftFloat library will be made a common library for programs on a | |
| 657 | system, the supplied <CODE>softfloat.h</CODE> has a couple of deficiencies for | |
| 658 | this purpose: | |
| 659 | <UL> | |
| 660 | <LI> | |
| 661 | As supplied, <CODE>softfloat.h</CODE> depends on another header, | |
| 662 | <CODE>softfloat_types.h</CODE>, that is not intended for public use but which | |
| 663 | must also be visible to the programmer&rsquo;s compiler. | |
| 664 | <LI> | |
| 665 | More troubling, at the time <CODE>softfloat.h</CODE> is included in a C source | |
| 666 | file, macros <CODE>SOFTFLOAT_FAST_INT64</CODE> and <CODE>THREAD_LOCAL</CODE> | |
| 667 | must be defined, or not defined, consistent with how these macro were defined | |
| 668 | when the SoftFloat library was built. | |
| 669 | </UL> | |
| 670 | In the situation that new programs may regularly <CODE>#include</CODE> header | |
| 671 | file <CODE>softfloat.h</CODE>, it is recommended that a custom, self-contained | |
| 672 | version of this header file be created that eliminates these issues. | |
| 673 | </P> | |
| 674 | ||
| 675 | ||
| 676 | <H2>8. Contact Information</H2> | |
| 677 | ||
| 678 | <P> | |
| 679 | At the time of this writing, the most up-to-date information about SoftFloat | |
| 680 | and 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> | |
| 13 | John R. Hauser<BR> | |
| 14 | 2018 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> | |
| 72 | Berkeley SoftFloat is a software implementation of binary floating-point that | |
| 73 | conforms to the IEEE Standard for Floating-Point Arithmetic. | |
| 74 | The current release supports five binary formats: <NOBR>16-bit</NOBR> | |
| 75 | half-precision, <NOBR>32-bit</NOBR> single-precision, <NOBR>64-bit</NOBR> | |
| 76 | double-precision, <NOBR>80-bit</NOBR> double-extended-precision, and | |
| 77 | <NOBR>128-bit</NOBR> quadruple-precision. | |
| 78 | The following functions are supported for each format: | |
| 79 | <UL> | |
| 80 | <LI> | |
| 81 | addition, subtraction, multiplication, division, and square root; | |
| 82 | <LI> | |
| 83 | fused multiply-add as defined by the IEEE Standard, except for | |
| 84 | <NOBR>80-bit</NOBR> double-extended-precision; | |
| 85 | <LI> | |
| 86 | remainder as defined by the IEEE Standard; | |
| 87 | <LI> | |
| 88 | round to integral value; | |
| 89 | <LI> | |
| 90 | comparisons; | |
| 91 | <LI> | |
| 92 | conversions to/from other supported formats; and | |
| 93 | <LI> | |
| 94 | conversions to/from <NOBR>32-bit</NOBR> and <NOBR>64-bit</NOBR> integers, | |
| 95 | signed and unsigned. | |
| 96 | </UL> | |
| 97 | All operations required by the original 1985 version of the IEEE Floating-Point | |
| 98 | Standard are implemented, except for conversions to and from decimal. | |
| 99 | </P> | |
| 100 | ||
| 101 | <P> | |
| 102 | This document gives information about the types defined and the routines | |
| 103 | implemented by SoftFloat. | |
| 104 | It does not attempt to define or explain the IEEE Floating-Point Standard. | |
| 105 | Information about the standard is available elsewhere. | |
| 106 | </P> | |
| 107 | ||
| 108 | <P> | |
| 109 | The current version of SoftFloat is <NOBR>Release 3e</NOBR>. | |
| 110 | This 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 | |
| 112 | specialization and optimization examples for those compiling SoftFloat. | |
| 113 | </P> | |
| 114 | ||
| 115 | <P> | |
| 116 | The previous <NOBR>Release 3d</NOBR> fixed bugs that were found in the square | |
| 117 | root 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 | |
| 120 | incorrect result.) | |
| 121 | The bugs affected all prior <NOBR>Release-3</NOBR> versions of SoftFloat | |
| 122 | <NOBR>through 3c</NOBR>. | |
| 123 | The flaw in the <NOBR>64-bit</NOBR> floating-point square root function was of | |
| 124 | very minor impact, causing a <NOBR>1-ulp</NOBR> error (<NOBR>1 unit</NOBR> in | |
| 125 | the last place) a few times out of a billion. | |
| 126 | The bugs in the <NOBR>80-bit</NOBR> and <NOBR>128-bit</NOBR> square root | |
| 127 | functions were more serious. | |
| 128 | Although incorrect results again occurred only a few times out of a billion, | |
| 129 | when they did occur a large portion of the less-significant bits could be | |
| 130 | wrong. | |
| 131 | </P> | |
| 132 | ||
| 133 | <P> | |
| 134 | Among earlier releases, 3b was notable for adding support for the | |
| 135 | <NOBR>16-bit</NOBR> half-precision format. | |
| 136 | For 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> | |
| 141 | The functional interface of SoftFloat <NOBR>Release 3</NOBR> and later differs | |
| 142 | in many details from the releases that came before. | |
| 143 | For 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> | |
| 151 | SoftFloat 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> | |
| 157 | SoftFloat is written in C and is designed to work with other C code. | |
| 158 | The C compiler used must conform at a minimum to the 1989 ANSI standard for the | |
| 159 | C language (same as the 1990 ISO standard) and must in addition support basic | |
| 160 | arithmetic on <NOBR>64-bit</NOBR> integers. | |
| 161 | Earlier releases of SoftFloat included implementations of <NOBR>32-bit</NOBR> | |
| 162 | single-precision and <NOBR>64-bit</NOBR> double-precision floating-point that | |
| 163 | did not require <NOBR>64-bit</NOBR> integers, but this option is not supported | |
| 164 | starting with <NOBR>Release 3</NOBR>. | |
| 165 | Since 1999, ISO standards for C have mandated compiler support for | |
| 166 | <NOBR>64-bit</NOBR> integers. | |
| 167 | A compiler conforming to the 1999 C Standard or later is recommended but not | |
| 168 | strictly required. | |
| 169 | </P> | |
| 170 | ||
| 171 | <P> | |
| 172 | Most operations not required by the original 1985 version of the IEEE | |
| 173 | Floating-Point Standard but added in the 2008 version are not yet supported in | |
| 174 | SoftFloat <NOBR>Release 3e</NOBR>. | |
| 175 | </P> | |
| 176 | ||
| 177 | ||
| 178 | <H2>3. Acknowledgments and License</H2> | |
| 179 | ||
| 180 | <P> | |
| 181 | The SoftFloat package was written by me, <NOBR>John R.</NOBR> Hauser. | |
| 182 | <NOBR>Release 3</NOBR> of SoftFloat was a completely new implementation | |
| 183 | supplanting earlier releases. | |
| 184 | The project to create <NOBR>Release 3</NOBR> (now <NOBR>through 3e</NOBR>) was | |
| 185 | done in the employ of the University of California, Berkeley, within the | |
| 186 | Department of Electrical Engineering and Computer Sciences, first for the | |
| 187 | Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab. | |
| 188 | The work was officially overseen by Prof. Krste Asanovic, with funding provided | |
| 189 | by 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> | |
| 199 | Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery | |
| 200 | (Award #DIG07-10227), with additional support from Par Lab affiliates Nokia, | |
| 201 | NVIDIA, Oracle, and Samsung. | |
| 202 | </TD> | |
| 203 | </TR> | |
| 204 | <TR> | |
| 205 | <TD VALIGN=TOP><NOBR>ASPIRE Lab:</NOBR></TD> | |
| 206 | <TD></TD> | |
| 207 | <TD> | |
| 208 | DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from | |
| 209 | ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA, | |
| 210 | Oracle, and Samsung. | |
| 211 | </TD> | |
| 212 | </TR> | |
| 213 | </TABLE> | |
| 214 | </BLOCKQUOTE> | |
| 215 | </P> | |
| 216 | ||
| 217 | <P> | |
| 218 | The following applies to the whole of SoftFloat <NOBR>Release 3e</NOBR> as well | |
| 219 | as to each source file individually. | |
| 220 | </P> | |
| 221 | ||
| 222 | <P> | |
| 223 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the | |
| 224 | University of California. | |
| 225 | All rights reserved. | |
| 226 | </P> | |
| 227 | ||
| 228 | <P> | |
| 229 | Redistribution and use in source and binary forms, with or without | |
| 230 | modification, are permitted provided that the following conditions are met: | |
| 231 | <OL> | |
| 232 | ||
| 233 | <LI> | |
| 234 | <P> | |
| 235 | Redistributions of source code must retain the above copyright notice, this | |
| 236 | list of conditions, and the following disclaimer. | |
| 237 | </P> | |
| 238 | ||
| 239 | <LI> | |
| 240 | <P> | |
| 241 | Redistributions in binary form must reproduce the above copyright notice, this | |
| 242 | list of conditions, and the following disclaimer in the documentation and/or | |
| 243 | other materials provided with the distribution. | |
| 244 | </P> | |
| 245 | ||
| 246 | <LI> | |
| 247 | <P> | |
| 248 | Neither the name of the University nor the names of its contributors may be | |
| 249 | used to endorse or promote products derived from this software without specific | |
| 250 | prior written permission. | |
| 251 | </P> | |
| 252 | ||
| 253 | </OL> | |
| 254 | </P> | |
| 255 | ||
| 256 | <P> | |
| 257 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS &ldquo;AS IS&rdquo;, | |
| 258 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 259 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 260 | DISCLAIMED. | |
| 261 | IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
| 262 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 263 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 264 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
| 265 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE | |
| 266 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
| 267 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 268 | </P> | |
| 269 | ||
| 270 | ||
| 271 | <H2>4. Types and Functions</H2> | |
| 272 | ||
| 273 | <P> | |
| 274 | The 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> | |
| 281 | Header 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. | |
| 284 | These standard headers have been part of the ISO C Standard Library since 1999. | |
| 285 | With any recent compiler, they are likely to be supported, even if the compiler | |
| 286 | does not claim complete conformance to the latest ISO C Standard. | |
| 287 | For older or nonstandard compilers, a port of SoftFloat may have substitutes | |
| 288 | for these headers. | |
| 289 | Header <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> | |
| 294 | uint16_t | |
| 295 | uint32_t | |
| 296 | uint64_t | |
| 297 | int32_t | |
| 298 | int64_t | |
| 299 | uint_fast8_t | |
| 300 | uint_fast32_t | |
| 301 | uint_fast64_t | |
| 302 | int_fast32_t | |
| 303 | int_fast64_t | |
| 304 | </PRE> | |
| 305 | </BLOCKQUOTE> | |
| 306 | </P> | |
| 307 | ||
| 308 | ||
| 309 | <H3>4.2. Floating-Point Types</H3> | |
| 310 | ||
| 311 | <P> | |
| 312 | The <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 | |
| 330 | Motorola 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> | |
| 338 | The 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>. | |
| 342 | Aside from these size requirements, the definitions of all these types may | |
| 343 | differ for different ports of SoftFloat to specific systems. | |
| 344 | A given port of SoftFloat may or may not define some of the floating-point | |
| 345 | types 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> | |
| 350 | Header 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. | |
| 353 | This structure is the same size as type <CODE>extFloat80_t</CODE> and contains | |
| 354 | at least these two fields (not necessarily in this order): | |
| 355 | <BLOCKQUOTE> | |
| 356 | <PRE> | |
| 357 | uint16_t signExp; | |
| 358 | uint64_t signif; | |
| 359 | </PRE> | |
| 360 | </BLOCKQUOTE> | |
| 361 | Field <CODE>signExp</CODE> contains the sign and exponent of the floating-point | |
| 362 | value, with the sign in the most significant bit (<NOBR>bit 15</NOBR>) and the | |
| 363 | encoded exponent in the other <NOBR>15 bits</NOBR>. | |
| 364 | Field <CODE>signif</CODE> is the complete <NOBR>64-bit</NOBR> significand of | |
| 365 | the floating-point value. | |
| 366 | (In the usual encoding for <NOBR>80-bit</NOBR> extended floating-point, the | |
| 367 | leading <NOBR>1 bit</NOBR> of normalized numbers is not implicit but is stored | |
| 368 | in the most significant bit of the significand.) | |
| 369 | </P> | |
| 370 | ||
| 371 | <H3>4.3. Supported Floating-Point Functions</H3> | |
| 372 | ||
| 373 | <P> | |
| 374 | SoftFloat implements these arithmetic operations for its floating-point types: | |
| 375 | <UL> | |
| 376 | <LI> | |
| 377 | conversions between any two floating-point formats; | |
| 378 | <LI> | |
| 379 | for each floating-point format, conversions to and from signed and unsigned | |
| 380 | <NOBR>32-bit</NOBR> and <NOBR>64-bit</NOBR> integers; | |
| 381 | <LI> | |
| 382 | for each format, the usual addition, subtraction, multiplication, division, and | |
| 383 | square root operations; | |
| 384 | <LI> | |
| 385 | for each format except <CODE>extFloat80_t</CODE>, the fused multiply-add | |
| 386 | operation defined by the IEEE Standard; | |
| 387 | <LI> | |
| 388 | for each format, the floating-point remainder operation defined by the IEEE | |
| 389 | Standard; | |
| 390 | <LI> | |
| 391 | for each format, a &ldquo;round to integer&rdquo; operation that rounds to the | |
| 392 | nearest integer value in the same format; and | |
| 393 | <LI> | |
| 394 | comparisons between two values in the same floating-point format. | |
| 395 | </UL> | |
| 396 | </P> | |
| 397 | ||
| 398 | <P> | |
| 399 | The following operations required by the 2008 IEEE Floating-Point Standard are | |
| 400 | not 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> | |
| 406 | conversions between floating-point formats and decimal or hexadecimal character | |
| 407 | sequences; | |
| 408 | <LI> | |
| 409 | all &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 | |
| 411 | manipulation of the floating-point sign bit); and | |
| 412 | <LI> | |
| 413 | all &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> | |
| 421 | Because the <NOBR>80-bit</NOBR> double-extended-precision format, | |
| 422 | <CODE>extFloat80_t</CODE>, stores an explicit leading significand bit, many | |
| 423 | finite floating-point numbers are encodable in this type in multiple equivalent | |
| 424 | forms. | |
| 425 | Of these multiple encodings, there is always a unique one with the least | |
| 426 | encoded exponent value, and this encoding is considered the <I>canonical</I> | |
| 427 | representation of the floating-point number. | |
| 428 | Any other equivalent representations (having a higher encoded exponent value) | |
| 429 | are <I>non-canonical</I>. | |
| 430 | For a value in the subnormal range (including zero), the canonical | |
| 431 | representation always has an encoded exponent of zero and a leading significand | |
| 432 | bit <NOBR>of 0</NOBR>. | |
| 433 | For finite values outside the subnormal range, the canonical representation | |
| 434 | always has an encoded exponent that is nonzero and a leading significand bit | |
| 435 | <NOBR>of 1</NOBR>. | |
| 436 | </P> | |
| 437 | ||
| 438 | <P> | |
| 439 | For an infinity or NaN, the leading significand bit is similarly expected to | |
| 440 | <NOBR>be 1</NOBR>. | |
| 441 | An infinity or NaN with a leading significand bit <NOBR>of 0</NOBR> is again | |
| 442 | considered non-canonical. | |
| 443 | Hence, altogether, to be canonical, a value of type <CODE>extFloat80_t</CODE> | |
| 444 | must have a leading significand bit <NOBR>of 1</NOBR>, unless the value is | |
| 445 | subnormal or zero, in which case the leading significand bit and the encoded | |
| 446 | exponent must both be zero. | |
| 447 | </P> | |
| 448 | ||
| 449 | <P> | |
| 450 | SoftFloat&rsquo;s functions are not guaranteed to operate as expected when | |
| 451 | inputs of type <CODE>extFloat80_t</CODE> are non-canonical. | |
| 452 | Assuming all of a function&rsquo;s <CODE>extFloat80_t</CODE> inputs (if any) | |
| 453 | are canonical, function outputs of type <CODE>extFloat80_t</CODE> will always | |
| 454 | be canonical. | |
| 455 | </P> | |
| 456 | ||
| 457 | <H3>4.5. Conventions for Passing Arguments and Results</H3> | |
| 458 | ||
| 459 | <P> | |
| 460 | Values 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 | |
| 462 | cases passed as function arguments by value. | |
| 463 | Likewise, when an output of a function is no more than <NOBR>64 bits</NOBR>, it | |
| 464 | is always returned directly as the function result. | |
| 465 | Thus, for example, the SoftFloat function for adding two <NOBR>64-bit</NOBR> | |
| 466 | floating-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> | |
| 473 | The story is more complex when function inputs and outputs are | |
| 474 | <NOBR>80-bit</NOBR> and <NOBR>128-bit</NOBR> floating-point. | |
| 475 | For these types, SoftFloat always provides a function that passes these larger | |
| 476 | values into or out of the function indirectly, via pointers. | |
| 477 | For example, for adding two <NOBR>128-bit</NOBR> floating-point values, | |
| 478 | SoftFloat supplies this function: | |
| 479 | <BLOCKQUOTE> | |
| 480 | <CODE>void f128M_add( const float128_t *, const float128_t *, float128_t * );</CODE> | |
| 481 | </BLOCKQUOTE> | |
| 482 | The first two arguments point to the values to be added, and the last argument | |
| 483 | points to the location where the sum will be stored. | |
| 484 | The <CODE>M</CODE> in the name <CODE>f128M_add</CODE> is mnemonic for the fact | |
| 485 | that the <NOBR>128-bit</NOBR> inputs and outputs are &ldquo;in memory&rdquo;, | |
| 486 | pointed to by pointer arguments. | |
| 487 | </P> | |
| 488 | ||
| 489 | <P> | |
| 490 | All ports of SoftFloat implement these <I>pass-by-pointer</I> functions for | |
| 491 | types <CODE>extFloat80_t</CODE> and <CODE>float128_t</CODE>. | |
| 492 | At the same time, SoftFloat ports may also implement alternate versions of | |
| 493 | these same functions that pass <CODE>extFloat80_t</CODE> and | |
| 494 | <CODE>float128_t</CODE> by value, like the smaller formats. | |
| 495 | Thus, besides the function with name <CODE>f128M_add</CODE> shown above, a | |
| 496 | SoftFloat 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> | |
| 503 | As 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> | |
| 506 | and <CODE>float128_t</CODE>, because passing such large types directly can have | |
| 507 | significant extra cost. | |
| 508 | On computers where the word size is <NOBR>64 bits</NOBR> or larger, both | |
| 509 | function versions (<CODE>f128M_add</CODE> and <CODE>f128_add</CODE>) are | |
| 510 | provided, because the cost of passing by value is then more reasonable. | |
| 511 | Applications that must be portable accross both classes of computers must use | |
| 512 | the pointer-based functions, as these are always implemented. | |
| 513 | However, if it is known that SoftFloat includes the by-value functions for all | |
| 514 | platforms of interest, programmers can use whichever version they prefer. | |
| 515 | </P> | |
| 516 | ||
| 517 | ||
| 518 | <H2>5. Reserved Names</H2> | |
| 519 | ||
| 520 | <P> | |
| 521 | In addition to the variables and functions documented here, SoftFloat defines | |
| 522 | some symbol names for its own private use. | |
| 523 | These private names always begin with the prefix | |
| 524 | &lsquo;<CODE>softfloat_</CODE>&rsquo;. | |
| 525 | When a program includes header <CODE>softfloat.h</CODE> or links with the | |
| 526 | SoftFloat library, all names with prefix &lsquo;<CODE>softfloat_</CODE>&rsquo; | |
| 527 | are reserved for possible use by SoftFloat. | |
| 528 | Applications that use SoftFloat should not define their own names with this | |
| 529 | prefix, and should reference only such names as are documented. | |
| 530 | </P> | |
| 531 | ||
| 532 | ||
| 533 | <H2>6. Mode Variables</H2> | |
| 534 | ||
| 535 | <P> | |
| 536 | The following global variables control rounding mode, underflow detection, and | |
| 537 | the <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> | |
| 543 | These mode variables are covered in the next several subsections. | |
| 544 | For some SoftFloat ports, these variables may be <I>per-thread</I> (declared | |
| 545 | <CODE>thread_local</CODE>), meaning that different execution threads have their | |
| 546 | own separate copies of the variables. | |
| 547 | </P> | |
| 548 | ||
| 549 | <H3>6.1. Rounding Mode</H3> | |
| 550 | ||
| 551 | <P> | |
| 552 | All five rounding modes defined by the 2008 IEEE Floating-Point Standard are | |
| 553 | implemented for all operations that require rounding. | |
| 554 | Some ports of SoftFloat may also implement the <I>round-to-odd</I> mode. | |
| 555 | </P> | |
| 556 | ||
| 557 | <P> | |
| 558 | The rounding mode is selected by the global variable | |
| 559 | <BLOCKQUOTE> | |
| 560 | <CODE>uint_fast8_t softfloat_roundingMode;</CODE> | |
| 561 | </BLOCKQUOTE> | |
| 562 | This 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> | |
| 591 | Variable <CODE>softfloat_roundingMode</CODE> is initialized to | |
| 592 | <CODE>softfloat_round_near_even</CODE>. | |
| 593 | </P> | |
| 594 | ||
| 595 | <P> | |
| 596 | When <CODE>softfloat_round_odd</CODE> is the rounding mode for a function that | |
| 597 | rounds 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 | |
| 599 | integer, the rounded result is the closest <EM>odd</EM> integer. | |
| 600 | For other operations, this rounding mode acts as though the floating-point | |
| 601 | result is first rounded to minimum magnitude, the same as | |
| 602 | <CODE>softfloat_round_minMag</CODE>, and then, if the result is inexact, the | |
| 603 | least-significant bit of the result is set <NOBR>to 1</NOBR>. | |
| 604 | Rounding to odd is also known as <EM>jamming</EM>. | |
| 605 | </P> | |
| 606 | ||
| 607 | <H3>6.2. Underflow Detection</H3> | |
| 608 | ||
| 609 | <P> | |
| 610 | In the terminology of the IEEE Standard, SoftFloat can detect tininess for | |
| 611 | underflow either before or after rounding. | |
| 612 | The choice is made by the global variable | |
| 613 | <BLOCKQUOTE> | |
| 614 | <CODE>uint_fast8_t softfloat_detectTininess;</CODE> | |
| 615 | </BLOCKQUOTE> | |
| 616 | which can be set to either | |
| 617 | <BLOCKQUOTE> | |
| 618 | <CODE>softfloat_tininess_beforeRounding</CODE><BR> | |
| 619 | <CODE>softfloat_tininess_afterRounding</CODE> | |
| 620 | </BLOCKQUOTE> | |
| 621 | Detecting tininess after rounding is usually better because it results in fewer | |
| 622 | spurious underflow signals. | |
| 623 | The other option is provided for compatibility with some systems. | |
| 624 | Like most systems (and as required by the newer 2008 IEEE Standard), SoftFloat | |
| 625 | always 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> | |
| 631 | For <CODE>extFloat80_t</CODE> only, the rounding precision of the basic | |
| 632 | arithmetic operations is controlled by the global variable | |
| 633 | <BLOCKQUOTE> | |
| 634 | <CODE>uint_fast8_t extF80_roundingPrecision;</CODE> | |
| 635 | </BLOCKQUOTE> | |
| 636 | The 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> | |
| 644 | When <CODE>extF80_roundingPrecision</CODE> is set to its default value of 80, | |
| 645 | these operations are rounded to the full precision of the <NOBR>80-bit</NOBR> | |
| 646 | double-extended-precision format, like occurs for other formats. | |
| 647 | Setting <CODE>extF80_roundingPrecision</CODE> to 32 or to 64 causes the | |
| 648 | operations 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. | |
| 651 | When rounding to reduced precision, additional bits in the result significand | |
| 652 | beyond the rounding point are set to zero. | |
| 653 | The consequences of setting <CODE>extF80_roundingPrecision</CODE> to a value | |
| 654 | other than 32, 64, or 80 is not specified. | |
| 655 | Operations 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> | |
| 663 | All five exception flags required by the IEEE Floating-Point Standard are | |
| 664 | implemented. | |
| 665 | Each flag is stored as a separate bit in the global variable | |
| 666 | <BLOCKQUOTE> | |
| 667 | <CODE>uint_fast8_t softfloat_exceptionFlags;</CODE> | |
| 668 | </BLOCKQUOTE> | |
| 669 | The positions of the exception flag bits within this variable are determined by | |
| 670 | the 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> | |
| 678 | Variable <CODE>softfloat_exceptionFlags</CODE> is initialized to all zeros, | |
| 679 | meaning no exceptions. | |
| 680 | </P> | |
| 681 | ||
| 682 | <P> | |
| 683 | For some SoftFloat ports, <CODE>softfloat_exceptionFlags</CODE> may be | |
| 684 | <I>per-thread</I> (declared <CODE>thread_local</CODE>), meaning that different | |
| 685 | execution threads have their own separate instances of it. | |
| 686 | </P> | |
| 687 | ||
| 688 | <P> | |
| 689 | An 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> | |
| 693 | where <CODE>&lt;<I>exception</I>&gt;</CODE> is the appropriate name. | |
| 694 | To raise a floating-point exception, function <CODE>softfloat_raiseFlags</CODE> | |
| 695 | should normally be used. | |
| 696 | </P> | |
| 697 | ||
| 698 | <P> | |
| 699 | When SoftFloat detects an exception other than <I>inexact</I>, it calls | |
| 700 | <CODE>softfloat_raiseFlags</CODE>. | |
| 701 | The default version of this function simply raises the corresponding exception | |
| 702 | flags. | |
| 703 | Particular ports of SoftFloat may support alternate behavior, such as exception | |
| 704 | traps, by modifying the default <CODE>softfloat_raiseFlags</CODE>. | |
| 705 | A program may also supply its own <CODE>softfloat_raiseFlags</CODE> function to | |
| 706 | override the one from the SoftFloat library. | |
| 707 | </P> | |
| 708 | ||
| 709 | <P> | |
| 710 | Because inexact results occur frequently under most circumstances (and thus are | |
| 711 | hardly exceptional), SoftFloat does not ordinarily call | |
| 712 | <CODE>softfloat_raiseFlags</CODE> for <I>inexact</I> exceptions. | |
| 713 | It does always raise the <I>inexact</I> exception flag as required. | |
| 714 | </P> | |
| 715 | ||
| 716 | ||
| 717 | <H2>8. Function Details</H2> | |
| 718 | ||
| 719 | <P> | |
| 720 | In this section, <CODE>&lt;<I>float</I>&gt;</CODE> appears in function names as | |
| 721 | a 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> | |
| 754 | The circumstances under which values of floating-point types | |
| 755 | <CODE>extFloat80_t</CODE> and <CODE>float128_t</CODE> may be passed either by | |
| 756 | value 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> | |
| 763 | All conversions from a <NOBR>32-bit</NOBR> or <NOBR>64-bit</NOBR> integer, | |
| 764 | signed or unsigned, to a floating-point format are supported. | |
| 765 | Functions 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> | |
| 772 | Conversions from <NOBR>32-bit</NOBR> integers to <NOBR>64-bit</NOBR> | |
| 773 | double-precision and larger formats are always exact, and likewise conversions | |
| 774 | from <NOBR>64-bit</NOBR> integers to <NOBR>80-bit</NOBR> | |
| 775 | double-extended-precision and <NOBR>128-bit</NOBR> quadruple-precision are also | |
| 776 | always exact. | |
| 777 | </P> | |
| 778 | ||
| 779 | <P> | |
| 780 | Each conversion function takes one input of the appropriate type and generates | |
| 781 | one output. | |
| 782 | The following illustrates the signatures of these functions in cases when the | |
| 783 | floating-point result is passed either by value or via pointers: | |
| 784 | <BLOCKQUOTE> | |
| 785 | <PRE> | |
| 786 | float64_t i32_to_f64( int32_t <I>a</I> ); | |
| 787 | </PRE> | |
| 788 | <PRE> | |
| 789 | void 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> | |
| 797 | Conversions 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 | |
| 799 | functions: | |
| 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> | |
| 806 | The functions have signatures as follows, depending on whether the | |
| 807 | floating-point input is passed by value or via pointers: | |
| 808 | <BLOCKQUOTE> | |
| 809 | <PRE> | |
| 810 | int_fast32_t f64_to_i32( float64_t <I>a</I>, uint_fast8_t <I>roundingMode</I>, bool <I>exact</I> ); | |
| 811 | </PRE> | |
| 812 | <PRE> | |
| 813 | int_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> | |
| 820 | The <CODE><I>roundingMode</I></CODE> argument specifies the rounding mode for | |
| 821 | the conversion. | |
| 822 | The variable that usually indicates rounding mode, | |
| 823 | <CODE>softfloat_roundingMode</CODE>, is ignored. | |
| 824 | Argument <CODE><I>exact</I></CODE> determines whether the <I>inexact</I> | |
| 825 | exception flag is raised if the conversion is not exact. | |
| 826 | If <CODE><I>exact</I></CODE> is <CODE>true</CODE>, the <I>inexact</I> flag may | |
| 827 | be raised; | |
| 828 | otherwise, it will not be, even if the conversion is inexact. | |
| 829 | </P> | |
| 830 | ||
| 831 | <P> | |
| 832 | A conversion from floating-point to integer format raises the <I>invalid</I> | |
| 833 | exception if the source value cannot be rounded to a representable integer of | |
| 834 | the desired size (32 or 64 bits). | |
| 835 | In such circumstances, the integer result returned is determined by the | |
| 836 | particular port of SoftFloat, although typically this value will be either the | |
| 837 | maximum or minimum value of the integer format. | |
| 838 | The functions that convert to integer types never raise the floating-point | |
| 839 | <I>overflow</I> exception. | |
| 840 | </P> | |
| 841 | ||
| 842 | <P> | |
| 843 | Because languages such <NOBR>as C</NOBR> require that conversions to integers | |
| 844 | be rounded toward zero, the following functions are provided for improved speed | |
| 845 | and 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> | |
| 852 | These functions round only toward zero (to minimum magnitude). | |
| 853 | The signatures for these functions are the same as above without the redundant | |
| 854 | <CODE><I>roundingMode</I></CODE> argument: | |
| 855 | <BLOCKQUOTE> | |
| 856 | <PRE> | |
| 857 | int_fast32_t f64_to_i32_r_minMag( float64_t <I>a</I>, bool <I>exact</I> ); | |
| 858 | </PRE> | |
| 859 | <PRE> | |
| 860 | int_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> | |
| 868 | Conversions between floating-point formats are done by functions with these | |
| 869 | names: | |
| 870 | <BLOCKQUOTE> | |
| 871 | <CODE>&lt;<I>float</I>&gt;_to_&lt;<I>float</I>&gt;</CODE> | |
| 872 | </BLOCKQUOTE> | |
| 873 | All combinations of source and result type are supported where the source and | |
| 874 | result are different formats. | |
| 875 | There are four different styles of signature for these functions, depending on | |
| 876 | whether the input and the output floating-point values are passed by value or | |
| 877 | via pointers: | |
| 878 | <BLOCKQUOTE> | |
| 879 | <PRE> | |
| 880 | float32_t f64_to_f32( float64_t <I>a</I> ); | |
| 881 | </PRE> | |
| 882 | <PRE> | |
| 883 | float32_t f128M_to_f32( const float128_t *<I>aPtr</I> ); | |
| 884 | </PRE> | |
| 885 | <PRE> | |
| 886 | void f32_to_f128M( float32_t <I>a</I>, float128_t *<I>destPtr</I> ); | |
| 887 | </PRE> | |
| 888 | <PRE> | |
| 889 | void extF80M_to_f128M( const extFloat80_t *<I>aPtr</I>, float128_t *<I>destPtr</I> ); | |
| 890 | </PRE> | |
| 891 | </BLOCKQUOTE> | |
| 892 | </P> | |
| 893 | ||
| 894 | <P> | |
| 895 | Conversions from a smaller to a larger floating-point format are always exact | |
| 896 | and so require no rounding. | |
| 897 | </P> | |
| 898 | ||
| 899 | <H3>8.4. Basic Arithmetic Functions</H3> | |
| 900 | ||
| 901 | <P> | |
| 902 | The 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> | |
| 910 | Each floating-point operation takes two operands, except for <CODE>sqrt</CODE> | |
| 911 | (square root) which takes only one. | |
| 912 | The operands and result are all of the same floating-point format. | |
| 913 | Signatures for these functions take the following forms: | |
| 914 | <BLOCKQUOTE> | |
| 915 | <PRE> | |
| 916 | float64_t f64_add( float64_t <I>a</I>, float64_t <I>b</I> ); | |
| 917 | </PRE> | |
| 918 | <PRE> | |
| 919 | void | |
| 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> | |
| 924 | float64_t f64_sqrt( float64_t <I>a</I> ); | |
| 925 | </PRE> | |
| 926 | <PRE> | |
| 927 | void f128M_sqrt( const float128_t *<I>aPtr</I>, float128_t *<I>destPtr</I> ); | |
| 928 | </PRE> | |
| 929 | </BLOCKQUOTE> | |
| 930 | When 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 | |
| 932 | operands, and the last argument, <CODE><I>destPtr</I></CODE>, points to the | |
| 933 | location where the result is stored. | |
| 934 | </P> | |
| 935 | ||
| 936 | <P> | |
| 937 | Rounding 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> | |
| 947 | The 2008 version of the IEEE Floating-Point Standard defines a <I>fused | |
| 948 | multiply-add</I> operation that does a combined multiplication and addition | |
| 949 | with only a single rounding. | |
| 950 | SoftFloat implements fused multiply-add with functions | |
| 951 | <BLOCKQUOTE> | |
| 952 | <CODE>&lt;<I>float</I>&gt;_mulAdd</CODE> | |
| 953 | </BLOCKQUOTE> | |
| 954 | Unlike 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> | |
| 960 | Depending on whether floating-point values are passed by value or via pointers, | |
| 961 | the fused multiply-add functions have signatures of these forms: | |
| 962 | <BLOCKQUOTE> | |
| 963 | <PRE> | |
| 964 | float64_t f64_mulAdd( float64_t <I>a</I>, float64_t <I>b</I>, float64_t <I>c</I> ); | |
| 965 | </PRE> | |
| 966 | <PRE> | |
| 967 | void | |
| 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> | |
| 976 | The functions compute | |
| 977 | <NOBR>(<CODE><I>a</I></CODE> &times; <CODE><I>b</I></CODE>) | |
| 978 | + <CODE><I>c</I></CODE></NOBR> | |
| 979 | with a single rounding. | |
| 980 | When 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> | |
| 988 | If 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 | |
| 990 | the 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> | |
| 996 | For each format, SoftFloat implements the remainder operation defined by the | |
| 997 | IEEE Floating-Point Standard. | |
| 998 | The remainder functions have names | |
| 999 | <BLOCKQUOTE> | |
| 1000 | <CODE>&lt;<I>float</I>&gt;_rem</CODE> | |
| 1001 | </BLOCKQUOTE> | |
| 1002 | Each remainder operation takes two floating-point operands of the same format | |
| 1003 | and returns a result in the same format. | |
| 1004 | Depending on whether floating-point values are passed by value or via pointers, | |
| 1005 | the remainder functions have signatures of these forms: | |
| 1006 | <BLOCKQUOTE> | |
| 1007 | <PRE> | |
| 1008 | float64_t f64_rem( float64_t <I>a</I>, float64_t <I>b</I> ); | |
| 1009 | </PRE> | |
| 1010 | <PRE> | |
| 1011 | void | |
| 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> | |
| 1016 | When 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> | |
| 1023 | The 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>, | |
| 1026 | where <I>n</I> is the integer closest to | |
| 1027 | <NOBR><CODE><I>a</I></CODE> &divide; <CODE><I>b</I></CODE></NOBR>. | |
| 1028 | If <NOBR><CODE><I>a</I></CODE> &divide; <CODE><I>b</I></CODE></NOBR> is exactly | |
| 1029 | halfway 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>. | |
| 1031 | The IEEE Standard&rsquo;s remainder operation is always exact and so requires | |
| 1032 | no rounding. | |
| 1033 | </P> | |
| 1034 | ||
| 1035 | <P> | |
| 1036 | Depending on the relative magnitudes of the operands, the remainder | |
| 1037 | functions can take considerably longer to execute than the other SoftFloat | |
| 1038 | functions. | |
| 1039 | This is an inherent characteristic of the remainder operation itself and is not | |
| 1040 | a flaw in the SoftFloat implementation. | |
| 1041 | </P> | |
| 1042 | ||
| 1043 | <H3>8.7. Round-to-Integer Functions</H3> | |
| 1044 | ||
| 1045 | <P> | |
| 1046 | For each format, SoftFloat implements the round-to-integer operation specified | |
| 1047 | by the IEEE Floating-Point Standard. | |
| 1048 | These functions are named | |
| 1049 | <BLOCKQUOTE> | |
| 1050 | <CODE>&lt;<I>float</I>&gt;_roundToInt</CODE> | |
| 1051 | </BLOCKQUOTE> | |
| 1052 | Each round-to-integer operation takes a single floating-point operand. | |
| 1053 | This operand is rounded to an integer according to a specified rounding mode, | |
| 1054 | and 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> | |
| 1059 | The signatures of the round-to-integer functions are similar to those for | |
| 1060 | conversions to an integer type: | |
| 1061 | <BLOCKQUOTE> | |
| 1062 | <PRE> | |
| 1063 | float64_t f64_roundToInt( float64_t <I>a</I>, uint_fast8_t <I>roundingMode</I>, bool <I>exact</I> ); | |
| 1064 | </PRE> | |
| 1065 | <PRE> | |
| 1066 | void | |
| 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> | |
| 1075 | When 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> | |
| 1081 | The <CODE><I>roundingMode</I></CODE> argument specifies the rounding mode to | |
| 1082 | apply. | |
| 1083 | The variable that usually indicates rounding mode, | |
| 1084 | <CODE>softfloat_roundingMode</CODE>, is ignored. | |
| 1085 | Argument <CODE><I>exact</I></CODE> determines whether the <I>inexact</I> | |
| 1086 | exception flag is raised if the conversion is not exact. | |
| 1087 | If <CODE><I>exact</I></CODE> is <CODE>true</CODE>, the <I>inexact</I> flag may | |
| 1088 | be raised; | |
| 1089 | otherwise, it will not be, even if the conversion is inexact. | |
| 1090 | </P> | |
| 1091 | ||
| 1092 | <H3>8.8. Comparison Functions</H3> | |
| 1093 | ||
| 1094 | <P> | |
| 1095 | For each format, the following floating-point comparison functions are | |
| 1096 | provided: | |
| 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> | |
| 1102 | Each comparison takes two operands of the same type and returns a Boolean. | |
| 1103 | The abbreviation <CODE>eq</CODE> stands for &ldquo;equal&rdquo; (=); | |
| 1104 | <CODE>le</CODE> stands for &ldquo;less than or equal&rdquo; (&le;); | |
| 1105 | and <CODE>lt</CODE> stands for &ldquo;less than&rdquo; (&lt;). | |
| 1106 | Depending on whether the floating-point operands are passed by value or via | |
| 1107 | pointers, the comparison functions have signatures of these forms: | |
| 1108 | <BLOCKQUOTE> | |
| 1109 | <PRE> | |
| 1110 | bool f64_eq( float64_t <I>a</I>, float64_t <I>b</I> ); | |
| 1111 | </PRE> | |
| 1112 | <PRE> | |
| 1113 | bool f128M_eq( const float128_t *<I>aPtr</I>, const float128_t *<I>bPtr</I> ); | |
| 1114 | </PRE> | |
| 1115 | </BLOCKQUOTE> | |
| 1116 | </P> | |
| 1117 | ||
| 1118 | <P> | |
| 1119 | The usual greater-than (&gt;), greater-than-or-equal (&ge;), and not-equal | |
| 1120 | (&ne;) comparisons are easily obtained from the functions provided. | |
| 1121 | The not-equal function is just the logical complement of the equal function. | |
| 1122 | The greater-than-or-equal function is identical to the less-than-or-equal | |
| 1123 | function with the arguments in reverse order, and likewise the greater-than | |
| 1124 | function is identical to the less-than function with the arguments reversed. | |
| 1125 | </P> | |
| 1126 | ||
| 1127 | <P> | |
| 1128 | The IEEE Floating-Point Standard specifies that the less-than-or-equal and | |
| 1129 | less-than comparisons by default raise the <I>invalid</I> exception if either | |
| 1130 | operand is any kind of NaN. | |
| 1131 | Equality comparisons, on the other hand, are defined by default to raise the | |
| 1132 | <I>invalid</I> exception only for signaling NaNs, not quiet NaNs. | |
| 1133 | For 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> | |
| 1139 | The <CODE>signaling</CODE> equality comparisons are identical to the default | |
| 1140 | equality comparisons except that the <I>invalid</I> exception is raised for any | |
| 1141 | NaN input, not just for signaling NaNs. | |
| 1142 | Similarly, the <CODE>quiet</CODE> comparison functions are identical to their | |
| 1143 | default counterparts except that the <I>invalid</I> exception is not raised for | |
| 1144 | quiet NaNs. | |
| 1145 | </P> | |
| 1146 | ||
| 1147 | <H3>8.9. Signaling NaN Test Functions</H3> | |
| 1148 | ||
| 1149 | <P> | |
| 1150 | Functions for testing whether a floating-point value is a signaling NaN are | |
| 1151 | provided with these names: | |
| 1152 | <BLOCKQUOTE> | |
| 1153 | <CODE>&lt;<I>float</I>&gt;_isSignalingNaN</CODE> | |
| 1154 | </BLOCKQUOTE> | |
| 1155 | The functions take one floating-point operand and return a Boolean indicating | |
| 1156 | whether the operand is a signaling NaN. | |
| 1157 | Accordingly, the functions have the forms | |
| 1158 | <BLOCKQUOTE> | |
| 1159 | <PRE> | |
| 1160 | bool f64_isSignalingNaN( float64_t <I>a</I> ); | |
| 1161 | </PRE> | |
| 1162 | <PRE> | |
| 1163 | bool 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> | |
| 1171 | SoftFloat provides a single function for raising floating-point exceptions: | |
| 1172 | <BLOCKQUOTE> | |
| 1173 | <PRE> | |
| 1174 | void softfloat_raiseFlags( uint_fast8_t <I>exceptions</I> ); | |
| 1175 | </PRE> | |
| 1176 | </BLOCKQUOTE> | |
| 1177 | The <CODE><I>exceptions</I></CODE> argument is a mask indicating the set of | |
| 1178 | exceptions to raise. | |
| 1179 | (See earlier section 7, <I>Exceptions and Exception Flags</I>.) | |
| 1180 | In addition to setting the specified exception flags in variable | |
| 1181 | <CODE>softfloat_exceptionFlags</CODE>, the <CODE>softfloat_raiseFlags</CODE> | |
| 1182 | function 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> | |
| 1189 | Apart from a change in the legal use license, <NOBR>Release 3</NOBR> of | |
| 1190 | SoftFloat introduced numerous technical differences compared to earlier | |
| 1191 | releases. | |
| 1192 | </P> | |
| 1193 | ||
| 1194 | <H3>9.1. Name Changes</H3> | |
| 1195 | ||
| 1196 | <P> | |
| 1197 | The most obvious and pervasive difference compared to <NOBR>Release 2</NOBR> | |
| 1198 | is that the names of most functions and variables have changed, even when the | |
| 1199 | behavior has not. | |
| 1200 | First, the floating-point types, the mode variables, the exception flags | |
| 1201 | variable, the function to raise exceptions, and various associated constants | |
| 1202 | have 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> | |
| 1294 | Furthermore, <NOBR>Release 3</NOBR> adopted the following new abbreviations for | |
| 1295 | function 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> | |
| 1310 | Thus, for example, the function to add two <NOBR>32-bit</NOBR> floating-point | |
| 1311 | numbers, previously called <CODE>float32_add</CODE> in <NOBR>Release 2</NOBR>, | |
| 1312 | is now <CODE>f32_add</CODE>. | |
| 1313 | Lastly, 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> | |
| 1343 | Besides simple name changes, some operations were given a different interface | |
| 1344 | in <NOBR>Release 3</NOBR> than they had in <NOBR>Release 2</NOBR>: | |
| 1345 | <UL> | |
| 1346 | ||
| 1347 | <LI> | |
| 1348 | <P> | |
| 1349 | Since <NOBR>Release 3</NOBR>, integer arguments and results of functions have | |
| 1350 | standard types from header <CODE>&lt;stdint.h&gt;</CODE>, such as | |
| 1351 | <CODE>uint32_t</CODE>, whereas previously their types could be defined | |
| 1352 | differently for each port of SoftFloat, usually using traditional C types such | |
| 1353 | as <CODE>unsigned</CODE> <CODE>int</CODE>. | |
| 1354 | Likewise, functions in <NOBR>Release 3</NOBR> and later pass Booleans as | |
| 1355 | standard type <CODE>bool</CODE> from <CODE>&lt;stdbool.h&gt;</CODE>, whereas | |
| 1356 | previously these were again passed as a port-specific type (usually | |
| 1357 | <CODE>int</CODE>). | |
| 1358 | </P> | |
| 1359 | ||
| 1360 | <LI> | |
| 1361 | <P> | |
| 1362 | As explained earlier in <NOBR>section 4.5</NOBR>, <I>Conventions for Passing | |
| 1363 | Arguments and Results</I>, SoftFloat functions in <NOBR>Release 3</NOBR> and | |
| 1364 | later may pass <NOBR>80-bit</NOBR> and <NOBR>128-bit</NOBR> floating-point | |
| 1365 | values through pointers, meaning that functions take pointer arguments and then | |
| 1366 | read or write floating-point values at the locations indicated by the pointers. | |
| 1367 | In <NOBR>Release 2</NOBR>, floating-point arguments and results were always | |
| 1368 | passed by value, regardless of their size. | |
| 1369 | </P> | |
| 1370 | ||
| 1371 | <LI> | |
| 1372 | <P> | |
| 1373 | Functions that round to an integer have additional | |
| 1374 | <CODE><I>roundingMode</I></CODE> and <CODE><I>exact</I></CODE> arguments that | |
| 1375 | they did not have in <NOBR>Release 2</NOBR>. | |
| 1376 | Refer to sections 8.2 <NOBR>and 8.7</NOBR> for descriptions of these functions | |
| 1377 | since <NOBR>Release 3</NOBR>. | |
| 1378 | For <NOBR>Release 2</NOBR>, the rounding mode, when needed, was taken from the | |
| 1379 | same 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>). | |
| 1382 | Also, for <NOBR>Release 2</NOBR>, if the original floating-point input was not | |
| 1383 | an exact integer value, and if the <I>invalid</I> exception was not raised by | |
| 1384 | the 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 | |
| 1386 | case. | |
| 1387 | Applications using SoftFloat <NOBR>Release 3</NOBR> or later can get the same | |
| 1388 | effect 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> | |
| 1400 | With <NOBR>Release 3</NOBR>, some new features have been added that were not | |
| 1401 | present in <NOBR>Release 2</NOBR>: | |
| 1402 | <UL> | |
| 1403 | ||
| 1404 | <LI> | |
| 1405 | <P> | |
| 1406 | A 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>. | |
| 1411 | This 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 | |
| 1416 | SoftFloat&rsquo;s floating-point types this way, depending on the platform and | |
| 1417 | the applications using SoftFloat. | |
| 1418 | Ports of SoftFloat may choose to forgo the convenience in favor of better | |
| 1419 | speed.) | |
| 1420 | </P> | |
| 1421 | ||
| 1422 | <P> | |
| 1423 | <LI> | |
| 1424 | As 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> | |
| 1430 | Functions have been added for converting between the floating-point types and | |
| 1431 | unsigned integers. | |
| 1432 | <NOBR>Release 2</NOBR> supported only signed integers, not unsigned. | |
| 1433 | </P> | |
| 1434 | ||
| 1435 | <P> | |
| 1436 | <LI> | |
| 1437 | Fused multiply-add functions have been added for all floating-point formats | |
| 1438 | except <NOBR>80-bit</NOBR> double-extended-precision, | |
| 1439 | <CODE>extFloat80_t</CODE>. | |
| 1440 | </P> | |
| 1441 | ||
| 1442 | <P> | |
| 1443 | <LI> | |
| 1444 | New rounding modes are supported: | |
| 1445 | <CODE>softfloat_round_near_maxMag</CODE> (round to nearest, with ties to | |
| 1446 | maximum magnitude, away from zero), and, as of <NOBR>Release 3c</NOBR>, | |
| 1447 | optional <CODE>softfloat_round_odd</CODE> (round to odd, also known as | |
| 1448 | jamming). | |
| 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 | |
| 1458 | Standard&rsquo;s rules for portability. | |
| 1459 | For example, older releases of SoftFloat employed type conversions in ways | |
| 1460 | that, while commonly practiced, are not fully defined by the C Standard. | |
| 1461 | Such problematic type conversions have generally been replaced by the use of | |
| 1462 | unions, 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> | |
| 1468 | Starting with <NOBR>Release 3</NOBR>, SoftFloat now builds as a library. | |
| 1469 | Previously, SoftFloat compiled into a single, monolithic object file containing | |
| 1470 | all the SoftFloat functions, with the consequence that a program linking with | |
| 1471 | SoftFloat would get every SoftFloat function in its binary file even if only a | |
| 1472 | few functions were actually used. | |
| 1473 | With SoftFloat in the form of a library, a program that is linked by a standard | |
| 1474 | linker will include only those functions of SoftFloat that it needs and no | |
| 1475 | others. | |
| 1476 | </P> | |
| 1477 | ||
| 1478 | <H3>9.6. Optimization Gains (and Losses)</H3> | |
| 1479 | ||
| 1480 | <P> | |
| 1481 | Individual SoftFloat functions have been variously improved in | |
| 1482 | <NOBR>Release 3</NOBR> compared to earlier releases. | |
| 1483 | In particular, better, faster algorithms have been deployed for the operations | |
| 1484 | of division, square root, and remainder. | |
| 1485 | For 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> | |
| 1491 | However, because <NOBR>Release 2</NOBR> compiled all of SoftFloat together as a | |
| 1492 | single object file, compilers could make optimizations across function calls | |
| 1493 | when one SoftFloat function calls another. | |
| 1494 | Now that the functions of SoftFloat are compiled separately and only afterward | |
| 1495 | linked together into a program, there is not usually the same opportunity to | |
| 1496 | optimize across function calls. | |
| 1497 | Some loss of speed has been observed due to this change. | |
| 1498 | </P> | |
| 1499 | ||
| 1500 | ||
| 1501 | <H2>10. Future Directions</H2> | |
| 1502 | ||
| 1503 | <P> | |
| 1504 | The following improvements are anticipated for future releases of SoftFloat: | |
| 1505 | <UL> | |
| 1506 | <LI> | |
| 1507 | more functions from the 2008 version of the IEEE Floating-Point Standard; | |
| 1508 | <LI> | |
| 1509 | consistent, defined behavior for non-canonical representations of extended | |
| 1510 | format <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> | |
| 1520 | At the time of this writing, the most up-to-date information about SoftFloat | |
| 1521 | and 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 44 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 45 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 47 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 47 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 46 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 49 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 49 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 51 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 50 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 53 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 52 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 53 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 46 | void 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 | ||
| 4 | This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2018 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 76 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 103 | void 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 | *----------------------------------------------------------------------------*/ | |
| 109 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 117 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 138 | void 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 | *----------------------------------------------------------------------------*/ | |
| 144 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 152 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 173 | void 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 | *----------------------------------------------------------------------------*/ | |
| 179 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 187 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 218 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 227 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 238 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 267 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 275 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 286 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 307 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 316 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 326 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 349 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 358 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 369 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 44 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 45 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 47 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 47 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 46 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 49 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 49 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 51 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 50 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 53 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 52 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 53 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2018 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2018 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 46 | void 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 | ||
| 4 | This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2018 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 76 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 103 | void 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 | *----------------------------------------------------------------------------*/ | |
| 109 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 117 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 138 | void 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 | *----------------------------------------------------------------------------*/ | |
| 144 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 152 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 173 | void 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 | *----------------------------------------------------------------------------*/ | |
| 179 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 187 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 218 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 227 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 238 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 267 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 275 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 286 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 307 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 316 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 326 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 349 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 358 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 369 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 44 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 45 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 50 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 47 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 49 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 52 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 51 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 52 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 46 | void 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 | ||
| 4 | This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 76 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 110 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 145 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 180 | uint_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 | |
| 219 | INLINE | |
| 220 | struct 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 | |
| 228 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 240 | struct 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 | |
| 276 | INLINE | |
| 277 | struct 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 | |
| 285 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 297 | struct 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 | |
| 326 | INLINE | |
| 327 | void | |
| 328 | softfloat_commonNaNToExtF80M( | |
| 329 | const struct commonNaN *aPtr, struct extFloat80M *zSPtr ) | |
| 330 | { | |
| 331 | zSPtr->signExp = defaultNaNExtF80UI64; | |
| 332 | zSPtr->signif = defaultNaNExtF80UI0; | |
| 333 | } | |
| 334 | #else | |
| 335 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 346 | void | |
| 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 | |
| 378 | INLINE | |
| 379 | void | |
| 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 | |
| 388 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 400 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 44 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 45 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 47 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 47 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 46 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 49 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 49 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 51 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 50 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 48 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 53 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 52 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 53 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 50 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 46 | void 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 | ||
| 4 | This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 76 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 103 | void 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 | *----------------------------------------------------------------------------*/ | |
| 109 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 117 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 138 | void 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 | *----------------------------------------------------------------------------*/ | |
| 144 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 152 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 173 | void 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 | *----------------------------------------------------------------------------*/ | |
| 179 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 187 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 218 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 227 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 238 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 267 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 275 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 286 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 307 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 316 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 326 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 349 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 358 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 369 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void | |
| 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 | ||
| 85 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void | |
| 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 | ||
| 57 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | bool extF80M_eq( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | return extF80_eq( *aPtr, *bPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 45 | bool 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 | ||
| 54 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 45 | bool extF80M_le( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) | |
| 46 | { | |
| 47 | ||
| 48 | return extF80_le( *aPtr, *bPtr ); | |
| 49 | ||
| 50 | } | |
| 51 | ||
| 52 | #else | |
| 53 | ||
| 54 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | bool 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 | ||
| 55 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 45 | bool extF80M_lt( const extFloat80_t *aPtr, const extFloat80_t *bPtr ) | |
| 46 | { | |
| 47 | ||
| 48 | return extF80_lt( *aPtr, *bPtr ); | |
| 49 | ||
| 50 | } | |
| 51 | ||
| 52 | #else | |
| 53 | ||
| 54 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | bool 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 | ||
| 55 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void | |
| 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 | ||
| 57 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void | |
| 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 | ||
| 57 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void | |
| 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 | ||
| 61 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void extF80M_sqrt( const extFloat80_t *aPtr, extFloat80_t *zPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | *zPtr = extF80_sqrt( *aPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void | |
| 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 | ||
| 85 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void extF80M_to_f128M( const extFloat80_t *aPtr, float128_t *zPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | *zPtr = extF80_to_f128( *aPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | float16_t extF80M_to_f16( const extFloat80_t *aPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | return extF80_to_f16( *aPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | float32_t extF80M_to_f32( const extFloat80_t *aPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | return extF80_to_f32( *aPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | float64_t extF80M_to_f64( const extFloat80_t *aPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | return extF80_to_f64( *aPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | int_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 | ||
| 57 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | int_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 | ||
| 55 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | int_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 | ||
| 57 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | int_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 | ||
| 55 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | uint_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 | ||
| 57 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | uint_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 | ||
| 55 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | uint_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 | ||
| 57 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | uint_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 | ||
| 55 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 45 | void | |
| 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 | ||
| 83 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void | |
| 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 | ||
| 56 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | bool f128M_eq( const float128_t *aPtr, const float128_t *bPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | return f128_eq( *aPtr, *bPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | bool 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 | ||
| 55 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 45 | bool f128M_le( const float128_t *aPtr, const float128_t *bPtr ) | |
| 46 | { | |
| 47 | ||
| 48 | return f128_le( *aPtr, *bPtr ); | |
| 49 | ||
| 50 | } | |
| 51 | ||
| 52 | #else | |
| 53 | ||
| 54 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | bool 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 | ||
| 55 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 45 | bool f128M_lt( const float128_t *aPtr, const float128_t *bPtr ) | |
| 46 | { | |
| 47 | ||
| 48 | return f128_lt( *aPtr, *bPtr ); | |
| 49 | ||
| 50 | } | |
| 51 | ||
| 52 | #else | |
| 53 | ||
| 54 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | bool 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 | ||
| 55 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void | |
| 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 | ||
| 56 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void | |
| 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 | ||
| 72 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void | |
| 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 | ||
| 56 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void | |
| 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 | ||
| 61 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void f128M_sqrt( const float128_t *aPtr, float128_t *zPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | *zPtr = f128_sqrt( *aPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 45 | void | |
| 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 | ||
| 83 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void f128M_to_extF80M( const float128_t *aPtr, extFloat80_t *zPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | *zPtr = f128_to_extF80( *aPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | float16_t f128M_to_f16( const float128_t *aPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | return f128_to_f16( *aPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | float32_t f128M_to_f32( const float128_t *aPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | return f128_to_f32( *aPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | float64_t f128M_to_f64( const float128_t *aPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | return f128_to_f64( *aPtr ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | int_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 | ||
| 56 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | int_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 | ||
| 55 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | int_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 | ||
| 56 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | int_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 | ||
| 55 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | uint_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 | ||
| 56 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | uint_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 | ||
| 55 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | uint_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 | ||
| 56 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | uint_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 | ||
| 55 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extern const uint16_t softfloat_approxRecip_1k0s[]; | |
| 45 | extern const uint16_t softfloat_approxRecip_1k1s[]; | |
| 46 | ||
| 47 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extern const uint16_t softfloat_approxRecipSqrt_1k0s[]; | |
| 45 | extern const uint16_t softfloat_approxRecipSqrt_1k1s[]; | |
| 46 | ||
| 47 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void f16_to_extF80M( float16_t a, extFloat80_t *zPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | *zPtr = f16_to_extF80( a ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void f16_to_f128M( float16_t a, float128_t *zPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | *zPtr = f16_to_f128( a ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void f32_to_extF80M( float32_t a, extFloat80_t *zPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | *zPtr = f32_to_extF80( a ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void f32_to_f128M( float32_t a, float128_t *zPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | *zPtr = f32_to_f128( a ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void f64_to_extF80M( float64_t a, extFloat80_t *zPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | *zPtr = f64_to_extF80( a ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | void f64_to_f128M( float64_t a, float128_t *zPtr ) | |
| 47 | { | |
| 48 | ||
| 49 | *zPtr = f64_to_f128( a ); | |
| 50 | ||
| 51 | } | |
| 52 | ||
| 53 | #else | |
| 54 | ||
| 55 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void i32_to_extF80M( int32_t a, extFloat80_t *zPtr ) | |
| 45 | { | |
| 46 | ||
| 47 | *zPtr = i32_to_extF80( a ); | |
| 48 | ||
| 49 | } | |
| 50 | ||
| 51 | #else | |
| 52 | ||
| 53 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void i32_to_f128M( int32_t a, float128_t *zPtr ) | |
| 45 | { | |
| 46 | ||
| 47 | *zPtr = i32_to_f128( a ); | |
| 48 | ||
| 49 | } | |
| 50 | ||
| 51 | #else | |
| 52 | ||
| 53 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void i64_to_extF80M( int64_t a, extFloat80_t *zPtr ) | |
| 45 | { | |
| 46 | ||
| 47 | *zPtr = i64_to_extF80( a ); | |
| 48 | ||
| 49 | } | |
| 50 | ||
| 51 | #else | |
| 52 | ||
| 53 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void i64_to_f128M( int64_t a, float128_t *zPtr ) | |
| 45 | { | |
| 46 | ||
| 47 | *zPtr = i64_to_f128( a ); | |
| 48 | ||
| 49 | } | |
| 50 | ||
| 51 | #else | |
| 52 | ||
| 53 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 45 | union ui16_f16 { uint16_t ui; float16_t f; }; | |
| 46 | union ui32_f32 { uint32_t ui; float32_t f; }; | |
| 47 | union ui64_f64 { uint64_t ui; float64_t f; }; | |
| 48 | ||
| 49 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 50 | union extF80M_extF80 { struct extFloat80M fM; extFloat80_t f; }; | |
| 51 | union ui128_f128 { struct uint128 ui; float128_t f; }; | |
| 52 | #endif | |
| 53 | ||
| 54 | enum { | |
| 55 | softfloat_mulAdd_subC = 1, | |
| 56 | softfloat_mulAdd_subProd = 2 | |
| 57 | }; | |
| 58 | ||
| 59 | /*---------------------------------------------------------------------------- | |
| 60 | *----------------------------------------------------------------------------*/ | |
| 61 | uint_fast32_t softfloat_roundToUI32( bool, uint_fast64_t, uint_fast8_t, bool ); | |
| 62 | ||
| 63 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 64 | uint_fast64_t | |
| 65 | softfloat_roundToUI64( | |
| 66 | bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); | |
| 67 | #else | |
| 68 | uint_fast64_t softfloat_roundMToUI64( bool, uint32_t *, uint_fast8_t, bool ); | |
| 69 | #endif | |
| 70 | ||
| 71 | int_fast32_t softfloat_roundToI32( bool, uint_fast64_t, uint_fast8_t, bool ); | |
| 72 | ||
| 73 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 74 | int_fast64_t | |
| 75 | softfloat_roundToI64( | |
| 76 | bool, uint_fast64_t, uint_fast64_t, uint_fast8_t, bool ); | |
| 77 | #else | |
| 78 | int_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 | ||
| 90 | struct exp8_sig16 { int_fast8_t exp; uint_fast16_t sig; }; | |
| 91 | struct exp8_sig16 softfloat_normSubnormalF16Sig( uint_fast16_t ); | |
| 92 | ||
| 93 | float16_t softfloat_roundPackToF16( bool, int_fast16_t, uint_fast16_t ); | |
| 94 | float16_t softfloat_normRoundPackToF16( bool, int_fast16_t, uint_fast16_t ); | |
| 95 | ||
| 96 | float16_t softfloat_addMagsF16( uint_fast16_t, uint_fast16_t ); | |
| 97 | float16_t softfloat_subMagsF16( uint_fast16_t, uint_fast16_t ); | |
| 98 | float16_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 | ||
| 111 | struct exp16_sig32 { int_fast16_t exp; uint_fast32_t sig; }; | |
| 112 | struct exp16_sig32 softfloat_normSubnormalF32Sig( uint_fast32_t ); | |
| 113 | ||
| 114 | float32_t softfloat_roundPackToF32( bool, int_fast16_t, uint_fast32_t ); | |
| 115 | float32_t softfloat_normRoundPackToF32( bool, int_fast16_t, uint_fast32_t ); | |
| 116 | ||
| 117 | float32_t softfloat_addMagsF32( uint_fast32_t, uint_fast32_t ); | |
| 118 | float32_t softfloat_subMagsF32( uint_fast32_t, uint_fast32_t ); | |
| 119 | float32_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 | ||
| 132 | struct exp16_sig64 { int_fast16_t exp; uint_fast64_t sig; }; | |
| 133 | struct exp16_sig64 softfloat_normSubnormalF64Sig( uint_fast64_t ); | |
| 134 | ||
| 135 | float64_t softfloat_roundPackToF64( bool, int_fast16_t, uint_fast64_t ); | |
| 136 | float64_t softfloat_normRoundPackToF64( bool, int_fast16_t, uint_fast64_t ); | |
| 137 | ||
| 138 | float64_t softfloat_addMagsF64( uint_fast64_t, uint_fast64_t, bool ); | |
| 139 | float64_t softfloat_subMagsF64( uint_fast64_t, uint_fast64_t, bool ); | |
| 140 | float64_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 | ||
| 157 | struct exp32_sig64 { int_fast32_t exp; uint64_t sig; }; | |
| 158 | struct exp32_sig64 softfloat_normSubnormalExtF80Sig( uint_fast64_t ); | |
| 159 | ||
| 160 | extFloat80_t | |
| 161 | softfloat_roundPackToExtF80( | |
| 162 | bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); | |
| 163 | extFloat80_t | |
| 164 | softfloat_normRoundPackToExtF80( | |
| 165 | bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast8_t ); | |
| 166 | ||
| 167 | extFloat80_t | |
| 168 | softfloat_addMagsExtF80( | |
| 169 | uint_fast16_t, uint_fast64_t, uint_fast16_t, uint_fast64_t, bool ); | |
| 170 | extFloat80_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 | ||
| 183 | struct exp32_sig128 { int_fast32_t exp; struct uint128 sig; }; | |
| 184 | struct exp32_sig128 | |
| 185 | softfloat_normSubnormalF128Sig( uint_fast64_t, uint_fast64_t ); | |
| 186 | ||
| 187 | float128_t | |
| 188 | softfloat_roundPackToF128( | |
| 189 | bool, int_fast32_t, uint_fast64_t, uint_fast64_t, uint_fast64_t ); | |
| 190 | float128_t | |
| 191 | softfloat_normRoundPackToF128( | |
| 192 | bool, int_fast32_t, uint_fast64_t, uint_fast64_t ); | |
| 193 | ||
| 194 | float128_t | |
| 195 | softfloat_addMagsF128( | |
| 196 | uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); | |
| 197 | float128_t | |
| 198 | softfloat_subMagsF128( | |
| 199 | uint_fast64_t, uint_fast64_t, uint_fast64_t, uint_fast64_t, bool ); | |
| 200 | float128_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 | ||
| 216 | bool | |
| 217 | softfloat_tryPropagateNaNExtF80M( | |
| 218 | const struct extFloat80M *, | |
| 219 | const struct extFloat80M *, | |
| 220 | struct extFloat80M * | |
| 221 | ); | |
| 222 | void softfloat_invalidExtF80M( struct extFloat80M * ); | |
| 223 | ||
| 224 | int softfloat_normExtF80SigM( uint64_t * ); | |
| 225 | ||
| 226 | void | |
| 227 | softfloat_roundPackMToExtF80M( | |
| 228 | bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); | |
| 229 | void | |
| 230 | softfloat_normRoundPackMToExtF80M( | |
| 231 | bool, int32_t, uint32_t *, uint_fast8_t, struct extFloat80M * ); | |
| 232 | ||
| 233 | void | |
| 234 | softfloat_addExtF80M( | |
| 235 | const struct extFloat80M *, | |
| 236 | const struct extFloat80M *, | |
| 237 | struct extFloat80M *, | |
| 238 | bool | |
| 239 | ); | |
| 240 | ||
| 241 | int | |
| 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 | ||
| 252 | bool softfloat_isNaNF128M( const uint32_t * ); | |
| 253 | ||
| 254 | bool | |
| 255 | softfloat_tryPropagateNaNF128M( | |
| 256 | const uint32_t *, const uint32_t *, uint32_t * ); | |
| 257 | void softfloat_invalidF128M( uint32_t * ); | |
| 258 | ||
| 259 | int softfloat_shiftNormSigF128M( const uint32_t *, uint_fast8_t, uint32_t * ); | |
| 260 | ||
| 261 | void softfloat_roundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); | |
| 262 | void softfloat_normRoundPackMToF128M( bool, int32_t, uint32_t *, uint32_t * ); | |
| 263 | ||
| 264 | void | |
| 265 | softfloat_addF128M( const uint32_t *, const uint32_t *, uint32_t *, bool ); | |
| 266 | void | |
| 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 | ||
| 4 | This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2017 The Regents of the University of California. All rights | |
| 8 | reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 47 | INLINE uint_fast8_t softfloat_countLeadingZeros16( uint16_t a ) | |
| 48 | { return a ? __builtin_clz( a ) - 16 : 16; } | |
| 49 | #define softfloat_countLeadingZeros16 softfloat_countLeadingZeros16 | |
| 50 | ||
| 51 | INLINE uint_fast8_t softfloat_countLeadingZeros32( uint32_t a ) | |
| 52 | { return a ? __builtin_clz( a ) : 32; } | |
| 53 | #define softfloat_countLeadingZeros32 softfloat_countLeadingZeros32 | |
| 54 | ||
| 55 | INLINE 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 | ||
| 63 | INLINE 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 | ||
| 71 | INLINE 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 | ||
| 79 | INLINE | |
| 80 | struct 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 | ||
| 88 | INLINE | |
| 89 | void | |
| 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 | ||
| 4 | This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | |
| 46 | struct uint128 { uint64_t v0, v64; }; | |
| 47 | struct uint64_extra { uint64_t extra, v; }; | |
| 48 | struct uint128_extra { uint64_t extra; struct uint128 v; }; | |
| 49 | #else | |
| 50 | struct uint128 { uint64_t v64, v0; }; | |
| 51 | struct uint64_extra { uint64_t v, extra; }; | |
| 52 | struct 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 | ||
| 4 | This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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) | |
| 52 | INLINE | |
| 53 | uint64_t softfloat_shortShiftRightJam64( uint64_t a, uint_fast8_t dist ) | |
| 54 | { return a>>dist | ((a & (((uint_fast64_t) 1<<dist) - 1)) != 0); } | |
| 55 | #else | |
| 56 | uint64_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) | |
| 71 | INLINE 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 | |
| 77 | uint32_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) | |
| 92 | INLINE 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 | |
| 98 | uint64_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 | *----------------------------------------------------------------------------*/ | |
| 107 | extern 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) | |
| 115 | INLINE 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 | |
| 126 | uint_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) | |
| 136 | INLINE 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 | |
| 151 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 160 | uint_fast8_t softfloat_countLeadingZeros64( uint64_t a ); | |
| 161 | #endif | |
| 162 | ||
| 163 | extern const uint16_t softfloat_approxRecip_1k0s[16]; | |
| 164 | extern 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 | |
| 181 | uint32_t softfloat_approxRecip32_1( uint32_t a ); | |
| 182 | #endif | |
| 183 | #endif | |
| 184 | ||
| 185 | extern const uint16_t softfloat_approxRecipSqrt_1k0s[16]; | |
| 186 | extern 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 | *----------------------------------------------------------------------------*/ | |
| 207 | uint32_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) | |
| 224 | INLINE | |
| 225 | bool softfloat_eq128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) | |
| 226 | { return (a64 == b64) && (a0 == b0); } | |
| 227 | #else | |
| 228 | bool 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) | |
| 239 | INLINE | |
| 240 | bool softfloat_le128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) | |
| 241 | { return (a64 < b64) || ((a64 == b64) && (a0 <= b0)); } | |
| 242 | #else | |
| 243 | bool 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) | |
| 254 | INLINE | |
| 255 | bool softfloat_lt128( uint64_t a64, uint64_t a0, uint64_t b64, uint64_t b0 ) | |
| 256 | { return (a64 < b64) || ((a64 == b64) && (a0 < b0)); } | |
| 257 | #else | |
| 258 | bool 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) | |
| 268 | INLINE | |
| 269 | struct 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 | |
| 278 | struct 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) | |
| 289 | INLINE | |
| 290 | struct 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 | |
| 299 | struct 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) | |
| 310 | INLINE | |
| 311 | struct 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 | |
| 321 | struct 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) | |
| 336 | INLINE | |
| 337 | struct 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 | |
| 350 | struct 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) | |
| 362 | INLINE | |
| 363 | struct 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 | |
| 375 | struct 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) | |
| 399 | INLINE | |
| 400 | struct 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 | |
| 416 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 433 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 455 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 473 | void | |
| 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) | |
| 485 | INLINE | |
| 486 | struct 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 | |
| 495 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 508 | void | |
| 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) | |
| 520 | INLINE | |
| 521 | struct 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 | |
| 531 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 545 | void | |
| 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) | |
| 555 | INLINE 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 | |
| 565 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 573 | struct 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) | |
| 583 | INLINE | |
| 584 | struct 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 | |
| 596 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 608 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 629 | int_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 | *----------------------------------------------------------------------------*/ | |
| 641 | int_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) | |
| 654 | INLINE | |
| 655 | void | |
| 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 | |
| 665 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 681 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 725 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 768 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 804 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 828 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 859 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 901 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 943 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 959 | uint_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 | *----------------------------------------------------------------------------*/ | |
| 984 | void 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 | *----------------------------------------------------------------------------*/ | |
| 1027 | void 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 | *----------------------------------------------------------------------------*/ | |
| 1055 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 1095 | void 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 | *----------------------------------------------------------------------------*/ | |
| 1107 | void | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 1122 | void | |
| 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 | ||
| 4 | This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 60 | extern THREAD_LOCAL uint_fast8_t softfloat_detectTininess; | |
| 61 | enum { | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 70 | extern THREAD_LOCAL uint_fast8_t softfloat_roundingMode; | |
| 71 | enum { | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 83 | extern THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags; | |
| 84 | enum { | |
| 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 | *----------------------------------------------------------------------------*/ | |
| 95 | void softfloat_raiseFlags( uint_fast8_t ); | |
| 96 | ||
| 97 | /*---------------------------------------------------------------------------- | |
| 98 | | Integer-to-floating-point conversion routines. | |
| 99 | *----------------------------------------------------------------------------*/ | |
| 100 | float16_t ui32_to_f16( uint32_t ); | |
| 101 | float32_t ui32_to_f32( uint32_t ); | |
| 102 | float64_t ui32_to_f64( uint32_t ); | |
| 103 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 104 | extFloat80_t ui32_to_extF80( uint32_t ); | |
| 105 | float128_t ui32_to_f128( uint32_t ); | |
| 106 | #endif | |
| 107 | void ui32_to_extF80M( uint32_t, extFloat80_t * ); | |
| 108 | void ui32_to_f128M( uint32_t, float128_t * ); | |
| 109 | float16_t ui64_to_f16( uint64_t ); | |
| 110 | float32_t ui64_to_f32( uint64_t ); | |
| 111 | float64_t ui64_to_f64( uint64_t ); | |
| 112 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 113 | extFloat80_t ui64_to_extF80( uint64_t ); | |
| 114 | float128_t ui64_to_f128( uint64_t ); | |
| 115 | #endif | |
| 116 | void ui64_to_extF80M( uint64_t, extFloat80_t * ); | |
| 117 | void ui64_to_f128M( uint64_t, float128_t * ); | |
| 118 | float16_t i32_to_f16( int32_t ); | |
| 119 | float32_t i32_to_f32( int32_t ); | |
| 120 | float64_t i32_to_f64( int32_t ); | |
| 121 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 122 | extFloat80_t i32_to_extF80( int32_t ); | |
| 123 | float128_t i32_to_f128( int32_t ); | |
| 124 | #endif | |
| 125 | void i32_to_extF80M( int32_t, extFloat80_t * ); | |
| 126 | void i32_to_f128M( int32_t, float128_t * ); | |
| 127 | float16_t i64_to_f16( int64_t ); | |
| 128 | float32_t i64_to_f32( int64_t ); | |
| 129 | float64_t i64_to_f64( int64_t ); | |
| 130 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 131 | extFloat80_t i64_to_extF80( int64_t ); | |
| 132 | float128_t i64_to_f128( int64_t ); | |
| 133 | #endif | |
| 134 | void i64_to_extF80M( int64_t, extFloat80_t * ); | |
| 135 | void i64_to_f128M( int64_t, float128_t * ); | |
| 136 | ||
| 137 | /*---------------------------------------------------------------------------- | |
| 138 | | 16-bit (half-precision) floating-point operations. | |
| 139 | *----------------------------------------------------------------------------*/ | |
| 140 | uint_fast32_t f16_to_ui32( float16_t, uint_fast8_t, bool ); | |
| 141 | uint_fast64_t f16_to_ui64( float16_t, uint_fast8_t, bool ); | |
| 142 | int_fast32_t f16_to_i32( float16_t, uint_fast8_t, bool ); | |
| 143 | int_fast64_t f16_to_i64( float16_t, uint_fast8_t, bool ); | |
| 144 | uint_fast32_t f16_to_ui32_r_minMag( float16_t, bool ); | |
| 145 | uint_fast64_t f16_to_ui64_r_minMag( float16_t, bool ); | |
| 146 | int_fast32_t f16_to_i32_r_minMag( float16_t, bool ); | |
| 147 | int_fast64_t f16_to_i64_r_minMag( float16_t, bool ); | |
| 148 | float32_t f16_to_f32( float16_t ); | |
| 149 | float64_t f16_to_f64( float16_t ); | |
| 150 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 151 | extFloat80_t f16_to_extF80( float16_t ); | |
| 152 | float128_t f16_to_f128( float16_t ); | |
| 153 | #endif | |
| 154 | void f16_to_extF80M( float16_t, extFloat80_t * ); | |
| 155 | void f16_to_f128M( float16_t, float128_t * ); | |
| 156 | float16_t f16_roundToInt( float16_t, uint_fast8_t, bool ); | |
| 157 | float16_t f16_add( float16_t, float16_t ); | |
| 158 | float16_t f16_sub( float16_t, float16_t ); | |
| 159 | float16_t f16_mul( float16_t, float16_t ); | |
| 160 | float16_t f16_mulAdd( float16_t, float16_t, float16_t ); | |
| 161 | float16_t f16_div( float16_t, float16_t ); | |
| 162 | float16_t f16_rem( float16_t, float16_t ); | |
| 163 | float16_t f16_sqrt( float16_t ); | |
| 164 | bool f16_eq( float16_t, float16_t ); | |
| 165 | bool f16_le( float16_t, float16_t ); | |
| 166 | bool f16_lt( float16_t, float16_t ); | |
| 167 | bool f16_eq_signaling( float16_t, float16_t ); | |
| 168 | bool f16_le_quiet( float16_t, float16_t ); | |
| 169 | bool f16_lt_quiet( float16_t, float16_t ); | |
| 170 | bool f16_isSignalingNaN( float16_t ); | |
| 171 | ||
| 172 | /*---------------------------------------------------------------------------- | |
| 173 | | 32-bit (single-precision) floating-point operations. | |
| 174 | *----------------------------------------------------------------------------*/ | |
| 175 | uint_fast32_t f32_to_ui32( float32_t, uint_fast8_t, bool ); | |
| 176 | uint_fast64_t f32_to_ui64( float32_t, uint_fast8_t, bool ); | |
| 177 | int_fast32_t f32_to_i32( float32_t, uint_fast8_t, bool ); | |
| 178 | int_fast64_t f32_to_i64( float32_t, uint_fast8_t, bool ); | |
| 179 | uint_fast32_t f32_to_ui32_r_minMag( float32_t, bool ); | |
| 180 | uint_fast64_t f32_to_ui64_r_minMag( float32_t, bool ); | |
| 181 | int_fast32_t f32_to_i32_r_minMag( float32_t, bool ); | |
| 182 | int_fast64_t f32_to_i64_r_minMag( float32_t, bool ); | |
| 183 | float16_t f32_to_f16( float32_t ); | |
| 184 | float64_t f32_to_f64( float32_t ); | |
| 185 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 186 | extFloat80_t f32_to_extF80( float32_t ); | |
| 187 | float128_t f32_to_f128( float32_t ); | |
| 188 | #endif | |
| 189 | void f32_to_extF80M( float32_t, extFloat80_t * ); | |
| 190 | void f32_to_f128M( float32_t, float128_t * ); | |
| 191 | float32_t f32_roundToInt( float32_t, uint_fast8_t, bool ); | |
| 192 | float32_t f32_add( float32_t, float32_t ); | |
| 193 | float32_t f32_sub( float32_t, float32_t ); | |
| 194 | float32_t f32_mul( float32_t, float32_t ); | |
| 195 | float32_t f32_mulAdd( float32_t, float32_t, float32_t ); | |
| 196 | float32_t f32_div( float32_t, float32_t ); | |
| 197 | float32_t f32_rem( float32_t, float32_t ); | |
| 198 | float32_t f32_sqrt( float32_t ); | |
| 199 | bool f32_eq( float32_t, float32_t ); | |
| 200 | bool f32_le( float32_t, float32_t ); | |
| 201 | bool f32_lt( float32_t, float32_t ); | |
| 202 | bool f32_eq_signaling( float32_t, float32_t ); | |
| 203 | bool f32_le_quiet( float32_t, float32_t ); | |
| 204 | bool f32_lt_quiet( float32_t, float32_t ); | |
| 205 | bool f32_isSignalingNaN( float32_t ); | |
| 206 | ||
| 207 | /*---------------------------------------------------------------------------- | |
| 208 | | 64-bit (double-precision) floating-point operations. | |
| 209 | *----------------------------------------------------------------------------*/ | |
| 210 | uint_fast32_t f64_to_ui32( float64_t, uint_fast8_t, bool ); | |
| 211 | uint_fast64_t f64_to_ui64( float64_t, uint_fast8_t, bool ); | |
| 212 | int_fast32_t f64_to_i32( float64_t, uint_fast8_t, bool ); | |
| 213 | int_fast64_t f64_to_i64( float64_t, uint_fast8_t, bool ); | |
| 214 | uint_fast32_t f64_to_ui32_r_minMag( float64_t, bool ); | |
| 215 | uint_fast64_t f64_to_ui64_r_minMag( float64_t, bool ); | |
| 216 | int_fast32_t f64_to_i32_r_minMag( float64_t, bool ); | |
| 217 | int_fast64_t f64_to_i64_r_minMag( float64_t, bool ); | |
| 218 | float16_t f64_to_f16( float64_t ); | |
| 219 | float32_t f64_to_f32( float64_t ); | |
| 220 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 221 | extFloat80_t f64_to_extF80( float64_t ); | |
| 222 | float128_t f64_to_f128( float64_t ); | |
| 223 | #endif | |
| 224 | void f64_to_extF80M( float64_t, extFloat80_t * ); | |
| 225 | void f64_to_f128M( float64_t, float128_t * ); | |
| 226 | float64_t f64_roundToInt( float64_t, uint_fast8_t, bool ); | |
| 227 | float64_t f64_add( float64_t, float64_t ); | |
| 228 | float64_t f64_sub( float64_t, float64_t ); | |
| 229 | float64_t f64_mul( float64_t, float64_t ); | |
| 230 | float64_t f64_mulAdd( float64_t, float64_t, float64_t ); | |
| 231 | float64_t f64_div( float64_t, float64_t ); | |
| 232 | float64_t f64_rem( float64_t, float64_t ); | |
| 233 | float64_t f64_sqrt( float64_t ); | |
| 234 | bool f64_eq( float64_t, float64_t ); | |
| 235 | bool f64_le( float64_t, float64_t ); | |
| 236 | bool f64_lt( float64_t, float64_t ); | |
| 237 | bool f64_eq_signaling( float64_t, float64_t ); | |
| 238 | bool f64_le_quiet( float64_t, float64_t ); | |
| 239 | bool f64_lt_quiet( float64_t, float64_t ); | |
| 240 | bool 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 | *----------------------------------------------------------------------------*/ | |
| 246 | extern THREAD_LOCAL uint_fast8_t extF80_roundingPrecision; | |
| 247 | ||
| 248 | /*---------------------------------------------------------------------------- | |
| 249 | | 80-bit extended double-precision floating-point operations. | |
| 250 | *----------------------------------------------------------------------------*/ | |
| 251 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 252 | uint_fast32_t extF80_to_ui32( extFloat80_t, uint_fast8_t, bool ); | |
| 253 | uint_fast64_t extF80_to_ui64( extFloat80_t, uint_fast8_t, bool ); | |
| 254 | int_fast32_t extF80_to_i32( extFloat80_t, uint_fast8_t, bool ); | |
| 255 | int_fast64_t extF80_to_i64( extFloat80_t, uint_fast8_t, bool ); | |
| 256 | uint_fast32_t extF80_to_ui32_r_minMag( extFloat80_t, bool ); | |
| 257 | uint_fast64_t extF80_to_ui64_r_minMag( extFloat80_t, bool ); | |
| 258 | int_fast32_t extF80_to_i32_r_minMag( extFloat80_t, bool ); | |
| 259 | int_fast64_t extF80_to_i64_r_minMag( extFloat80_t, bool ); | |
| 260 | float16_t extF80_to_f16( extFloat80_t ); | |
| 261 | float32_t extF80_to_f32( extFloat80_t ); | |
| 262 | float64_t extF80_to_f64( extFloat80_t ); | |
| 263 | float128_t extF80_to_f128( extFloat80_t ); | |
| 264 | extFloat80_t extF80_roundToInt( extFloat80_t, uint_fast8_t, bool ); | |
| 265 | extFloat80_t extF80_add( extFloat80_t, extFloat80_t ); | |
| 266 | extFloat80_t extF80_sub( extFloat80_t, extFloat80_t ); | |
| 267 | extFloat80_t extF80_mul( extFloat80_t, extFloat80_t ); | |
| 268 | extFloat80_t extF80_div( extFloat80_t, extFloat80_t ); | |
| 269 | extFloat80_t extF80_rem( extFloat80_t, extFloat80_t ); | |
| 270 | extFloat80_t extF80_sqrt( extFloat80_t ); | |
| 271 | bool extF80_eq( extFloat80_t, extFloat80_t ); | |
| 272 | bool extF80_le( extFloat80_t, extFloat80_t ); | |
| 273 | bool extF80_lt( extFloat80_t, extFloat80_t ); | |
| 274 | bool extF80_eq_signaling( extFloat80_t, extFloat80_t ); | |
| 275 | bool extF80_le_quiet( extFloat80_t, extFloat80_t ); | |
| 276 | bool extF80_lt_quiet( extFloat80_t, extFloat80_t ); | |
| 277 | bool extF80_isSignalingNaN( extFloat80_t ); | |
| 278 | #endif | |
| 279 | uint_fast32_t extF80M_to_ui32( const extFloat80_t *, uint_fast8_t, bool ); | |
| 280 | uint_fast64_t extF80M_to_ui64( const extFloat80_t *, uint_fast8_t, bool ); | |
| 281 | int_fast32_t extF80M_to_i32( const extFloat80_t *, uint_fast8_t, bool ); | |
| 282 | int_fast64_t extF80M_to_i64( const extFloat80_t *, uint_fast8_t, bool ); | |
| 283 | uint_fast32_t extF80M_to_ui32_r_minMag( const extFloat80_t *, bool ); | |
| 284 | uint_fast64_t extF80M_to_ui64_r_minMag( const extFloat80_t *, bool ); | |
| 285 | int_fast32_t extF80M_to_i32_r_minMag( const extFloat80_t *, bool ); | |
| 286 | int_fast64_t extF80M_to_i64_r_minMag( const extFloat80_t *, bool ); | |
| 287 | float16_t extF80M_to_f16( const extFloat80_t * ); | |
| 288 | float32_t extF80M_to_f32( const extFloat80_t * ); | |
| 289 | float64_t extF80M_to_f64( const extFloat80_t * ); | |
| 290 | void extF80M_to_f128M( const extFloat80_t *, float128_t * ); | |
| 291 | void | |
| 292 | extF80M_roundToInt( | |
| 293 | const extFloat80_t *, uint_fast8_t, bool, extFloat80_t * ); | |
| 294 | void extF80M_add( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); | |
| 295 | void extF80M_sub( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); | |
| 296 | void extF80M_mul( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); | |
| 297 | void extF80M_div( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); | |
| 298 | void extF80M_rem( const extFloat80_t *, const extFloat80_t *, extFloat80_t * ); | |
| 299 | void extF80M_sqrt( const extFloat80_t *, extFloat80_t * ); | |
| 300 | bool extF80M_eq( const extFloat80_t *, const extFloat80_t * ); | |
| 301 | bool extF80M_le( const extFloat80_t *, const extFloat80_t * ); | |
| 302 | bool extF80M_lt( const extFloat80_t *, const extFloat80_t * ); | |
| 303 | bool extF80M_eq_signaling( const extFloat80_t *, const extFloat80_t * ); | |
| 304 | bool extF80M_le_quiet( const extFloat80_t *, const extFloat80_t * ); | |
| 305 | bool extF80M_lt_quiet( const extFloat80_t *, const extFloat80_t * ); | |
| 306 | bool extF80M_isSignalingNaN( const extFloat80_t * ); | |
| 307 | ||
| 308 | /*---------------------------------------------------------------------------- | |
| 309 | | 128-bit (quadruple-precision) floating-point operations. | |
| 310 | *----------------------------------------------------------------------------*/ | |
| 311 | #ifdef SOFTFLOAT_FAST_INT64 | |
| 312 | uint_fast32_t f128_to_ui32( float128_t, uint_fast8_t, bool ); | |
| 313 | uint_fast64_t f128_to_ui64( float128_t, uint_fast8_t, bool ); | |
| 314 | int_fast32_t f128_to_i32( float128_t, uint_fast8_t, bool ); | |
| 315 | int_fast64_t f128_to_i64( float128_t, uint_fast8_t, bool ); | |
| 316 | uint_fast32_t f128_to_ui32_r_minMag( float128_t, bool ); | |
| 317 | uint_fast64_t f128_to_ui64_r_minMag( float128_t, bool ); | |
| 318 | int_fast32_t f128_to_i32_r_minMag( float128_t, bool ); | |
| 319 | int_fast64_t f128_to_i64_r_minMag( float128_t, bool ); | |
| 320 | float16_t f128_to_f16( float128_t ); | |
| 321 | float32_t f128_to_f32( float128_t ); | |
| 322 | float64_t f128_to_f64( float128_t ); | |
| 323 | extFloat80_t f128_to_extF80( float128_t ); | |
| 324 | float128_t f128_roundToInt( float128_t, uint_fast8_t, bool ); | |
| 325 | float128_t f128_add( float128_t, float128_t ); | |
| 326 | float128_t f128_sub( float128_t, float128_t ); | |
| 327 | float128_t f128_mul( float128_t, float128_t ); | |
| 328 | float128_t f128_mulAdd( float128_t, float128_t, float128_t ); | |
| 329 | float128_t f128_div( float128_t, float128_t ); | |
| 330 | float128_t f128_rem( float128_t, float128_t ); | |
| 331 | float128_t f128_sqrt( float128_t ); | |
| 332 | bool f128_eq( float128_t, float128_t ); | |
| 333 | bool f128_le( float128_t, float128_t ); | |
| 334 | bool f128_lt( float128_t, float128_t ); | |
| 335 | bool f128_eq_signaling( float128_t, float128_t ); | |
| 336 | bool f128_le_quiet( float128_t, float128_t ); | |
| 337 | bool f128_lt_quiet( float128_t, float128_t ); | |
| 338 | bool f128_isSignalingNaN( float128_t ); | |
| 339 | #endif | |
| 340 | uint_fast32_t f128M_to_ui32( const float128_t *, uint_fast8_t, bool ); | |
| 341 | uint_fast64_t f128M_to_ui64( const float128_t *, uint_fast8_t, bool ); | |
| 342 | int_fast32_t f128M_to_i32( const float128_t *, uint_fast8_t, bool ); | |
| 343 | int_fast64_t f128M_to_i64( const float128_t *, uint_fast8_t, bool ); | |
| 344 | uint_fast32_t f128M_to_ui32_r_minMag( const float128_t *, bool ); | |
| 345 | uint_fast64_t f128M_to_ui64_r_minMag( const float128_t *, bool ); | |
| 346 | int_fast32_t f128M_to_i32_r_minMag( const float128_t *, bool ); | |
| 347 | int_fast64_t f128M_to_i64_r_minMag( const float128_t *, bool ); | |
| 348 | float16_t f128M_to_f16( const float128_t * ); | |
| 349 | float32_t f128M_to_f32( const float128_t * ); | |
| 350 | float64_t f128M_to_f64( const float128_t * ); | |
| 351 | void f128M_to_extF80M( const float128_t *, extFloat80_t * ); | |
| 352 | void f128M_roundToInt( const float128_t *, uint_fast8_t, bool, float128_t * ); | |
| 353 | void f128M_add( const float128_t *, const float128_t *, float128_t * ); | |
| 354 | void f128M_sub( const float128_t *, const float128_t *, float128_t * ); | |
| 355 | void f128M_mul( const float128_t *, const float128_t *, float128_t * ); | |
| 356 | void | |
| 357 | f128M_mulAdd( | |
| 358 | const float128_t *, const float128_t *, const float128_t *, float128_t * | |
| 359 | ); | |
| 360 | void f128M_div( const float128_t *, const float128_t *, float128_t * ); | |
| 361 | void f128M_rem( const float128_t *, const float128_t *, float128_t * ); | |
| 362 | void f128M_sqrt( const float128_t *, float128_t * ); | |
| 363 | bool f128M_eq( const float128_t *, const float128_t * ); | |
| 364 | bool f128M_le( const float128_t *, const float128_t * ); | |
| 365 | bool f128M_lt( const float128_t *, const float128_t * ); | |
| 366 | bool f128M_eq_signaling( const float128_t *, const float128_t * ); | |
| 367 | bool f128M_le_quiet( const float128_t *, const float128_t * ); | |
| 368 | bool f128M_lt_quiet( const float128_t *, const float128_t * ); | |
| 369 | bool 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 | ||
| 4 | This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | *----------------------------------------------------------------------------*/ | |
| 51 | typedef struct { uint16_t v; } float16_t; | |
| 52 | typedef struct { uint32_t v; } float32_t; | |
| 53 | typedef struct { uint64_t v; } float64_t; | |
| 54 | typedef 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 | |
| 62 | struct extFloat80M { uint64_t signif; uint16_t signExp; }; | |
| 63 | #else | |
| 64 | struct 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 | *----------------------------------------------------------------------------*/ | |
| 79 | typedef struct extFloat80M extFloat80_t; | |
| 80 | ||
| 81 | #endif | |
| 82 |
deps/SoftFloat-3e/source/s_add128.c deleted-55| ... | ... | @@ -1,55 +0,0 @@ |
| 1 | ||
| 2 | /*============================================================================ | |
| 3 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 43 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 43 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 43 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 42 | extern const uint16_t softfloat_approxRecip_1k0s[16]; | |
| 43 | extern const uint16_t softfloat_approxRecip_1k1s[16]; | |
| 44 | ||
| 45 | uint32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 42 | extern const uint16_t softfloat_approxRecipSqrt_1k0s[]; | |
| 43 | extern const uint16_t softfloat_approxRecipSqrt_1k1s[]; | |
| 44 | ||
| 45 | uint32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | const 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 | }; | |
| 45 | const 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | const 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 | }; | |
| 45 | const 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 42 | int | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 45 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | const 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 43 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | *----------------------------------------------------------------------------*/ | |
| 44 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 43 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 43 | bool 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 45 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 46 | float64_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 | ||
| 246 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | int 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 42 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 42 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 42 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 42 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 42 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 42 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 42 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | int 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | int_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | uint_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 45 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 41 | int | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | static | |
| 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 | ||
| 72 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 42 | uint32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 42 | uint64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 45 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 45 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 42 | uint64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | struct 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 43 | void | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the | |
| 8 | University of California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 42 | bool | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All rights reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, EVEN 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 | ||
| 43 | bool | |
| 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 47 | THREAD_LOCAL uint_fast8_t softfloat_roundingMode = softfloat_round_near_even; | |
| 48 | THREAD_LOCAL uint_fast8_t softfloat_detectTininess = init_detectTininess; | |
| 49 | THREAD_LOCAL uint_fast8_t softfloat_exceptionFlags = 0; | |
| 50 | ||
| 51 | THREAD_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void ui32_to_extF80M( uint32_t a, extFloat80_t *zPtr ) | |
| 45 | { | |
| 46 | ||
| 47 | *zPtr = ui32_to_extF80( a ); | |
| 48 | ||
| 49 | } | |
| 50 | ||
| 51 | #else | |
| 52 | ||
| 53 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void ui32_to_f128M( uint32_t a, float128_t *zPtr ) | |
| 45 | { | |
| 46 | ||
| 47 | *zPtr = ui32_to_f128( a ); | |
| 48 | ||
| 49 | } | |
| 50 | ||
| 51 | #else | |
| 52 | ||
| 53 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float64_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | extFloat80_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void ui64_to_extF80M( uint64_t a, extFloat80_t *zPtr ) | |
| 45 | { | |
| 46 | ||
| 47 | *zPtr = ui64_to_extF80( a ); | |
| 48 | ||
| 49 | } | |
| 50 | ||
| 51 | #else | |
| 52 | ||
| 53 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float128_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | ||
| 44 | void ui64_to_f128M( uint64_t a, float128_t *zPtr ) | |
| 45 | { | |
| 46 | ||
| 47 | *zPtr = ui64_to_f128( a ); | |
| 48 | ||
| 49 | } | |
| 50 | ||
| 51 | #else | |
| 52 | ||
| 53 | void 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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float16_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of | |
| 8 | California. All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float32_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 | ||
| 4 | This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic | |
| 5 | Package, Release 3e, by John R. Hauser. | |
| 6 | ||
| 7 | Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. | |
| 8 | All Rights Reserved. | |
| 9 | ||
| 10 | Redistribution and use in source and binary forms, with or without | |
| 11 | modification, are permitted provided that the following conditions are met: | |
| 12 | ||
| 13 | 1. Redistributions of source code must retain the above copyright notice, | |
| 14 | this list of conditions, and the following disclaimer. | |
| 15 | ||
| 16 | 2. Redistributions in binary form must reproduce the above copyright notice, | |
| 17 | this list of conditions, and the following disclaimer in the documentation | |
| 18 | and/or other materials provided with the distribution. | |
| 19 | ||
| 20 | 3. Neither the name of the University nor the names of its contributors may | |
| 21 | be used to endorse or promote products derived from this software without | |
| 22 | specific prior written permission. | |
| 23 | ||
| 24 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY | |
| 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE | |
| 27 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY | |
| 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
| 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 33 | SOFTWARE, 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 | float64_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 | 30 | const clangMain = @import("main.zig").clangMain; |
| 31 | 31 | const Module = @import("Module.zig"); |
| 32 | 32 | const Cache = @import("Cache.zig"); |
| 33 | const stage1 = @import("stage1.zig"); | |
| 34 | 33 | const translate_c = @import("translate_c.zig"); |
| 35 | 34 | const c_codegen = @import("codegen/c.zig"); |
| 36 | 35 | const ThreadPool = @import("ThreadPool.zig"); |
| ... | ... | @@ -5411,199 +5410,6 @@ fn buildOutputFromZig( |
| 5411 | 5410 | }; |
| 5412 | 5411 | } |
| 5413 | 5412 | |
| 5414 | fn 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 | ||
| 5564 | fn 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 | ||
| 5570 | fn 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 | ||
| 5607 | 5413 | pub fn build_crt_file( |
| 5608 | 5414 | comp: *Compilation, |
| 5609 | 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 | ||
| 5 | const std = @import("std"); | |
| 6 | const assert = std.debug.assert; | |
| 7 | const mem = std.mem; | |
| 8 | const CrossTarget = std.zig.CrossTarget; | |
| 9 | const Target = std.Target; | |
| 10 | const builtin = @import("builtin"); | |
| 11 | ||
| 12 | const build_options = @import("build_options"); | |
| 13 | const stage2 = @import("main.zig"); | |
| 14 | const fatal = stage2.fatal; | |
| 15 | const Compilation = @import("Compilation.zig"); | |
| 16 | const translate_c = @import("translate_c.zig"); | |
| 17 | const target_util = @import("target.zig"); | |
| 18 | ||
| 19 | comptime { | |
| 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 | ||
| 28 | pub const log = stage2.log; | |
| 29 | pub const log_level = stage2.log_level; | |
| 30 | ||
| 31 | pub 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; | |
| 64 | pub const ErrColor = c_int; | |
| 65 | /// Matches std.builtin.CodeModel | |
| 66 | pub const CodeModel = c_int; | |
| 67 | /// Matches std.Target.Os.Tag | |
| 68 | pub const OS = c_int; | |
| 69 | /// Matches std.builtin.BuildMode | |
| 70 | pub const BuildMode = c_int; | |
| 71 | ||
| 72 | pub 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 | ||
| 84 | pub 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 | ||
| 94 | pub 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 | ||
| 161 | pub const os_init = zig_stage1_os_init; | |
| 162 | extern fn zig_stage1_os_init() void; | |
| 163 | ||
| 164 | pub const create = zig_stage1_create; | |
| 165 | extern 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 | ||
| 177 | extern fn zig_stage1_build_object(*Module) void; | |
| 178 | extern fn zig_stage1_destroy(*Module) void; | |
| 179 | ||
| 180 | // ABI warning | |
| 181 | export fn stage2_panic(ptr: [*]const u8, len: usize) void { | |
| 182 | @panic(ptr[0..len]); | |
| 183 | } | |
| 184 | ||
| 185 | // ABI warning | |
| 186 | const 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 | |
| 271 | export fn stage2_version_string() [*:0]const u8 { | |
| 272 | return build_options.version; | |
| 273 | } | |
| 274 | ||
| 275 | // ABI warning | |
| 276 | export 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 | |
| 285 | export 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 | |
| 292 | export 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 | |
| 301 | export fn stage2_progress_destroy(progress: *std.Progress) void { | |
| 302 | std.heap.c_allocator.destroy(progress); | |
| 303 | } | |
| 304 | ||
| 305 | // ABI warning | |
| 306 | export 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 | |
| 316 | export fn stage2_progress_disable_tty(progress: *std.Progress) void { | |
| 317 | progress.terminal = null; | |
| 318 | } | |
| 319 | ||
| 320 | // ABI warning | |
| 321 | export 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 | |
| 337 | export 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 | |
| 345 | export fn stage2_progress_complete_one(node: *std.Progress.Node) void { | |
| 346 | node.completeOne(); | |
| 347 | } | |
| 348 | ||
| 349 | // ABI warning | |
| 350 | export 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 | |
| 358 | pub 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 | |
| 372 | const Stage2SemVer = extern struct { | |
| 373 | major: u32, | |
| 374 | minor: u32, | |
| 375 | patch: u32, | |
| 376 | }; | |
| 377 | ||
| 378 | // ABI warning | |
| 379 | export 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 | ||
| 413 | export 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 | ||
| 453 | export 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 | ||
| 473 | export 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 | ||
| 21 | struct AstNode; | |
| 22 | struct ZigFn; | |
| 23 | struct Scope; | |
| 24 | struct ScopeBlock; | |
| 25 | struct ScopeFnDef; | |
| 26 | struct ScopeExpr; | |
| 27 | struct ZigType; | |
| 28 | struct ZigVar; | |
| 29 | struct ErrorTableEntry; | |
| 30 | struct BuiltinFnEntry; | |
| 31 | struct TypeStructField; | |
| 32 | struct CodeGen; | |
| 33 | struct ZigValue; | |
| 34 | struct Stage1ZirInst; | |
| 35 | struct Stage1AirInst; | |
| 36 | struct Stage1AirInstCast; | |
| 37 | struct Stage1AirInstAlloca; | |
| 38 | struct Stage1AirInstCall; | |
| 39 | struct Stage1AirInstAwait; | |
| 40 | struct Stage1ZirBasicBlock; | |
| 41 | struct Stage1AirBasicBlock; | |
| 42 | struct ScopeDecls; | |
| 43 | struct ZigWindowsSDK; | |
| 44 | struct Tld; | |
| 45 | struct TldExport; | |
| 46 | struct IrAnalyze; | |
| 47 | struct ResultLoc; | |
| 48 | struct ResultLocPeer; | |
| 49 | struct ResultLocPeerParent; | |
| 50 | struct ResultLocBitCast; | |
| 51 | struct ResultLocCast; | |
| 52 | struct ResultLocReturn; | |
| 53 | struct Stage1Air; | |
| 54 | ||
| 55 | enum FileExt { | |
| 56 | FileExtUnknown, | |
| 57 | FileExtAsm, | |
| 58 | FileExtC, | |
| 59 | FileExtCpp, | |
| 60 | FileExtHeader, | |
| 61 | FileExtLLVMIr, | |
| 62 | FileExtLLVMBitCode, | |
| 63 | }; | |
| 64 | ||
| 65 | enum PtrLen { | |
| 66 | PtrLenUnknown, | |
| 67 | PtrLenSingle, | |
| 68 | PtrLenC, | |
| 69 | }; | |
| 70 | ||
| 71 | enum 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 | |
| 93 | enum 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. | |
| 106 | enum BuiltinPtrSize { | |
| 107 | BuiltinPtrSizeOne, | |
| 108 | BuiltinPtrSizeMany, | |
| 109 | BuiltinPtrSizeSlice, | |
| 110 | BuiltinPtrSizeC, | |
| 111 | }; | |
| 112 | ||
| 113 | enum UndefAllowed { | |
| 114 | UndefOk, | |
| 115 | UndefBad, | |
| 116 | LazyOkNoUndef, | |
| 117 | LazyOk, | |
| 118 | }; | |
| 119 | ||
| 120 | enum X64CABIClass { | |
| 121 | X64CABIClass_Unknown, | |
| 122 | X64CABIClass_MEMORY, | |
| 123 | X64CABIClass_MEMORY_nobyval, | |
| 124 | X64CABIClass_INTEGER, | |
| 125 | X64CABIClass_SSE, | |
| 126 | X64CABIClass_AGG, | |
| 127 | }; | |
| 128 | ||
| 129 | struct 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 | ||
| 141 | struct 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 | ||
| 163 | enum OutType { | |
| 164 | OutTypeUnknown, | |
| 165 | OutTypeExe, | |
| 166 | OutTypeLib, | |
| 167 | OutTypeObj, | |
| 168 | }; | |
| 169 | ||
| 170 | enum ConstParentId { | |
| 171 | ConstParentIdNone, | |
| 172 | ConstParentIdStruct, | |
| 173 | ConstParentIdErrUnionCode, | |
| 174 | ConstParentIdErrUnionPayload, | |
| 175 | ConstParentIdOptionalPayload, | |
| 176 | ConstParentIdArray, | |
| 177 | ConstParentIdUnion, | |
| 178 | ConstParentIdScalar, | |
| 179 | }; | |
| 180 | ||
| 181 | struct 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 | ||
| 211 | struct ConstStructValue { | |
| 212 | ZigValue **fields; | |
| 213 | }; | |
| 214 | ||
| 215 | struct ConstUnionValue { | |
| 216 | BigInt tag; | |
| 217 | ZigValue *payload; | |
| 218 | }; | |
| 219 | ||
| 220 | enum ConstArraySpecial { | |
| 221 | ConstArraySpecialNone, | |
| 222 | ConstArraySpecialUndef, | |
| 223 | ConstArraySpecialBuf, | |
| 224 | }; | |
| 225 | ||
| 226 | struct ConstArrayValue { | |
| 227 | ConstArraySpecial special; | |
| 228 | union { | |
| 229 | struct { | |
| 230 | ZigValue *elements; | |
| 231 | } s_none; | |
| 232 | Buf *s_buf; | |
| 233 | } data; | |
| 234 | }; | |
| 235 | ||
| 236 | enum 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 | ||
| 275 | enum 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 | ||
| 290 | struct 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 | ||
| 324 | struct ConstErrValue { | |
| 325 | ZigValue *error_set; | |
| 326 | ZigValue *payload; | |
| 327 | }; | |
| 328 | ||
| 329 | struct ConstBoundFnValue { | |
| 330 | ZigFn *fn; | |
| 331 | Stage1AirInst *first_arg; | |
| 332 | AstNode *first_arg_src; | |
| 333 | }; | |
| 334 | ||
| 335 | struct ConstArgTuple { | |
| 336 | size_t start_index; | |
| 337 | size_t end_index; | |
| 338 | }; | |
| 339 | ||
| 340 | enum 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 | ||
| 360 | enum RuntimeHintErrorUnion { | |
| 361 | RuntimeHintErrorUnionUnknown, | |
| 362 | RuntimeHintErrorUnionError, | |
| 363 | RuntimeHintErrorUnionNonError, | |
| 364 | }; | |
| 365 | ||
| 366 | enum 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 | ||
| 372 | enum RuntimeHintPtr { | |
| 373 | RuntimeHintPtrUnknown, | |
| 374 | RuntimeHintPtrStack, | |
| 375 | RuntimeHintPtrNonStack, | |
| 376 | }; | |
| 377 | ||
| 378 | enum RuntimeHintSliceId { | |
| 379 | RuntimeHintSliceIdUnknown, | |
| 380 | RuntimeHintSliceIdLen, | |
| 381 | }; | |
| 382 | ||
| 383 | struct RuntimeHintSlice { | |
| 384 | enum RuntimeHintSliceId id; | |
| 385 | uint64_t len; | |
| 386 | }; | |
| 387 | ||
| 388 | enum 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 | ||
| 403 | struct LazyValue { | |
| 404 | LazyValueId id; | |
| 405 | }; | |
| 406 | ||
| 407 | struct LazyValueTypeInfoDecls { | |
| 408 | LazyValue base; | |
| 409 | ||
| 410 | IrAnalyze *ira; | |
| 411 | ||
| 412 | ScopeDecls *decls_scope; | |
| 413 | AstNode *source_node; | |
| 414 | }; | |
| 415 | ||
| 416 | struct LazyValueAlignOf { | |
| 417 | LazyValue base; | |
| 418 | ||
| 419 | IrAnalyze *ira; | |
| 420 | Stage1AirInst *target_type; | |
| 421 | }; | |
| 422 | ||
| 423 | struct LazyValueSizeOf { | |
| 424 | LazyValue base; | |
| 425 | ||
| 426 | IrAnalyze *ira; | |
| 427 | Stage1AirInst *target_type; | |
| 428 | ||
| 429 | bool bit_size; | |
| 430 | }; | |
| 431 | ||
| 432 | struct 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 | ||
| 445 | struct LazyValueArrayType { | |
| 446 | LazyValue base; | |
| 447 | ||
| 448 | IrAnalyze *ira; | |
| 449 | Stage1AirInst *sentinel; // can be null | |
| 450 | Stage1AirInst *elem_type; | |
| 451 | uint64_t length; | |
| 452 | }; | |
| 453 | ||
| 454 | struct 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 | ||
| 471 | struct LazyValuePtrTypeSimple { | |
| 472 | LazyValue base; | |
| 473 | ||
| 474 | IrAnalyze *ira; | |
| 475 | Stage1AirInst *elem_type; | |
| 476 | }; | |
| 477 | ||
| 478 | struct LazyValueOptType { | |
| 479 | LazyValue base; | |
| 480 | ||
| 481 | IrAnalyze *ira; | |
| 482 | Stage1AirInst *payload_type; | |
| 483 | }; | |
| 484 | ||
| 485 | struct 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 | ||
| 498 | struct LazyValueErrUnionType { | |
| 499 | LazyValue base; | |
| 500 | ||
| 501 | IrAnalyze *ira; | |
| 502 | Stage1AirInst *err_set_type; | |
| 503 | Stage1AirInst *payload_type; | |
| 504 | Buf *type_name; | |
| 505 | }; | |
| 506 | ||
| 507 | struct 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 | ||
| 559 | enum ReturnKnowledge { | |
| 560 | ReturnKnowledgeUnknown, | |
| 561 | ReturnKnowledgeKnownError, | |
| 562 | ReturnKnowledgeKnownNonError, | |
| 563 | ReturnKnowledgeKnownNull, | |
| 564 | ReturnKnowledgeKnownNonNull, | |
| 565 | ReturnKnowledgeSkipDefers, | |
| 566 | }; | |
| 567 | ||
| 568 | enum VisibMod { | |
| 569 | VisibModPrivate, | |
| 570 | VisibModPub, | |
| 571 | }; | |
| 572 | ||
| 573 | enum GlobalLinkageId { | |
| 574 | GlobalLinkageIdInternal, | |
| 575 | GlobalLinkageIdStrong, | |
| 576 | GlobalLinkageIdWeak, | |
| 577 | GlobalLinkageIdLinkOnce, | |
| 578 | }; | |
| 579 | ||
| 580 | enum TldId { | |
| 581 | TldIdVar, | |
| 582 | TldIdFn, | |
| 583 | TldIdContainer, | |
| 584 | TldIdCompTime, | |
| 585 | TldIdUsingNamespace, | |
| 586 | }; | |
| 587 | ||
| 588 | enum TldResolution { | |
| 589 | TldResolutionUnresolved, | |
| 590 | TldResolutionResolving, | |
| 591 | TldResolutionInvalid, | |
| 592 | TldResolutionOkLazy, | |
| 593 | TldResolutionOk, | |
| 594 | }; | |
| 595 | ||
| 596 | struct 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 | ||
| 607 | struct TldVar { | |
| 608 | Tld base; | |
| 609 | ||
| 610 | ZigVar *var; | |
| 611 | Buf *extern_lib_name; | |
| 612 | bool analyzing_type; // flag to detect dependency loops | |
| 613 | }; | |
| 614 | ||
| 615 | struct TldFn { | |
| 616 | Tld base; | |
| 617 | ||
| 618 | ZigFn *fn_entry; | |
| 619 | Buf *extern_lib_name; | |
| 620 | }; | |
| 621 | ||
| 622 | struct TldContainer { | |
| 623 | Tld base; | |
| 624 | ||
| 625 | ScopeDecls *decls_scope; | |
| 626 | ZigType *type_entry; | |
| 627 | }; | |
| 628 | ||
| 629 | struct TldCompTime { | |
| 630 | Tld base; | |
| 631 | }; | |
| 632 | ||
| 633 | struct TldUsingNamespace { | |
| 634 | Tld base; | |
| 635 | ||
| 636 | ZigValue *using_namespace_value; | |
| 637 | }; | |
| 638 | ||
| 639 | struct TypeEnumField { | |
| 640 | Buf *name; | |
| 641 | BigInt value; | |
| 642 | uint32_t decl_index; | |
| 643 | AstNode *decl_node; | |
| 644 | }; | |
| 645 | ||
| 646 | struct 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 | ||
| 656 | enum 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 | ||
| 714 | enum FnInline { | |
| 715 | FnInlineAuto, | |
| 716 | FnInlineAlways, | |
| 717 | FnInlineNever, | |
| 718 | }; | |
| 719 | ||
| 720 | struct 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 | ||
| 748 | struct AstNodeFnDef { | |
| 749 | AstNode *fn_proto; | |
| 750 | AstNode *body; | |
| 751 | }; | |
| 752 | ||
| 753 | struct 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 | ||
| 763 | struct AstNodeBlock { | |
| 764 | Buf *name; | |
| 765 | ZigList<AstNode *> statements; | |
| 766 | }; | |
| 767 | ||
| 768 | enum ReturnKind { | |
| 769 | ReturnKindUnconditional, | |
| 770 | ReturnKindError, | |
| 771 | }; | |
| 772 | ||
| 773 | struct AstNodeReturnExpr { | |
| 774 | ReturnKind kind; | |
| 775 | // might be null in case of return void; | |
| 776 | AstNode *expr; | |
| 777 | }; | |
| 778 | ||
| 779 | struct 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 | ||
| 789 | struct 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 | ||
| 810 | struct AstNodeTestDecl { | |
| 811 | // nullptr if the test declaration has no name | |
| 812 | Buf *name; | |
| 813 | ||
| 814 | AstNode *body; | |
| 815 | }; | |
| 816 | ||
| 817 | enum 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 | ||
| 869 | struct AstNodeBinOpExpr { | |
| 870 | AstNode *op1; | |
| 871 | BinOpType bin_op; | |
| 872 | AstNode *op2; | |
| 873 | }; | |
| 874 | ||
| 875 | struct AstNodeCatchExpr { | |
| 876 | AstNode *op1; | |
| 877 | AstNode *symbol; // can be null | |
| 878 | AstNode *op2; | |
| 879 | }; | |
| 880 | ||
| 881 | struct AstNodeUnwrapOptional { | |
| 882 | AstNode *expr; | |
| 883 | }; | |
| 884 | ||
| 885 | // Must be synchronized with std.builtin.CallOptions.Modifier | |
| 886 | enum 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 | ||
| 900 | struct 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 | |
| 908 | enum PrefetchRw { | |
| 909 | PrefetchRwRead, | |
| 910 | PrefetchRwWrite, | |
| 911 | }; | |
| 912 | ||
| 913 | // Must be kept in sync with std.builtin.PrefetchOptions.Cache | |
| 914 | enum PrefetchCache { | |
| 915 | PrefetchCacheInstruction, | |
| 916 | PrefetchCacheData, | |
| 917 | }; | |
| 918 | ||
| 919 | struct AstNodeArrayAccessExpr { | |
| 920 | AstNode *array_ref_expr; | |
| 921 | AstNode *subscript; | |
| 922 | }; | |
| 923 | ||
| 924 | struct AstNodeSliceExpr { | |
| 925 | AstNode *array_ref_expr; | |
| 926 | AstNode *start; | |
| 927 | AstNode *end; | |
| 928 | AstNode *sentinel; // can be null | |
| 929 | }; | |
| 930 | ||
| 931 | struct AstNodeFieldAccessExpr { | |
| 932 | AstNode *struct_expr; | |
| 933 | Buf *field_name; | |
| 934 | }; | |
| 935 | ||
| 936 | struct AstNodePtrDerefExpr { | |
| 937 | AstNode *target; | |
| 938 | }; | |
| 939 | ||
| 940 | enum PrefixOp { | |
| 941 | PrefixOpInvalid, | |
| 942 | PrefixOpBoolNot, | |
| 943 | PrefixOpBinNot, | |
| 944 | PrefixOpNegation, | |
| 945 | PrefixOpNegationWrap, | |
| 946 | PrefixOpOptional, | |
| 947 | PrefixOpAddrOf, | |
| 948 | }; | |
| 949 | ||
| 950 | struct AstNodePrefixOpExpr { | |
| 951 | PrefixOp prefix_op; | |
| 952 | AstNode *primary_expr; | |
| 953 | }; | |
| 954 | ||
| 955 | struct 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 | ||
| 968 | struct AstNodeInferredArrayType { | |
| 969 | AstNode *sentinel; // can be null | |
| 970 | AstNode *child_type; | |
| 971 | }; | |
| 972 | ||
| 973 | struct 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 | ||
| 983 | struct AstNodeUsingNamespace { | |
| 984 | VisibMod visib_mod; | |
| 985 | AstNode *expr; | |
| 986 | }; | |
| 987 | ||
| 988 | struct AstNodeIfBoolExpr { | |
| 989 | AstNode *condition; | |
| 990 | AstNode *then_block; | |
| 991 | AstNode *else_node; // null, block node, or other if expr node | |
| 992 | }; | |
| 993 | ||
| 994 | struct 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 | ||
| 1003 | struct 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 | ||
| 1011 | struct 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 | ||
| 1023 | struct 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 | ||
| 1034 | struct AstNodeSwitchExpr { | |
| 1035 | AstNode *expr; | |
| 1036 | ZigList<AstNode *> prongs; | |
| 1037 | }; | |
| 1038 | ||
| 1039 | struct 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 | ||
| 1048 | struct AstNodeSwitchRange { | |
| 1049 | AstNode *start; | |
| 1050 | AstNode *end; | |
| 1051 | }; | |
| 1052 | ||
| 1053 | struct AstNodeCompTime { | |
| 1054 | AstNode *expr; | |
| 1055 | }; | |
| 1056 | ||
| 1057 | struct AstNodeNoSuspend { | |
| 1058 | AstNode *expr; | |
| 1059 | }; | |
| 1060 | ||
| 1061 | struct AsmOutput { | |
| 1062 | Buf *asm_symbolic_name; | |
| 1063 | Buf *constraint; | |
| 1064 | Buf *variable_name; | |
| 1065 | AstNode *return_type; // null unless "=r" and return | |
| 1066 | }; | |
| 1067 | ||
| 1068 | struct AsmInput { | |
| 1069 | Buf *asm_symbolic_name; | |
| 1070 | Buf *constraint; | |
| 1071 | AstNode *expr; | |
| 1072 | }; | |
| 1073 | ||
| 1074 | struct SrcPos { | |
| 1075 | size_t line; | |
| 1076 | size_t column; | |
| 1077 | }; | |
| 1078 | ||
| 1079 | enum AsmTokenId { | |
| 1080 | AsmTokenIdTemplate, | |
| 1081 | AsmTokenIdPercent, | |
| 1082 | AsmTokenIdVar, | |
| 1083 | AsmTokenIdUniqueId, | |
| 1084 | }; | |
| 1085 | ||
| 1086 | struct AsmToken { | |
| 1087 | enum AsmTokenId id; | |
| 1088 | size_t start; | |
| 1089 | size_t end; | |
| 1090 | }; | |
| 1091 | ||
| 1092 | struct 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 | ||
| 1100 | enum ContainerKind { | |
| 1101 | ContainerKindStruct, | |
| 1102 | ContainerKindEnum, | |
| 1103 | ContainerKindUnion, | |
| 1104 | ContainerKindOpaque, | |
| 1105 | }; | |
| 1106 | ||
| 1107 | enum ContainerLayout { | |
| 1108 | ContainerLayoutAuto, | |
| 1109 | ContainerLayoutExtern, | |
| 1110 | ContainerLayoutPacked, | |
| 1111 | }; | |
| 1112 | ||
| 1113 | struct 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 | ||
| 1126 | struct AstNodeErrorSetField { | |
| 1127 | TokenIndex doc_comments; | |
| 1128 | AstNode *field_name; | |
| 1129 | }; | |
| 1130 | ||
| 1131 | struct AstNodeErrorSetDecl { | |
| 1132 | // Each AstNode could be AstNodeErrorSetField or just AstNodeSymbolExpr to save memory | |
| 1133 | ZigList<AstNode *> decls; | |
| 1134 | }; | |
| 1135 | ||
| 1136 | struct 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 | ||
| 1146 | struct AstNodeStructValueField { | |
| 1147 | Buf *name; | |
| 1148 | AstNode *expr; | |
| 1149 | }; | |
| 1150 | ||
| 1151 | enum ContainerInitKind { | |
| 1152 | ContainerInitKindStruct, | |
| 1153 | ContainerInitKindArray, | |
| 1154 | }; | |
| 1155 | ||
| 1156 | struct AstNodeContainerInitExpr { | |
| 1157 | AstNode *type; | |
| 1158 | ZigList<AstNode *> entries; | |
| 1159 | ContainerInitKind kind; | |
| 1160 | }; | |
| 1161 | ||
| 1162 | struct AstNodeIdentifier { | |
| 1163 | Buf *name; | |
| 1164 | bool is_at_syntax; | |
| 1165 | }; | |
| 1166 | ||
| 1167 | struct AstNodeEnumLiteral { | |
| 1168 | Buf *name; | |
| 1169 | }; | |
| 1170 | ||
| 1171 | struct AstNodeBreakExpr { | |
| 1172 | Buf *name; | |
| 1173 | AstNode *expr; // may be null | |
| 1174 | }; | |
| 1175 | ||
| 1176 | struct AstNodeResumeExpr { | |
| 1177 | AstNode *expr; | |
| 1178 | }; | |
| 1179 | ||
| 1180 | struct AstNodeContinueExpr { | |
| 1181 | Buf *name; | |
| 1182 | }; | |
| 1183 | ||
| 1184 | struct AstNodeAwaitExpr { | |
| 1185 | AstNode *expr; | |
| 1186 | }; | |
| 1187 | ||
| 1188 | struct AstNodeSuspend { | |
| 1189 | AstNode *block; | |
| 1190 | }; | |
| 1191 | ||
| 1192 | struct AstNodeAnyFrameType { | |
| 1193 | AstNode *payload_type; // can be NULL | |
| 1194 | }; | |
| 1195 | ||
| 1196 | struct 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 | |
| 1260 | struct FnTypeParamInfo { | |
| 1261 | bool is_noalias; | |
| 1262 | ZigType *type; | |
| 1263 | }; | |
| 1264 | ||
| 1265 | struct GenericFnTypeId { | |
| 1266 | CodeGen *codegen; | |
| 1267 | ZigFn *fn_entry; | |
| 1268 | ZigValue *params; | |
| 1269 | size_t param_count; | |
| 1270 | }; | |
| 1271 | ||
| 1272 | uint32_t generic_fn_type_id_hash(GenericFnTypeId *id); | |
| 1273 | bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b); | |
| 1274 | ||
| 1275 | struct 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 | ||
| 1285 | uint32_t fn_type_id_hash(FnTypeId*); | |
| 1286 | bool fn_type_id_eql(FnTypeId *a, FnTypeId *b); | |
| 1287 | ||
| 1288 | static const uint32_t VECTOR_INDEX_NONE = UINT32_MAX; | |
| 1289 | static const uint32_t VECTOR_INDEX_RUNTIME = UINT32_MAX - 1; | |
| 1290 | ||
| 1291 | struct InferredStructField { | |
| 1292 | ZigType *inferred_struct_type; | |
| 1293 | Buf *field_name; | |
| 1294 | bool already_resolved; | |
| 1295 | }; | |
| 1296 | ||
| 1297 | struct 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 | ||
| 1328 | struct ZigTypeInt { | |
| 1329 | uint32_t bit_count; | |
| 1330 | bool is_signed; | |
| 1331 | }; | |
| 1332 | ||
| 1333 | struct ZigTypeFloat { | |
| 1334 | size_t bit_count; | |
| 1335 | }; | |
| 1336 | ||
| 1337 | // Needs to have the same memory layout as ZigTypeVector | |
| 1338 | struct ZigTypeArray { | |
| 1339 | ZigType *child_type; | |
| 1340 | uint64_t len; | |
| 1341 | ZigValue *sentinel; | |
| 1342 | }; | |
| 1343 | ||
| 1344 | struct 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 | ||
| 1359 | enum ResolveStatus { | |
| 1360 | ResolveStatusUnstarted, | |
| 1361 | ResolveStatusInvalid, | |
| 1362 | ResolveStatusBeingInferred, | |
| 1363 | ResolveStatusZeroBitsKnown, | |
| 1364 | ResolveStatusAlignmentKnown, | |
| 1365 | ResolveStatusSizeKnown, | |
| 1366 | ResolveStatusLLVMFwdDecl, | |
| 1367 | ResolveStatusLLVMFull, | |
| 1368 | }; | |
| 1369 | ||
| 1370 | struct 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 | |
| 1382 | struct 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 | ||
| 1392 | enum StructSpecial { | |
| 1393 | StructSpecialNone, | |
| 1394 | StructSpecialSlice, | |
| 1395 | StructSpecialInferredTuple, | |
| 1396 | StructSpecialInferredStruct, | |
| 1397 | }; | |
| 1398 | ||
| 1399 | struct 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 | ||
| 1424 | struct ZigTypeOptional { | |
| 1425 | ZigType *child_type; | |
| 1426 | ResolveStatus resolve_status; | |
| 1427 | }; | |
| 1428 | ||
| 1429 | struct ZigTypeErrorUnion { | |
| 1430 | ZigType *err_set_type; | |
| 1431 | ZigType *payload_type; | |
| 1432 | size_t pad_bytes; | |
| 1433 | LLVMTypeRef pad_llvm_type; | |
| 1434 | }; | |
| 1435 | ||
| 1436 | struct ZigTypeErrorSet { | |
| 1437 | ErrorTableEntry **errors; | |
| 1438 | ZigFn *infer_fn; | |
| 1439 | uint32_t err_count; | |
| 1440 | bool incomplete; | |
| 1441 | }; | |
| 1442 | ||
| 1443 | struct 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 | ||
| 1463 | uint32_t type_ptr_hash(const ZigType *ptr); | |
| 1464 | bool type_ptr_eql(const ZigType *a, const ZigType *b); | |
| 1465 | ||
| 1466 | uint32_t pkg_ptr_hash(const ZigPackage *ptr); | |
| 1467 | bool pkg_ptr_eql(const ZigPackage *a, const ZigPackage *b); | |
| 1468 | ||
| 1469 | uint32_t tld_ptr_hash(const Tld *ptr); | |
| 1470 | bool tld_ptr_eql(const Tld *a, const Tld *b); | |
| 1471 | ||
| 1472 | uint32_t node_ptr_hash(const AstNode *ptr); | |
| 1473 | bool node_ptr_eql(const AstNode *a, const AstNode *b); | |
| 1474 | ||
| 1475 | uint32_t fn_ptr_hash(const ZigFn *ptr); | |
| 1476 | bool fn_ptr_eql(const ZigFn *a, const ZigFn *b); | |
| 1477 | ||
| 1478 | uint32_t err_ptr_hash(const ErrorTableEntry *ptr); | |
| 1479 | bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b); | |
| 1480 | ||
| 1481 | struct 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 | ||
| 1507 | struct FnGenParamInfo { | |
| 1508 | size_t src_index; | |
| 1509 | size_t gen_index; | |
| 1510 | bool is_byval; | |
| 1511 | ZigType *type; | |
| 1512 | }; | |
| 1513 | ||
| 1514 | struct 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 | ||
| 1527 | struct ZigTypeBoundFn { | |
| 1528 | ZigType *fn_type; | |
| 1529 | }; | |
| 1530 | ||
| 1531 | // Needs to have the same memory layout as ZigTypeArray | |
| 1532 | struct 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 | |
| 1540 | static_assert(sizeof(ZigTypeVector) == sizeof(ZigTypeArray), "Size of ZigTypeVector and ZigTypeArray do not match!"); | |
| 1541 | ||
| 1542 | enum 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 | ||
| 1571 | enum OnePossibleValue { | |
| 1572 | OnePossibleValueInvalid, | |
| 1573 | OnePossibleValueNo, | |
| 1574 | OnePossibleValueYes, | |
| 1575 | }; | |
| 1576 | ||
| 1577 | struct ZigTypeOpaque { | |
| 1578 | AstNode *decl_node; | |
| 1579 | Buf *bare_name; | |
| 1580 | ||
| 1581 | ScopeDecls *decls_scope; | |
| 1582 | }; | |
| 1583 | ||
| 1584 | struct 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 | ||
| 1595 | struct ZigTypeAnyFrame { | |
| 1596 | ZigType *result_type; // null if `anyframe` instead of `anyframe->T` | |
| 1597 | LLVMTypeRef struct_llvm_ty; | |
| 1598 | }; | |
| 1599 | ||
| 1600 | struct 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 | ||
| 1648 | enum FnAnalState { | |
| 1649 | FnAnalStateReady, | |
| 1650 | FnAnalStateProbing, | |
| 1651 | FnAnalStateComplete, | |
| 1652 | FnAnalStateInvalid, | |
| 1653 | }; | |
| 1654 | ||
| 1655 | struct GlobalExport { | |
| 1656 | Buf name; | |
| 1657 | GlobalLinkageId linkage; | |
| 1658 | }; | |
| 1659 | ||
| 1660 | struct 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 | ||
| 1723 | static inline bool fn_is_test(const ZigFn *fn) { | |
| 1724 | return fn->proto_node->type == NodeTypeTestDecl; | |
| 1725 | } | |
| 1726 | ||
| 1727 | uint32_t fn_table_entry_hash(ZigFn*); | |
| 1728 | bool fn_table_entry_eql(ZigFn *a, ZigFn *b); | |
| 1729 | ||
| 1730 | enum 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 | ||
| 1845 | struct BuiltinFnEntry { | |
| 1846 | BuiltinFnId id; | |
| 1847 | Buf name; | |
| 1848 | size_t param_count; | |
| 1849 | }; | |
| 1850 | ||
| 1851 | enum 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 | ||
| 1883 | uint32_t fn_eval_hash(Scope*); | |
| 1884 | bool fn_eval_eql(Scope *a, Scope *b); | |
| 1885 | ||
| 1886 | struct 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 | ||
| 1927 | uint32_t type_id_hash(TypeId const *); | |
| 1928 | bool type_id_eql(TypeId const *a, TypeId const *b); | |
| 1929 | ||
| 1930 | enum 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. | |
| 1943 | enum AddSubMul { | |
| 1944 | AddSubMulAdd = 0, | |
| 1945 | AddSubMulSub = 1, | |
| 1946 | AddSubMulMul = 2, | |
| 1947 | }; | |
| 1948 | ||
| 1949 | struct 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 | ||
| 1987 | uint32_t zig_llvm_fn_key_hash(ZigLLVMFnKey const *); | |
| 1988 | bool zig_llvm_fn_key_eql(ZigLLVMFnKey const *a, ZigLLVMFnKey const *b); | |
| 1989 | ||
| 1990 | struct TimeEvent { | |
| 1991 | double time; | |
| 1992 | const char *name; | |
| 1993 | }; | |
| 1994 | ||
| 1995 | struct CFile { | |
| 1996 | ZigList<const char *> args; | |
| 1997 | const char *source_path; | |
| 1998 | const char *preprocessor_only_basename; | |
| 1999 | }; | |
| 2000 | ||
| 2001 | struct 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 | ||
| 2216 | struct 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 | ||
| 2252 | struct 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 | ||
| 2263 | enum 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 | ||
| 2280 | struct 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 | |
| 2294 | struct 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 | ||
| 2311 | enum LVal { | |
| 2312 | LValNone, | |
| 2313 | LValPtr, | |
| 2314 | LValAssign, | |
| 2315 | }; | |
| 2316 | ||
| 2317 | // This scope comes from a block expression in user code. | |
| 2318 | // NodeTypeBlock | |
| 2319 | struct 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 | |
| 2341 | struct 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 | |
| 2348 | struct 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 | |
| 2356 | struct 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 | |
| 2365 | struct 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 | |
| 2374 | struct 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 | |
| 2393 | struct 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. | |
| 2402 | struct ScopeSuspend { | |
| 2403 | Scope base; | |
| 2404 | ||
| 2405 | bool reported_err; | |
| 2406 | }; | |
| 2407 | ||
| 2408 | // This scope is created for a comptime expression. | |
| 2409 | // NodeTypeCompTime, NodeTypeSwitchExpr | |
| 2410 | struct ScopeCompTime { | |
| 2411 | Scope base; | |
| 2412 | }; | |
| 2413 | ||
| 2414 | // This scope is created for a nosuspend expression. | |
| 2415 | // NodeTypeNoSuspend | |
| 2416 | struct ScopeNoSuspend { | |
| 2417 | Scope base; | |
| 2418 | }; | |
| 2419 | ||
| 2420 | // This scope is created for a function definition. | |
| 2421 | // NodeTypeFnDef | |
| 2422 | struct 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 | |
| 2431 | struct ScopeTypeOf { | |
| 2432 | Scope base; | |
| 2433 | }; | |
| 2434 | ||
| 2435 | enum 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. | |
| 2444 | struct 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 | |
| 2457 | enum AtomicOrder { | |
| 2458 | AtomicOrderUnordered, | |
| 2459 | AtomicOrderMonotonic, | |
| 2460 | AtomicOrderAcquire, | |
| 2461 | AtomicOrderRelease, | |
| 2462 | AtomicOrderAcqRel, | |
| 2463 | AtomicOrderSeqCst, | |
| 2464 | }; | |
| 2465 | ||
| 2466 | // synchronized with code in define_builtin_compile_vars | |
| 2467 | enum 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 | |
| 2478 | enum 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. | |
| 2494 | struct 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 | ||
| 2509 | struct 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. | |
| 2531 | enum 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. | |
| 2679 | enum 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 | ||
| 2774 | struct 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 | ||
| 2793 | struct 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 | ||
| 2815 | struct Stage1ZirInstDeclVar { | |
| 2816 | Stage1ZirInst base; | |
| 2817 | ||
| 2818 | ZigVar *var; | |
| 2819 | Stage1ZirInst *var_type; | |
| 2820 | Stage1ZirInst *align_value; | |
| 2821 | Stage1ZirInst *ptr; | |
| 2822 | }; | |
| 2823 | ||
| 2824 | struct Stage1AirInstDeclVar { | |
| 2825 | Stage1AirInst base; | |
| 2826 | ||
| 2827 | ZigVar *var; | |
| 2828 | Stage1AirInst *var_ptr; | |
| 2829 | }; | |
| 2830 | ||
| 2831 | struct 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 | ||
| 2841 | struct Stage1AirInstCondBr { | |
| 2842 | Stage1AirInst base; | |
| 2843 | ||
| 2844 | Stage1AirInst *condition; | |
| 2845 | Stage1AirBasicBlock *then_block; | |
| 2846 | Stage1AirBasicBlock *else_block; | |
| 2847 | }; | |
| 2848 | ||
| 2849 | struct Stage1ZirInstBr { | |
| 2850 | Stage1ZirInst base; | |
| 2851 | ||
| 2852 | Stage1ZirBasicBlock *dest_block; | |
| 2853 | Stage1ZirInst *is_comptime; | |
| 2854 | }; | |
| 2855 | ||
| 2856 | struct Stage1AirInstBr { | |
| 2857 | Stage1AirInst base; | |
| 2858 | ||
| 2859 | Stage1AirBasicBlock *dest_block; | |
| 2860 | }; | |
| 2861 | ||
| 2862 | struct Stage1ZirInstSwitchBrCase { | |
| 2863 | Stage1ZirInst *value; | |
| 2864 | Stage1ZirBasicBlock *block; | |
| 2865 | }; | |
| 2866 | ||
| 2867 | struct 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 | ||
| 2878 | struct Stage1AirInstSwitchBrCase { | |
| 2879 | Stage1AirInst *value; | |
| 2880 | Stage1AirBasicBlock *block; | |
| 2881 | }; | |
| 2882 | ||
| 2883 | struct Stage1AirInstSwitchBr { | |
| 2884 | Stage1AirInst base; | |
| 2885 | ||
| 2886 | Stage1AirInst *target_value; | |
| 2887 | Stage1AirBasicBlock *else_block; | |
| 2888 | size_t case_count; | |
| 2889 | Stage1AirInstSwitchBrCase *cases; | |
| 2890 | }; | |
| 2891 | ||
| 2892 | struct Stage1ZirInstSwitchVar { | |
| 2893 | Stage1ZirInst base; | |
| 2894 | ||
| 2895 | Stage1ZirInst *target_value_ptr; | |
| 2896 | Stage1ZirInst **prongs_ptr; | |
| 2897 | size_t prongs_len; | |
| 2898 | }; | |
| 2899 | ||
| 2900 | struct Stage1ZirInstSwitchElseVar { | |
| 2901 | Stage1ZirInst base; | |
| 2902 | ||
| 2903 | Stage1ZirInst *target_value_ptr; | |
| 2904 | Stage1ZirInstSwitchBr *switch_br; | |
| 2905 | }; | |
| 2906 | ||
| 2907 | struct Stage1ZirInstSwitchTarget { | |
| 2908 | Stage1ZirInst base; | |
| 2909 | ||
| 2910 | Stage1ZirInst *target_value_ptr; | |
| 2911 | }; | |
| 2912 | ||
| 2913 | struct 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 | ||
| 2923 | struct Stage1AirInstPhi { | |
| 2924 | Stage1AirInst base; | |
| 2925 | ||
| 2926 | size_t incoming_count; | |
| 2927 | Stage1AirBasicBlock **incoming_blocks; | |
| 2928 | Stage1AirInst **incoming_values; | |
| 2929 | }; | |
| 2930 | ||
| 2931 | enum IrUnOp { | |
| 2932 | IrUnOpInvalid, | |
| 2933 | IrUnOpBinNot, | |
| 2934 | IrUnOpNegation, | |
| 2935 | IrUnOpNegationWrap, | |
| 2936 | IrUnOpDereference, | |
| 2937 | IrUnOpOptional, | |
| 2938 | }; | |
| 2939 | ||
| 2940 | struct Stage1ZirInstUnOp { | |
| 2941 | Stage1ZirInst base; | |
| 2942 | ||
| 2943 | IrUnOp op_id; | |
| 2944 | LVal lval; | |
| 2945 | Stage1ZirInst *value; | |
| 2946 | ResultLoc *result_loc; | |
| 2947 | }; | |
| 2948 | ||
| 2949 | struct Stage1AirInstBinaryNot { | |
| 2950 | Stage1AirInst base; | |
| 2951 | Stage1AirInst *operand; | |
| 2952 | }; | |
| 2953 | ||
| 2954 | struct Stage1AirInstNegation { | |
| 2955 | Stage1AirInst base; | |
| 2956 | Stage1AirInst *operand; | |
| 2957 | bool wrapping; | |
| 2958 | }; | |
| 2959 | ||
| 2960 | enum 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 | ||
| 3000 | struct Stage1ZirInstBinOp { | |
| 3001 | Stage1ZirInst base; | |
| 3002 | ||
| 3003 | Stage1ZirInst *op1; | |
| 3004 | Stage1ZirInst *op2; | |
| 3005 | IrBinOp op_id; | |
| 3006 | bool safety_check_on; | |
| 3007 | }; | |
| 3008 | ||
| 3009 | struct Stage1AirInstBinOp { | |
| 3010 | Stage1AirInst base; | |
| 3011 | ||
| 3012 | Stage1AirInst *op1; | |
| 3013 | Stage1AirInst *op2; | |
| 3014 | IrBinOp op_id; | |
| 3015 | bool safety_check_on; | |
| 3016 | }; | |
| 3017 | ||
| 3018 | struct Stage1ZirInstMergeErrSets { | |
| 3019 | Stage1ZirInst base; | |
| 3020 | ||
| 3021 | Stage1ZirInst *op1; | |
| 3022 | Stage1ZirInst *op2; | |
| 3023 | Buf *type_name; | |
| 3024 | }; | |
| 3025 | ||
| 3026 | struct Stage1ZirInstLoadPtr { | |
| 3027 | Stage1ZirInst base; | |
| 3028 | ||
| 3029 | Stage1ZirInst *ptr; | |
| 3030 | }; | |
| 3031 | ||
| 3032 | struct Stage1AirInstLoadPtr { | |
| 3033 | Stage1AirInst base; | |
| 3034 | ||
| 3035 | Stage1AirInst *ptr; | |
| 3036 | Stage1AirInst *result_loc; | |
| 3037 | }; | |
| 3038 | ||
| 3039 | struct Stage1ZirInstStorePtr { | |
| 3040 | Stage1ZirInst base; | |
| 3041 | ||
| 3042 | Stage1ZirInst *ptr; | |
| 3043 | Stage1ZirInst *value; | |
| 3044 | ||
| 3045 | bool allow_write_through_const; | |
| 3046 | }; | |
| 3047 | ||
| 3048 | struct Stage1AirInstStorePtr { | |
| 3049 | Stage1AirInst base; | |
| 3050 | ||
| 3051 | Stage1AirInst *ptr; | |
| 3052 | Stage1AirInst *value; | |
| 3053 | }; | |
| 3054 | ||
| 3055 | struct Stage1AirInstVectorStoreElem { | |
| 3056 | Stage1AirInst base; | |
| 3057 | ||
| 3058 | Stage1AirInst *vector_ptr; | |
| 3059 | Stage1AirInst *index; | |
| 3060 | Stage1AirInst *value; | |
| 3061 | }; | |
| 3062 | ||
| 3063 | struct Stage1ZirInstFieldPtr { | |
| 3064 | Stage1ZirInst base; | |
| 3065 | ||
| 3066 | Stage1ZirInst *container_ptr; | |
| 3067 | Buf *field_name_buffer; | |
| 3068 | Stage1ZirInst *field_name_expr; | |
| 3069 | bool initializing; | |
| 3070 | }; | |
| 3071 | ||
| 3072 | struct Stage1AirInstStructFieldPtr { | |
| 3073 | Stage1AirInst base; | |
| 3074 | ||
| 3075 | Stage1AirInst *struct_ptr; | |
| 3076 | TypeStructField *field; | |
| 3077 | bool is_const; | |
| 3078 | }; | |
| 3079 | ||
| 3080 | struct Stage1AirInstUnionFieldPtr { | |
| 3081 | Stage1AirInst base; | |
| 3082 | ||
| 3083 | Stage1AirInst *union_ptr; | |
| 3084 | TypeUnionField *field; | |
| 3085 | bool safety_check_on; | |
| 3086 | bool initializing; | |
| 3087 | }; | |
| 3088 | ||
| 3089 | struct 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 | ||
| 3099 | struct Stage1AirInstElemPtr { | |
| 3100 | Stage1AirInst base; | |
| 3101 | ||
| 3102 | Stage1AirInst *array_ptr; | |
| 3103 | Stage1AirInst *elem_index; | |
| 3104 | bool safety_check_on; | |
| 3105 | }; | |
| 3106 | ||
| 3107 | struct Stage1ZirInstVarPtr { | |
| 3108 | Stage1ZirInst base; | |
| 3109 | ||
| 3110 | ZigVar *var; | |
| 3111 | ScopeFnDef *crossed_fndef_scope; | |
| 3112 | }; | |
| 3113 | ||
| 3114 | struct 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. | |
| 3123 | struct Stage1AirInstReturnPtr { | |
| 3124 | Stage1AirInst base; | |
| 3125 | }; | |
| 3126 | ||
| 3127 | struct 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. | |
| 3145 | struct 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. | |
| 3158 | struct 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. | |
| 3170 | struct 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 | ||
| 3181 | struct 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 | ||
| 3197 | struct Stage1ZirInstConst { | |
| 3198 | Stage1ZirInst base; | |
| 3199 | ||
| 3200 | ZigValue *value; | |
| 3201 | }; | |
| 3202 | ||
| 3203 | struct Stage1AirInstConst { | |
| 3204 | Stage1AirInst base; | |
| 3205 | }; | |
| 3206 | ||
| 3207 | struct 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. | |
| 3216 | struct Stage1AirInstReturn { | |
| 3217 | Stage1AirInst base; | |
| 3218 | ||
| 3219 | Stage1AirInst *operand; | |
| 3220 | }; | |
| 3221 | ||
| 3222 | enum 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 | |
| 3234 | struct Stage1AirInstCast { | |
| 3235 | Stage1AirInst base; | |
| 3236 | ||
| 3237 | Stage1AirInst *value; | |
| 3238 | CastOp cast_op; | |
| 3239 | }; | |
| 3240 | ||
| 3241 | struct 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 | ||
| 3251 | struct Stage1ZirInstContainerInitFieldsField { | |
| 3252 | Buf *name; | |
| 3253 | AstNode *source_node; | |
| 3254 | Stage1ZirInst *result_loc; | |
| 3255 | }; | |
| 3256 | ||
| 3257 | struct Stage1ZirInstContainerInitFields { | |
| 3258 | Stage1ZirInst base; | |
| 3259 | ||
| 3260 | size_t field_count; | |
| 3261 | Stage1ZirInstContainerInitFieldsField *fields; | |
| 3262 | Stage1ZirInst *result_loc; | |
| 3263 | }; | |
| 3264 | ||
| 3265 | struct Stage1ZirInstUnreachable { | |
| 3266 | Stage1ZirInst base; | |
| 3267 | }; | |
| 3268 | ||
| 3269 | struct Stage1AirInstUnreachable { | |
| 3270 | Stage1AirInst base; | |
| 3271 | }; | |
| 3272 | ||
| 3273 | struct 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 | ||
| 3283 | struct Stage1ZirInstSetCold { | |
| 3284 | Stage1ZirInst base; | |
| 3285 | ||
| 3286 | Stage1ZirInst *is_cold; | |
| 3287 | }; | |
| 3288 | ||
| 3289 | struct Stage1ZirInstSetRuntimeSafety { | |
| 3290 | Stage1ZirInst base; | |
| 3291 | ||
| 3292 | Stage1ZirInst *safety_on; | |
| 3293 | }; | |
| 3294 | ||
| 3295 | struct Stage1ZirInstSetFloatMode { | |
| 3296 | Stage1ZirInst base; | |
| 3297 | ||
| 3298 | Stage1ZirInst *scope_value; | |
| 3299 | Stage1ZirInst *mode_value; | |
| 3300 | }; | |
| 3301 | ||
| 3302 | struct Stage1ZirInstArrayType { | |
| 3303 | Stage1ZirInst base; | |
| 3304 | ||
| 3305 | Stage1ZirInst *size; | |
| 3306 | Stage1ZirInst *sentinel; | |
| 3307 | Stage1ZirInst *child_type; | |
| 3308 | }; | |
| 3309 | ||
| 3310 | struct Stage1ZirInstPtrTypeSimple { | |
| 3311 | Stage1ZirInst base; | |
| 3312 | ||
| 3313 | Stage1ZirInst *child_type; | |
| 3314 | }; | |
| 3315 | ||
| 3316 | struct 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 | ||
| 3330 | struct Stage1ZirInstAnyFrameType { | |
| 3331 | Stage1ZirInst base; | |
| 3332 | ||
| 3333 | Stage1ZirInst *payload_type; | |
| 3334 | }; | |
| 3335 | ||
| 3336 | struct 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 | ||
| 3347 | struct 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 | ||
| 3359 | struct 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 | ||
| 3372 | struct Stage1ZirInstSizeOf { | |
| 3373 | Stage1ZirInst base; | |
| 3374 | ||
| 3375 | Stage1ZirInst *type_value; | |
| 3376 | bool bit_size; | |
| 3377 | }; | |
| 3378 | ||
| 3379 | // returns true if nonnull, returns false if null | |
| 3380 | struct Stage1ZirInstTestNonNull { | |
| 3381 | Stage1ZirInst base; | |
| 3382 | ||
| 3383 | Stage1ZirInst *value; | |
| 3384 | }; | |
| 3385 | ||
| 3386 | struct 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. | |
| 3394 | struct Stage1ZirInstOptionalUnwrapPtr { | |
| 3395 | Stage1ZirInst base; | |
| 3396 | ||
| 3397 | Stage1ZirInst *base_ptr; | |
| 3398 | bool safety_check_on; | |
| 3399 | }; | |
| 3400 | ||
| 3401 | struct Stage1AirInstOptionalUnwrapPtr { | |
| 3402 | Stage1AirInst base; | |
| 3403 | ||
| 3404 | Stage1AirInst *base_ptr; | |
| 3405 | bool safety_check_on; | |
| 3406 | bool initializing; | |
| 3407 | }; | |
| 3408 | ||
| 3409 | struct Stage1ZirInstCtz { | |
| 3410 | Stage1ZirInst base; | |
| 3411 | ||
| 3412 | Stage1ZirInst *type; | |
| 3413 | Stage1ZirInst *op; | |
| 3414 | }; | |
| 3415 | ||
| 3416 | struct Stage1AirInstCtz { | |
| 3417 | Stage1AirInst base; | |
| 3418 | ||
| 3419 | Stage1AirInst *op; | |
| 3420 | }; | |
| 3421 | ||
| 3422 | struct Stage1ZirInstClz { | |
| 3423 | Stage1ZirInst base; | |
| 3424 | ||
| 3425 | Stage1ZirInst *type; | |
| 3426 | Stage1ZirInst *op; | |
| 3427 | }; | |
| 3428 | ||
| 3429 | struct Stage1AirInstClz { | |
| 3430 | Stage1AirInst base; | |
| 3431 | ||
| 3432 | Stage1AirInst *op; | |
| 3433 | }; | |
| 3434 | ||
| 3435 | struct Stage1ZirInstPopCount { | |
| 3436 | Stage1ZirInst base; | |
| 3437 | ||
| 3438 | Stage1ZirInst *type; | |
| 3439 | Stage1ZirInst *op; | |
| 3440 | }; | |
| 3441 | ||
| 3442 | struct Stage1AirInstPopCount { | |
| 3443 | Stage1AirInst base; | |
| 3444 | ||
| 3445 | Stage1AirInst *op; | |
| 3446 | }; | |
| 3447 | ||
| 3448 | struct Stage1AirInstUnionTag { | |
| 3449 | Stage1AirInst base; | |
| 3450 | ||
| 3451 | Stage1AirInst *value; | |
| 3452 | }; | |
| 3453 | ||
| 3454 | struct Stage1ZirInstImport { | |
| 3455 | Stage1ZirInst base; | |
| 3456 | ||
| 3457 | Stage1ZirInst *name; | |
| 3458 | }; | |
| 3459 | ||
| 3460 | struct Stage1ZirInstRef { | |
| 3461 | Stage1ZirInst base; | |
| 3462 | ||
| 3463 | Stage1ZirInst *value; | |
| 3464 | }; | |
| 3465 | ||
| 3466 | struct Stage1AirInstRef { | |
| 3467 | Stage1AirInst base; | |
| 3468 | ||
| 3469 | Stage1AirInst *operand; | |
| 3470 | Stage1AirInst *result_loc; | |
| 3471 | }; | |
| 3472 | ||
| 3473 | struct Stage1ZirInstCompileErr { | |
| 3474 | Stage1ZirInst base; | |
| 3475 | ||
| 3476 | Stage1ZirInst *msg; | |
| 3477 | }; | |
| 3478 | ||
| 3479 | struct Stage1ZirInstCompileLog { | |
| 3480 | Stage1ZirInst base; | |
| 3481 | ||
| 3482 | size_t msg_count; | |
| 3483 | Stage1ZirInst **msg_list; | |
| 3484 | }; | |
| 3485 | ||
| 3486 | struct Stage1ZirInstErrName { | |
| 3487 | Stage1ZirInst base; | |
| 3488 | ||
| 3489 | Stage1ZirInst *value; | |
| 3490 | }; | |
| 3491 | ||
| 3492 | struct Stage1AirInstErrName { | |
| 3493 | Stage1AirInst base; | |
| 3494 | ||
| 3495 | Stage1AirInst *value; | |
| 3496 | }; | |
| 3497 | ||
| 3498 | struct Stage1ZirInstCImport { | |
| 3499 | Stage1ZirInst base; | |
| 3500 | }; | |
| 3501 | ||
| 3502 | struct Stage1ZirInstCInclude { | |
| 3503 | Stage1ZirInst base; | |
| 3504 | ||
| 3505 | Stage1ZirInst *name; | |
| 3506 | }; | |
| 3507 | ||
| 3508 | struct Stage1ZirInstCDefine { | |
| 3509 | Stage1ZirInst base; | |
| 3510 | ||
| 3511 | Stage1ZirInst *name; | |
| 3512 | Stage1ZirInst *value; | |
| 3513 | }; | |
| 3514 | ||
| 3515 | struct Stage1ZirInstCUndef { | |
| 3516 | Stage1ZirInst base; | |
| 3517 | ||
| 3518 | Stage1ZirInst *name; | |
| 3519 | }; | |
| 3520 | ||
| 3521 | struct Stage1ZirInstEmbedFile { | |
| 3522 | Stage1ZirInst base; | |
| 3523 | ||
| 3524 | Stage1ZirInst *name; | |
| 3525 | }; | |
| 3526 | ||
| 3527 | struct 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 | ||
| 3540 | struct 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 | ||
| 3552 | struct Stage1ZirInstFence { | |
| 3553 | Stage1ZirInst base; | |
| 3554 | ||
| 3555 | Stage1ZirInst *order; | |
| 3556 | }; | |
| 3557 | ||
| 3558 | struct Stage1AirInstFence { | |
| 3559 | Stage1AirInst base; | |
| 3560 | ||
| 3561 | AtomicOrder order; | |
| 3562 | }; | |
| 3563 | ||
| 3564 | struct Stage1ZirInstReduce { | |
| 3565 | Stage1ZirInst base; | |
| 3566 | ||
| 3567 | Stage1ZirInst *op; | |
| 3568 | Stage1ZirInst *value; | |
| 3569 | }; | |
| 3570 | ||
| 3571 | struct Stage1AirInstReduce { | |
| 3572 | Stage1AirInst base; | |
| 3573 | ||
| 3574 | ReduceOp op; | |
| 3575 | Stage1AirInst *value; | |
| 3576 | }; | |
| 3577 | ||
| 3578 | struct Stage1ZirInstTruncate { | |
| 3579 | Stage1ZirInst base; | |
| 3580 | ||
| 3581 | Stage1ZirInst *dest_type; | |
| 3582 | Stage1ZirInst *target; | |
| 3583 | }; | |
| 3584 | ||
| 3585 | struct Stage1AirInstTruncate { | |
| 3586 | Stage1AirInst base; | |
| 3587 | ||
| 3588 | Stage1AirInst *target; | |
| 3589 | }; | |
| 3590 | ||
| 3591 | struct Stage1ZirInstIntCast { | |
| 3592 | Stage1ZirInst base; | |
| 3593 | ||
| 3594 | Stage1ZirInst *dest_type; | |
| 3595 | Stage1ZirInst *target; | |
| 3596 | }; | |
| 3597 | ||
| 3598 | struct Stage1ZirInstFloatCast { | |
| 3599 | Stage1ZirInst base; | |
| 3600 | ||
| 3601 | Stage1ZirInst *dest_type; | |
| 3602 | Stage1ZirInst *target; | |
| 3603 | }; | |
| 3604 | ||
| 3605 | struct Stage1ZirInstErrSetCast { | |
| 3606 | Stage1ZirInst base; | |
| 3607 | ||
| 3608 | Stage1ZirInst *dest_type; | |
| 3609 | Stage1ZirInst *target; | |
| 3610 | }; | |
| 3611 | ||
| 3612 | struct Stage1ZirInstIntToFloat { | |
| 3613 | Stage1ZirInst base; | |
| 3614 | ||
| 3615 | Stage1ZirInst *dest_type; | |
| 3616 | Stage1ZirInst *target; | |
| 3617 | }; | |
| 3618 | ||
| 3619 | struct Stage1ZirInstFloatToInt { | |
| 3620 | Stage1ZirInst base; | |
| 3621 | ||
| 3622 | Stage1ZirInst *dest_type; | |
| 3623 | Stage1ZirInst *target; | |
| 3624 | }; | |
| 3625 | ||
| 3626 | struct Stage1ZirInstBoolToInt { | |
| 3627 | Stage1ZirInst base; | |
| 3628 | ||
| 3629 | Stage1ZirInst *target; | |
| 3630 | }; | |
| 3631 | ||
| 3632 | struct Stage1ZirInstVectorType { | |
| 3633 | Stage1ZirInst base; | |
| 3634 | ||
| 3635 | Stage1ZirInst *len; | |
| 3636 | Stage1ZirInst *elem_type; | |
| 3637 | }; | |
| 3638 | ||
| 3639 | struct Stage1ZirInstBoolNot { | |
| 3640 | Stage1ZirInst base; | |
| 3641 | ||
| 3642 | Stage1ZirInst *value; | |
| 3643 | }; | |
| 3644 | ||
| 3645 | struct Stage1AirInstBoolNot { | |
| 3646 | Stage1AirInst base; | |
| 3647 | ||
| 3648 | Stage1AirInst *value; | |
| 3649 | }; | |
| 3650 | ||
| 3651 | struct Stage1ZirInstMemset { | |
| 3652 | Stage1ZirInst base; | |
| 3653 | ||
| 3654 | Stage1ZirInst *dest_ptr; | |
| 3655 | Stage1ZirInst *byte; | |
| 3656 | Stage1ZirInst *count; | |
| 3657 | }; | |
| 3658 | ||
| 3659 | struct Stage1AirInstMemset { | |
| 3660 | Stage1AirInst base; | |
| 3661 | ||
| 3662 | Stage1AirInst *dest_ptr; | |
| 3663 | Stage1AirInst *byte; | |
| 3664 | Stage1AirInst *count; | |
| 3665 | }; | |
| 3666 | ||
| 3667 | struct Stage1ZirInstMemcpy { | |
| 3668 | Stage1ZirInst base; | |
| 3669 | ||
| 3670 | Stage1ZirInst *dest_ptr; | |
| 3671 | Stage1ZirInst *src_ptr; | |
| 3672 | Stage1ZirInst *count; | |
| 3673 | }; | |
| 3674 | ||
| 3675 | struct Stage1AirInstMemcpy { | |
| 3676 | Stage1AirInst base; | |
| 3677 | ||
| 3678 | Stage1AirInst *dest_ptr; | |
| 3679 | Stage1AirInst *src_ptr; | |
| 3680 | Stage1AirInst *count; | |
| 3681 | }; | |
| 3682 | ||
| 3683 | struct Stage1ZirInstWasmMemorySize { | |
| 3684 | Stage1ZirInst base; | |
| 3685 | ||
| 3686 | Stage1ZirInst *index; | |
| 3687 | }; | |
| 3688 | ||
| 3689 | struct Stage1AirInstWasmMemorySize { | |
| 3690 | Stage1AirInst base; | |
| 3691 | ||
| 3692 | Stage1AirInst *index; | |
| 3693 | }; | |
| 3694 | ||
| 3695 | struct Stage1ZirInstWasmMemoryGrow { | |
| 3696 | Stage1ZirInst base; | |
| 3697 | ||
| 3698 | Stage1ZirInst *index; | |
| 3699 | Stage1ZirInst *delta; | |
| 3700 | }; | |
| 3701 | ||
| 3702 | struct Stage1AirInstWasmMemoryGrow { | |
| 3703 | Stage1AirInst base; | |
| 3704 | ||
| 3705 | Stage1AirInst *index; | |
| 3706 | Stage1AirInst *delta; | |
| 3707 | }; | |
| 3708 | ||
| 3709 | struct Stage1ZirInstSrc { | |
| 3710 | Stage1ZirInst base; | |
| 3711 | }; | |
| 3712 | ||
| 3713 | struct Stage1ZirInstPrefetch { | |
| 3714 | Stage1ZirInst base; | |
| 3715 | ||
| 3716 | Stage1ZirInst *ptr; | |
| 3717 | Stage1ZirInst *options; | |
| 3718 | }; | |
| 3719 | ||
| 3720 | struct 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 | ||
| 3731 | struct 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 | ||
| 3742 | struct 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 | ||
| 3753 | struct Stage1ZirInstBreakpoint { | |
| 3754 | Stage1ZirInst base; | |
| 3755 | }; | |
| 3756 | ||
| 3757 | struct Stage1AirInstBreakpoint { | |
| 3758 | Stage1AirInst base; | |
| 3759 | }; | |
| 3760 | ||
| 3761 | struct Stage1ZirInstReturnAddress { | |
| 3762 | Stage1ZirInst base; | |
| 3763 | }; | |
| 3764 | ||
| 3765 | struct Stage1AirInstReturnAddress { | |
| 3766 | Stage1AirInst base; | |
| 3767 | }; | |
| 3768 | ||
| 3769 | struct Stage1ZirInstFrameAddress { | |
| 3770 | Stage1ZirInst base; | |
| 3771 | }; | |
| 3772 | ||
| 3773 | struct Stage1AirInstFrameAddress { | |
| 3774 | Stage1AirInst base; | |
| 3775 | }; | |
| 3776 | ||
| 3777 | struct Stage1ZirInstFrameHandle { | |
| 3778 | Stage1ZirInst base; | |
| 3779 | }; | |
| 3780 | ||
| 3781 | struct Stage1AirInstFrameHandle { | |
| 3782 | Stage1AirInst base; | |
| 3783 | }; | |
| 3784 | ||
| 3785 | struct Stage1ZirInstFrameType { | |
| 3786 | Stage1ZirInst base; | |
| 3787 | ||
| 3788 | Stage1ZirInst *fn; | |
| 3789 | }; | |
| 3790 | ||
| 3791 | struct Stage1ZirInstFrameSize { | |
| 3792 | Stage1ZirInst base; | |
| 3793 | ||
| 3794 | Stage1ZirInst *fn; | |
| 3795 | }; | |
| 3796 | ||
| 3797 | struct Stage1AirInstFrameSize { | |
| 3798 | Stage1AirInst base; | |
| 3799 | ||
| 3800 | Stage1AirInst *fn; | |
| 3801 | }; | |
| 3802 | ||
| 3803 | enum IrOverflowOp { | |
| 3804 | IrOverflowOpAdd, | |
| 3805 | IrOverflowOpSub, | |
| 3806 | IrOverflowOpMul, | |
| 3807 | IrOverflowOpShl, | |
| 3808 | }; | |
| 3809 | ||
| 3810 | struct Stage1ZirInstOverflowOp { | |
| 3811 | Stage1ZirInst base; | |
| 3812 | ||
| 3813 | IrOverflowOp op; | |
| 3814 | Stage1ZirInst *type_value; | |
| 3815 | Stage1ZirInst *op1; | |
| 3816 | Stage1ZirInst *op2; | |
| 3817 | Stage1ZirInst *result_ptr; | |
| 3818 | }; | |
| 3819 | ||
| 3820 | struct 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 | ||
| 3832 | struct Stage1ZirInstMulAdd { | |
| 3833 | Stage1ZirInst base; | |
| 3834 | ||
| 3835 | Stage1ZirInst *type_value; | |
| 3836 | Stage1ZirInst *op1; | |
| 3837 | Stage1ZirInst *op2; | |
| 3838 | Stage1ZirInst *op3; | |
| 3839 | }; | |
| 3840 | ||
| 3841 | struct Stage1AirInstMulAdd { | |
| 3842 | Stage1AirInst base; | |
| 3843 | ||
| 3844 | Stage1AirInst *op1; | |
| 3845 | Stage1AirInst *op2; | |
| 3846 | Stage1AirInst *op3; | |
| 3847 | }; | |
| 3848 | ||
| 3849 | struct Stage1ZirInstAlignOf { | |
| 3850 | Stage1ZirInst base; | |
| 3851 | ||
| 3852 | Stage1ZirInst *type_value; | |
| 3853 | }; | |
| 3854 | ||
| 3855 | // returns true if error, returns false if not error | |
| 3856 | struct Stage1ZirInstTestErr { | |
| 3857 | Stage1ZirInst base; | |
| 3858 | ||
| 3859 | Stage1ZirInst *base_ptr; | |
| 3860 | bool resolve_err_set; | |
| 3861 | bool base_ptr_is_payload; | |
| 3862 | }; | |
| 3863 | ||
| 3864 | struct Stage1AirInstTestErr { | |
| 3865 | Stage1AirInst base; | |
| 3866 | ||
| 3867 | Stage1AirInst *err_union; | |
| 3868 | }; | |
| 3869 | ||
| 3870 | // Takes an error union pointer, returns a pointer to the error code. | |
| 3871 | struct Stage1ZirInstUnwrapErrCode { | |
| 3872 | Stage1ZirInst base; | |
| 3873 | ||
| 3874 | Stage1ZirInst *err_union_ptr; | |
| 3875 | bool initializing; | |
| 3876 | }; | |
| 3877 | ||
| 3878 | struct Stage1AirInstUnwrapErrCode { | |
| 3879 | Stage1AirInst base; | |
| 3880 | ||
| 3881 | Stage1AirInst *err_union_ptr; | |
| 3882 | bool initializing; | |
| 3883 | }; | |
| 3884 | ||
| 3885 | struct Stage1ZirInstUnwrapErrPayload { | |
| 3886 | Stage1ZirInst base; | |
| 3887 | ||
| 3888 | Stage1ZirInst *value; | |
| 3889 | bool safety_check_on; | |
| 3890 | bool initializing; | |
| 3891 | }; | |
| 3892 | ||
| 3893 | struct Stage1AirInstUnwrapErrPayload { | |
| 3894 | Stage1AirInst base; | |
| 3895 | ||
| 3896 | Stage1AirInst *value; | |
| 3897 | bool safety_check_on; | |
| 3898 | bool initializing; | |
| 3899 | }; | |
| 3900 | ||
| 3901 | struct Stage1AirInstOptionalWrap { | |
| 3902 | Stage1AirInst base; | |
| 3903 | ||
| 3904 | Stage1AirInst *operand; | |
| 3905 | Stage1AirInst *result_loc; | |
| 3906 | }; | |
| 3907 | ||
| 3908 | struct Stage1AirInstErrWrapPayload { | |
| 3909 | Stage1AirInst base; | |
| 3910 | ||
| 3911 | Stage1AirInst *operand; | |
| 3912 | Stage1AirInst *result_loc; | |
| 3913 | }; | |
| 3914 | ||
| 3915 | struct Stage1AirInstErrWrapCode { | |
| 3916 | Stage1AirInst base; | |
| 3917 | ||
| 3918 | Stage1AirInst *operand; | |
| 3919 | Stage1AirInst *result_loc; | |
| 3920 | }; | |
| 3921 | ||
| 3922 | struct 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 | |
| 3933 | struct Stage1ZirInstTestComptime { | |
| 3934 | Stage1ZirInst base; | |
| 3935 | ||
| 3936 | Stage1ZirInst *value; | |
| 3937 | }; | |
| 3938 | ||
| 3939 | struct Stage1ZirInstPtrCast { | |
| 3940 | Stage1ZirInst base; | |
| 3941 | ||
| 3942 | Stage1ZirInst *dest_type; | |
| 3943 | Stage1ZirInst *ptr; | |
| 3944 | bool safety_check_on; | |
| 3945 | }; | |
| 3946 | ||
| 3947 | struct Stage1AirInstPtrCast { | |
| 3948 | Stage1AirInst base; | |
| 3949 | ||
| 3950 | Stage1AirInst *ptr; | |
| 3951 | bool safety_check_on; | |
| 3952 | }; | |
| 3953 | ||
| 3954 | struct Stage1ZirInstImplicitCast { | |
| 3955 | Stage1ZirInst base; | |
| 3956 | ||
| 3957 | Stage1ZirInst *operand; | |
| 3958 | ResultLocCast *result_loc_cast; | |
| 3959 | }; | |
| 3960 | ||
| 3961 | struct Stage1ZirInstBitCast { | |
| 3962 | Stage1ZirInst base; | |
| 3963 | ||
| 3964 | Stage1ZirInst *operand; | |
| 3965 | ResultLocBitCast *result_loc_bit_cast; | |
| 3966 | }; | |
| 3967 | ||
| 3968 | struct Stage1AirInstBitCast { | |
| 3969 | Stage1AirInst base; | |
| 3970 | ||
| 3971 | Stage1AirInst *operand; | |
| 3972 | }; | |
| 3973 | ||
| 3974 | struct Stage1AirInstWidenOrShorten { | |
| 3975 | Stage1AirInst base; | |
| 3976 | ||
| 3977 | Stage1AirInst *target; | |
| 3978 | }; | |
| 3979 | ||
| 3980 | struct Stage1ZirInstPtrToInt { | |
| 3981 | Stage1ZirInst base; | |
| 3982 | ||
| 3983 | Stage1ZirInst *target; | |
| 3984 | }; | |
| 3985 | ||
| 3986 | struct Stage1AirInstPtrToInt { | |
| 3987 | Stage1AirInst base; | |
| 3988 | ||
| 3989 | Stage1AirInst *target; | |
| 3990 | }; | |
| 3991 | ||
| 3992 | struct Stage1ZirInstIntToPtr { | |
| 3993 | Stage1ZirInst base; | |
| 3994 | ||
| 3995 | Stage1ZirInst *dest_type; | |
| 3996 | Stage1ZirInst *target; | |
| 3997 | }; | |
| 3998 | ||
| 3999 | struct Stage1AirInstIntToPtr { | |
| 4000 | Stage1AirInst base; | |
| 4001 | ||
| 4002 | Stage1AirInst *target; | |
| 4003 | }; | |
| 4004 | ||
| 4005 | struct Stage1ZirInstIntToEnum { | |
| 4006 | Stage1ZirInst base; | |
| 4007 | ||
| 4008 | Stage1ZirInst *dest_type; | |
| 4009 | Stage1ZirInst *target; | |
| 4010 | }; | |
| 4011 | ||
| 4012 | struct Stage1AirInstIntToEnum { | |
| 4013 | Stage1AirInst base; | |
| 4014 | ||
| 4015 | Stage1AirInst *target; | |
| 4016 | }; | |
| 4017 | ||
| 4018 | struct Stage1ZirInstEnumToInt { | |
| 4019 | Stage1ZirInst base; | |
| 4020 | ||
| 4021 | Stage1ZirInst *target; | |
| 4022 | }; | |
| 4023 | ||
| 4024 | struct Stage1ZirInstIntToErr { | |
| 4025 | Stage1ZirInst base; | |
| 4026 | ||
| 4027 | Stage1ZirInst *target; | |
| 4028 | }; | |
| 4029 | ||
| 4030 | struct Stage1AirInstIntToErr { | |
| 4031 | Stage1AirInst base; | |
| 4032 | ||
| 4033 | Stage1AirInst *target; | |
| 4034 | }; | |
| 4035 | ||
| 4036 | struct Stage1ZirInstErrToInt { | |
| 4037 | Stage1ZirInst base; | |
| 4038 | ||
| 4039 | Stage1ZirInst *target; | |
| 4040 | }; | |
| 4041 | ||
| 4042 | struct Stage1AirInstErrToInt { | |
| 4043 | Stage1AirInst base; | |
| 4044 | ||
| 4045 | Stage1AirInst *target; | |
| 4046 | }; | |
| 4047 | ||
| 4048 | struct Stage1ZirInstCheckSwitchProngsRange { | |
| 4049 | Stage1ZirInst *start; | |
| 4050 | Stage1ZirInst *end; | |
| 4051 | }; | |
| 4052 | ||
| 4053 | struct Stage1ZirInstCheckSwitchProngs { | |
| 4054 | Stage1ZirInst base; | |
| 4055 | ||
| 4056 | Stage1ZirInst *target_value; | |
| 4057 | Stage1ZirInstCheckSwitchProngsRange *ranges; | |
| 4058 | size_t range_count; | |
| 4059 | AstNode* else_prong; | |
| 4060 | }; | |
| 4061 | ||
| 4062 | struct Stage1ZirInstCheckStatementIsVoid { | |
| 4063 | Stage1ZirInst base; | |
| 4064 | ||
| 4065 | Stage1ZirInst *statement_value; | |
| 4066 | }; | |
| 4067 | ||
| 4068 | struct Stage1ZirInstTypeName { | |
| 4069 | Stage1ZirInst base; | |
| 4070 | ||
| 4071 | Stage1ZirInst *type_value; | |
| 4072 | }; | |
| 4073 | ||
| 4074 | struct Stage1ZirInstDeclRef { | |
| 4075 | Stage1ZirInst base; | |
| 4076 | ||
| 4077 | LVal lval; | |
| 4078 | Tld *tld; | |
| 4079 | }; | |
| 4080 | ||
| 4081 | struct Stage1ZirInstPanic { | |
| 4082 | Stage1ZirInst base; | |
| 4083 | ||
| 4084 | Stage1ZirInst *msg; | |
| 4085 | }; | |
| 4086 | ||
| 4087 | struct Stage1AirInstPanic { | |
| 4088 | Stage1AirInst base; | |
| 4089 | ||
| 4090 | Stage1AirInst *msg; | |
| 4091 | }; | |
| 4092 | ||
| 4093 | struct Stage1ZirInstTagName { | |
| 4094 | Stage1ZirInst base; | |
| 4095 | ||
| 4096 | Stage1ZirInst *target; | |
| 4097 | }; | |
| 4098 | ||
| 4099 | struct Stage1AirInstTagName { | |
| 4100 | Stage1AirInst base; | |
| 4101 | ||
| 4102 | Stage1AirInst *target; | |
| 4103 | }; | |
| 4104 | ||
| 4105 | struct Stage1ZirInstFieldParentPtr { | |
| 4106 | Stage1ZirInst base; | |
| 4107 | ||
| 4108 | Stage1ZirInst *type_value; | |
| 4109 | Stage1ZirInst *field_name; | |
| 4110 | Stage1ZirInst *field_ptr; | |
| 4111 | }; | |
| 4112 | ||
| 4113 | struct Stage1AirInstFieldParentPtr { | |
| 4114 | Stage1AirInst base; | |
| 4115 | ||
| 4116 | Stage1AirInst *field_ptr; | |
| 4117 | TypeStructField *field; | |
| 4118 | }; | |
| 4119 | ||
| 4120 | struct Stage1ZirInstOffsetOf { | |
| 4121 | Stage1ZirInst base; | |
| 4122 | ||
| 4123 | Stage1ZirInst *type_value; | |
| 4124 | Stage1ZirInst *field_name; | |
| 4125 | }; | |
| 4126 | ||
| 4127 | struct Stage1ZirInstBitOffsetOf { | |
| 4128 | Stage1ZirInst base; | |
| 4129 | ||
| 4130 | Stage1ZirInst *type_value; | |
| 4131 | Stage1ZirInst *field_name; | |
| 4132 | }; | |
| 4133 | ||
| 4134 | struct Stage1ZirInstTypeInfo { | |
| 4135 | Stage1ZirInst base; | |
| 4136 | ||
| 4137 | Stage1ZirInst *type_value; | |
| 4138 | }; | |
| 4139 | ||
| 4140 | struct Stage1ZirInstType { | |
| 4141 | Stage1ZirInst base; | |
| 4142 | ||
| 4143 | Stage1ZirInst *type_info; | |
| 4144 | }; | |
| 4145 | ||
| 4146 | struct Stage1ZirInstHasField { | |
| 4147 | Stage1ZirInst base; | |
| 4148 | ||
| 4149 | Stage1ZirInst *container_type; | |
| 4150 | Stage1ZirInst *field_name; | |
| 4151 | }; | |
| 4152 | ||
| 4153 | struct Stage1ZirInstSetEvalBranchQuota { | |
| 4154 | Stage1ZirInst base; | |
| 4155 | ||
| 4156 | Stage1ZirInst *new_quota; | |
| 4157 | }; | |
| 4158 | ||
| 4159 | struct Stage1ZirInstAlignCast { | |
| 4160 | Stage1ZirInst base; | |
| 4161 | ||
| 4162 | Stage1ZirInst *align_bytes; | |
| 4163 | Stage1ZirInst *target; | |
| 4164 | }; | |
| 4165 | ||
| 4166 | struct Stage1AirInstAlignCast { | |
| 4167 | Stage1AirInst base; | |
| 4168 | ||
| 4169 | Stage1AirInst *target; | |
| 4170 | }; | |
| 4171 | ||
| 4172 | struct Stage1ZirInstAddrSpaceCast { | |
| 4173 | Stage1ZirInst base; | |
| 4174 | ||
| 4175 | Stage1ZirInst *addrspace; | |
| 4176 | Stage1ZirInst *ptr; | |
| 4177 | }; | |
| 4178 | ||
| 4179 | struct Stage1ZirInstSetAlignStack { | |
| 4180 | Stage1ZirInst base; | |
| 4181 | ||
| 4182 | Stage1ZirInst *align_bytes; | |
| 4183 | }; | |
| 4184 | ||
| 4185 | struct Stage1ZirInstArgType { | |
| 4186 | Stage1ZirInst base; | |
| 4187 | ||
| 4188 | Stage1ZirInst *fn_type; | |
| 4189 | Stage1ZirInst *arg_index; | |
| 4190 | }; | |
| 4191 | ||
| 4192 | struct Stage1ZirInstExport { | |
| 4193 | Stage1ZirInst base; | |
| 4194 | ||
| 4195 | Stage1ZirInst *target; | |
| 4196 | Stage1ZirInst *options; | |
| 4197 | }; | |
| 4198 | ||
| 4199 | struct Stage1ZirInstExtern { | |
| 4200 | Stage1ZirInst base; | |
| 4201 | ||
| 4202 | Stage1ZirInst *type; | |
| 4203 | Stage1ZirInst *options; | |
| 4204 | }; | |
| 4205 | ||
| 4206 | struct Stage1AirInstExtern { | |
| 4207 | Stage1AirInst base; | |
| 4208 | ||
| 4209 | Buf *name; | |
| 4210 | GlobalLinkageId linkage; | |
| 4211 | bool is_thread_local; | |
| 4212 | }; | |
| 4213 | ||
| 4214 | enum IrInstErrorReturnTraceOptional { | |
| 4215 | IrInstErrorReturnTraceNull, | |
| 4216 | IrInstErrorReturnTraceNonNull, | |
| 4217 | }; | |
| 4218 | ||
| 4219 | struct Stage1ZirInstErrorReturnTrace { | |
| 4220 | Stage1ZirInst base; | |
| 4221 | ||
| 4222 | IrInstErrorReturnTraceOptional optional; | |
| 4223 | }; | |
| 4224 | ||
| 4225 | struct Stage1AirInstErrorReturnTrace { | |
| 4226 | Stage1AirInst base; | |
| 4227 | ||
| 4228 | IrInstErrorReturnTraceOptional optional; | |
| 4229 | }; | |
| 4230 | ||
| 4231 | struct Stage1ZirInstErrorUnion { | |
| 4232 | Stage1ZirInst base; | |
| 4233 | ||
| 4234 | Stage1ZirInst *err_set; | |
| 4235 | Stage1ZirInst *payload; | |
| 4236 | Buf *type_name; | |
| 4237 | }; | |
| 4238 | ||
| 4239 | struct Stage1ZirInstAtomicRmw { | |
| 4240 | Stage1ZirInst base; | |
| 4241 | ||
| 4242 | Stage1ZirInst *operand_type; | |
| 4243 | Stage1ZirInst *ptr; | |
| 4244 | Stage1ZirInst *op; | |
| 4245 | Stage1ZirInst *operand; | |
| 4246 | Stage1ZirInst *ordering; | |
| 4247 | }; | |
| 4248 | ||
| 4249 | struct Stage1AirInstAtomicRmw { | |
| 4250 | Stage1AirInst base; | |
| 4251 | ||
| 4252 | Stage1AirInst *ptr; | |
| 4253 | Stage1AirInst *operand; | |
| 4254 | AtomicRmwOp op; | |
| 4255 | AtomicOrder ordering; | |
| 4256 | }; | |
| 4257 | ||
| 4258 | struct Stage1ZirInstAtomicLoad { | |
| 4259 | Stage1ZirInst base; | |
| 4260 | ||
| 4261 | Stage1ZirInst *operand_type; | |
| 4262 | Stage1ZirInst *ptr; | |
| 4263 | Stage1ZirInst *ordering; | |
| 4264 | }; | |
| 4265 | ||
| 4266 | struct Stage1AirInstAtomicLoad { | |
| 4267 | Stage1AirInst base; | |
| 4268 | ||
| 4269 | Stage1AirInst *ptr; | |
| 4270 | AtomicOrder ordering; | |
| 4271 | }; | |
| 4272 | ||
| 4273 | struct Stage1ZirInstAtomicStore { | |
| 4274 | Stage1ZirInst base; | |
| 4275 | ||
| 4276 | Stage1ZirInst *operand_type; | |
| 4277 | Stage1ZirInst *ptr; | |
| 4278 | Stage1ZirInst *value; | |
| 4279 | Stage1ZirInst *ordering; | |
| 4280 | }; | |
| 4281 | ||
| 4282 | struct Stage1AirInstAtomicStore { | |
| 4283 | Stage1AirInst base; | |
| 4284 | ||
| 4285 | Stage1AirInst *ptr; | |
| 4286 | Stage1AirInst *value; | |
| 4287 | AtomicOrder ordering; | |
| 4288 | }; | |
| 4289 | ||
| 4290 | struct Stage1ZirInstSaveErrRetAddr { | |
| 4291 | Stage1ZirInst base; | |
| 4292 | }; | |
| 4293 | ||
| 4294 | struct Stage1AirInstSaveErrRetAddr { | |
| 4295 | Stage1AirInst base; | |
| 4296 | }; | |
| 4297 | ||
| 4298 | struct Stage1ZirInstAddImplicitReturnType { | |
| 4299 | Stage1ZirInst base; | |
| 4300 | ||
| 4301 | Stage1ZirInst *value; | |
| 4302 | ResultLocReturn *result_loc_ret; | |
| 4303 | }; | |
| 4304 | ||
| 4305 | // For float ops that take a single argument | |
| 4306 | struct Stage1ZirInstFloatOp { | |
| 4307 | Stage1ZirInst base; | |
| 4308 | ||
| 4309 | Stage1ZirInst *operand; | |
| 4310 | BuiltinFnId fn_id; | |
| 4311 | }; | |
| 4312 | ||
| 4313 | struct Stage1AirInstFloatOp { | |
| 4314 | Stage1AirInst base; | |
| 4315 | ||
| 4316 | Stage1AirInst *operand; | |
| 4317 | BuiltinFnId fn_id; | |
| 4318 | }; | |
| 4319 | ||
| 4320 | struct Stage1ZirInstCheckRuntimeScope { | |
| 4321 | Stage1ZirInst base; | |
| 4322 | ||
| 4323 | Stage1ZirInst *scope_is_comptime; | |
| 4324 | Stage1ZirInst *is_comptime; | |
| 4325 | }; | |
| 4326 | ||
| 4327 | struct Stage1ZirInstBswap { | |
| 4328 | Stage1ZirInst base; | |
| 4329 | ||
| 4330 | Stage1ZirInst *type; | |
| 4331 | Stage1ZirInst *op; | |
| 4332 | }; | |
| 4333 | ||
| 4334 | struct Stage1AirInstBswap { | |
| 4335 | Stage1AirInst base; | |
| 4336 | ||
| 4337 | Stage1AirInst *op; | |
| 4338 | }; | |
| 4339 | ||
| 4340 | struct Stage1ZirInstBitReverse { | |
| 4341 | Stage1ZirInst base; | |
| 4342 | ||
| 4343 | Stage1ZirInst *type; | |
| 4344 | Stage1ZirInst *op; | |
| 4345 | }; | |
| 4346 | ||
| 4347 | struct Stage1AirInstBitReverse { | |
| 4348 | Stage1AirInst base; | |
| 4349 | ||
| 4350 | Stage1AirInst *op; | |
| 4351 | }; | |
| 4352 | ||
| 4353 | struct Stage1AirInstArrayToVector { | |
| 4354 | Stage1AirInst base; | |
| 4355 | ||
| 4356 | Stage1AirInst *array; | |
| 4357 | }; | |
| 4358 | ||
| 4359 | struct Stage1AirInstVectorToArray { | |
| 4360 | Stage1AirInst base; | |
| 4361 | ||
| 4362 | Stage1AirInst *vector; | |
| 4363 | Stage1AirInst *result_loc; | |
| 4364 | }; | |
| 4365 | ||
| 4366 | struct 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 | ||
| 4375 | struct Stage1AirInstShuffleVector { | |
| 4376 | Stage1AirInst base; | |
| 4377 | ||
| 4378 | Stage1AirInst *a; | |
| 4379 | Stage1AirInst *b; | |
| 4380 | Stage1AirInst *mask; // This is in zig-format, not llvm format | |
| 4381 | }; | |
| 4382 | ||
| 4383 | struct 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 | ||
| 4392 | struct Stage1AirInstSelect { | |
| 4393 | Stage1AirInst base; | |
| 4394 | ||
| 4395 | Stage1AirInst *pred; // This is in zig-format, not llvm format | |
| 4396 | Stage1AirInst *a; | |
| 4397 | Stage1AirInst *b; | |
| 4398 | }; | |
| 4399 | ||
| 4400 | struct Stage1ZirInstSplat { | |
| 4401 | Stage1ZirInst base; | |
| 4402 | ||
| 4403 | Stage1ZirInst *len; | |
| 4404 | Stage1ZirInst *scalar; | |
| 4405 | }; | |
| 4406 | ||
| 4407 | struct Stage1AirInstSplat { | |
| 4408 | Stage1AirInst base; | |
| 4409 | ||
| 4410 | Stage1AirInst *scalar; | |
| 4411 | }; | |
| 4412 | ||
| 4413 | struct Stage1AirInstAssertZero { | |
| 4414 | Stage1AirInst base; | |
| 4415 | ||
| 4416 | Stage1AirInst *target; | |
| 4417 | }; | |
| 4418 | ||
| 4419 | struct Stage1AirInstAssertNonNull { | |
| 4420 | Stage1AirInst base; | |
| 4421 | ||
| 4422 | Stage1AirInst *target; | |
| 4423 | }; | |
| 4424 | ||
| 4425 | struct Stage1ZirInstUnionInitNamedField { | |
| 4426 | Stage1ZirInst base; | |
| 4427 | ||
| 4428 | Stage1ZirInst *union_type; | |
| 4429 | Stage1ZirInst *field_name; | |
| 4430 | Stage1ZirInst *field_result_loc; | |
| 4431 | Stage1ZirInst *result_loc; | |
| 4432 | }; | |
| 4433 | ||
| 4434 | struct Stage1ZirInstHasDecl { | |
| 4435 | Stage1ZirInst base; | |
| 4436 | ||
| 4437 | Stage1ZirInst *container; | |
| 4438 | Stage1ZirInst *name; | |
| 4439 | }; | |
| 4440 | ||
| 4441 | struct Stage1ZirInstUndeclaredIdent { | |
| 4442 | Stage1ZirInst base; | |
| 4443 | ||
| 4444 | Buf *name; | |
| 4445 | }; | |
| 4446 | ||
| 4447 | struct Stage1ZirInstAlloca { | |
| 4448 | Stage1ZirInst base; | |
| 4449 | ||
| 4450 | Stage1ZirInst *align; | |
| 4451 | Stage1ZirInst *is_comptime; | |
| 4452 | const char *name_hint; | |
| 4453 | }; | |
| 4454 | ||
| 4455 | struct Stage1AirInstAlloca { | |
| 4456 | Stage1AirInst base; | |
| 4457 | ||
| 4458 | uint32_t align; | |
| 4459 | const char *name_hint; | |
| 4460 | size_t field_index; | |
| 4461 | }; | |
| 4462 | ||
| 4463 | struct Stage1ZirInstEndExpr { | |
| 4464 | Stage1ZirInst base; | |
| 4465 | ||
| 4466 | Stage1ZirInst *value; | |
| 4467 | ResultLoc *result_loc; | |
| 4468 | }; | |
| 4469 | ||
| 4470 | // This one is for writing through the result pointer. | |
| 4471 | struct Stage1ZirInstResolveResult { | |
| 4472 | Stage1ZirInst base; | |
| 4473 | ||
| 4474 | ResultLoc *result_loc; | |
| 4475 | Stage1ZirInst *ty; | |
| 4476 | }; | |
| 4477 | ||
| 4478 | struct Stage1ZirInstResetResult { | |
| 4479 | Stage1ZirInst base; | |
| 4480 | ||
| 4481 | ResultLoc *result_loc; | |
| 4482 | }; | |
| 4483 | ||
| 4484 | struct Stage1AirInstPtrOfArrayToSlice { | |
| 4485 | Stage1AirInst base; | |
| 4486 | ||
| 4487 | Stage1AirInst *operand; | |
| 4488 | Stage1AirInst *result_loc; | |
| 4489 | }; | |
| 4490 | ||
| 4491 | struct Stage1ZirInstSuspendBegin { | |
| 4492 | Stage1ZirInst base; | |
| 4493 | }; | |
| 4494 | ||
| 4495 | struct Stage1AirInstSuspendBegin { | |
| 4496 | Stage1AirInst base; | |
| 4497 | ||
| 4498 | LLVMBasicBlockRef resume_bb; | |
| 4499 | }; | |
| 4500 | ||
| 4501 | struct Stage1ZirInstSuspendFinish { | |
| 4502 | Stage1ZirInst base; | |
| 4503 | ||
| 4504 | Stage1ZirInstSuspendBegin *begin; | |
| 4505 | }; | |
| 4506 | ||
| 4507 | struct Stage1AirInstSuspendFinish { | |
| 4508 | Stage1AirInst base; | |
| 4509 | ||
| 4510 | Stage1AirInstSuspendBegin *begin; | |
| 4511 | }; | |
| 4512 | ||
| 4513 | struct Stage1ZirInstAwait { | |
| 4514 | Stage1ZirInst base; | |
| 4515 | ||
| 4516 | Stage1ZirInst *frame; | |
| 4517 | ResultLoc *result_loc; | |
| 4518 | bool is_nosuspend; | |
| 4519 | }; | |
| 4520 | ||
| 4521 | struct Stage1AirInstAwait { | |
| 4522 | Stage1AirInst base; | |
| 4523 | ||
| 4524 | Stage1AirInst *frame; | |
| 4525 | Stage1AirInst *result_loc; | |
| 4526 | ZigFn *target_fn; | |
| 4527 | bool is_nosuspend; | |
| 4528 | }; | |
| 4529 | ||
| 4530 | struct Stage1ZirInstResume { | |
| 4531 | Stage1ZirInst base; | |
| 4532 | ||
| 4533 | Stage1ZirInst *frame; | |
| 4534 | }; | |
| 4535 | ||
| 4536 | struct Stage1AirInstResume { | |
| 4537 | Stage1AirInst base; | |
| 4538 | ||
| 4539 | Stage1AirInst *frame; | |
| 4540 | }; | |
| 4541 | ||
| 4542 | enum SpillId { | |
| 4543 | SpillIdInvalid, | |
| 4544 | SpillIdRetErrCode, | |
| 4545 | }; | |
| 4546 | ||
| 4547 | struct Stage1ZirInstSpillBegin { | |
| 4548 | Stage1ZirInst base; | |
| 4549 | ||
| 4550 | Stage1ZirInst *operand; | |
| 4551 | SpillId spill_id; | |
| 4552 | }; | |
| 4553 | ||
| 4554 | struct Stage1AirInstSpillBegin { | |
| 4555 | Stage1AirInst base; | |
| 4556 | ||
| 4557 | SpillId spill_id; | |
| 4558 | Stage1AirInst *operand; | |
| 4559 | }; | |
| 4560 | ||
| 4561 | struct Stage1ZirInstSpillEnd { | |
| 4562 | Stage1ZirInst base; | |
| 4563 | ||
| 4564 | Stage1ZirInstSpillBegin *begin; | |
| 4565 | }; | |
| 4566 | ||
| 4567 | struct Stage1AirInstSpillEnd { | |
| 4568 | Stage1AirInst base; | |
| 4569 | ||
| 4570 | Stage1AirInstSpillBegin *begin; | |
| 4571 | }; | |
| 4572 | ||
| 4573 | struct Stage1AirInstVectorExtractElem { | |
| 4574 | Stage1AirInst base; | |
| 4575 | ||
| 4576 | Stage1AirInst *vector; | |
| 4577 | Stage1AirInst *index; | |
| 4578 | }; | |
| 4579 | ||
| 4580 | enum 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 | |
| 4594 | struct 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 | ||
| 4604 | struct ResultLocNone { | |
| 4605 | ResultLoc base; | |
| 4606 | }; | |
| 4607 | ||
| 4608 | struct ResultLocVar { | |
| 4609 | ResultLoc base; | |
| 4610 | ||
| 4611 | ZigVar *var; | |
| 4612 | }; | |
| 4613 | ||
| 4614 | struct ResultLocReturn { | |
| 4615 | ResultLoc base; | |
| 4616 | ||
| 4617 | bool implicit_return_type_done; | |
| 4618 | }; | |
| 4619 | ||
| 4620 | struct IrSuspendPosition { | |
| 4621 | size_t basic_block_index; | |
| 4622 | size_t instruction_index; | |
| 4623 | }; | |
| 4624 | ||
| 4625 | struct 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 | ||
| 4637 | struct 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 | |
| 4646 | struct ResultLocInstruction { | |
| 4647 | ResultLoc base; | |
| 4648 | }; | |
| 4649 | ||
| 4650 | // The source_instruction is the destination type | |
| 4651 | struct ResultLocBitCast { | |
| 4652 | ResultLoc base; | |
| 4653 | ||
| 4654 | ResultLoc *parent; | |
| 4655 | }; | |
| 4656 | ||
| 4657 | // The source_instruction is the destination type | |
| 4658 | struct ResultLocCast { | |
| 4659 | ResultLoc base; | |
| 4660 | ||
| 4661 | ResultLoc *parent; | |
| 4662 | }; | |
| 4663 | ||
| 4664 | static const size_t slice_ptr_index = 0; | |
| 4665 | static const size_t slice_len_index = 1; | |
| 4666 | ||
| 4667 | static const size_t maybe_child_index = 0; | |
| 4668 | static const size_t maybe_null_index = 1; | |
| 4669 | ||
| 4670 | static const size_t err_union_payload_index = 0; | |
| 4671 | static const size_t err_union_err_index = 1; | |
| 4672 | ||
| 4673 | // label (grep this): [fn_frame_struct_layout] | |
| 4674 | static const size_t frame_fn_ptr_index = 0; | |
| 4675 | static const size_t frame_resume_index = 1; | |
| 4676 | static const size_t frame_awaiter_index = 2; | |
| 4677 | static 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. | |
| 4682 | static 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 | ||
| 4690 | enum FloatMode { | |
| 4691 | FloatModeStrict, | |
| 4692 | FloatModeOptimized, | |
| 4693 | }; | |
| 4694 | ||
| 4695 | enum FnWalkId { | |
| 4696 | FnWalkIdAttrs, | |
| 4697 | FnWalkIdCall, | |
| 4698 | FnWalkIdTypes, | |
| 4699 | FnWalkIdVars, | |
| 4700 | FnWalkIdInits, | |
| 4701 | }; | |
| 4702 | ||
| 4703 | struct FnWalkAttrs { | |
| 4704 | ZigFn *fn; | |
| 4705 | LLVMValueRef llvm_fn; | |
| 4706 | unsigned gen_i; | |
| 4707 | }; | |
| 4708 | ||
| 4709 | struct FnWalkCall { | |
| 4710 | ZigList<LLVMValueRef> *gen_param_values; | |
| 4711 | ZigList<ZigType *> *gen_param_types; | |
| 4712 | Stage1AirInstCall *inst; | |
| 4713 | bool is_var_args; | |
| 4714 | }; | |
| 4715 | ||
| 4716 | struct FnWalkTypes { | |
| 4717 | ZigList<ZigLLVMDIType *> *param_di_types; | |
| 4718 | ZigList<LLVMTypeRef> *gen_param_types; | |
| 4719 | }; | |
| 4720 | ||
| 4721 | struct FnWalkVars { | |
| 4722 | ZigType *import; | |
| 4723 | LLVMValueRef llvm_fn; | |
| 4724 | ZigFn *fn; | |
| 4725 | ZigVar *var; | |
| 4726 | unsigned gen_i; | |
| 4727 | }; | |
| 4728 | ||
| 4729 | struct FnWalkInits { | |
| 4730 | LLVMValueRef llvm_fn; | |
| 4731 | ZigFn *fn; | |
| 4732 | unsigned gen_i; | |
| 4733 | }; | |
| 4734 | ||
| 4735 | struct 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 | ||
| 20 | static const size_t default_backward_branch_quota = 1000; | |
| 21 | ||
| 22 | static Error ATTRIBUTE_MUST_USE resolve_struct_type(CodeGen *g, ZigType *struct_type); | |
| 23 | ||
| 24 | static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type); | |
| 25 | static Error ATTRIBUTE_MUST_USE resolve_struct_alignment(CodeGen *g, ZigType *struct_type); | |
| 26 | static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type); | |
| 27 | static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type); | |
| 28 | static Error ATTRIBUTE_MUST_USE resolve_union_alignment(CodeGen *g, ZigType *union_type); | |
| 29 | static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry); | |
| 30 | static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status); | |
| 31 | static void preview_use_decl(CodeGen *g, TldUsingNamespace *using_namespace, ScopeDecls *dest_decls_scope); | |
| 32 | static void resolve_use_decl(CodeGen *g, TldUsingNamespace *tld_using_namespace, ScopeDecls *dest_decls_scope); | |
| 33 | static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame); | |
| 34 | ||
| 35 | // nullptr means not analyzed yet; this one means currently being analyzed | |
| 36 | static const AstNode *inferred_async_checking = reinterpret_cast<AstNode *>(0x1); | |
| 37 | // this one means analyzed and it's not async | |
| 38 | static const AstNode *inferred_async_none = reinterpret_cast<AstNode *>(0x2); | |
| 39 | ||
| 40 | static bool is_top_level_struct(ZigType *import) { | |
| 41 | return import->id == ZigTypeIdStruct && import->data.structure.root_struct != nullptr; | |
| 42 | } | |
| 43 | ||
| 44 | static 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 | ||
| 57 | ErrorMsg *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 | ||
| 71 | ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg) { | |
| 72 | return add_token_error_offset(g, owner, token, msg, 0); | |
| 73 | } | |
| 74 | ||
| 75 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { | |
| 76 | return add_token_error(g, node->owner, node->main_token, msg); | |
| 77 | } | |
| 78 | ||
| 79 | ErrorMsg *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 | ||
| 83 | ZigType *new_type_table_entry(ZigTypeId id) { | |
| 84 | ZigType *entry = heap::c_allocator.create<ZigType>(); | |
| 85 | entry->id = id; | |
| 86 | return entry; | |
| 87 | } | |
| 88 | ||
| 89 | static 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 | ||
| 104 | static 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 | ||
| 129 | static 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 | ||
| 135 | ScopeDecls *get_container_scope(ZigType *type_entry) { | |
| 136 | return *get_container_scope_ptr(type_entry); | |
| 137 | } | |
| 138 | ||
| 139 | void 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 | ||
| 146 | ScopeDecls *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 | ||
| 158 | ScopeBlock *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 | ||
| 166 | ScopeDefer *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 | ||
| 173 | ScopeDeferExpr *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 | ||
| 180 | Scope *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 | ||
| 187 | ScopeCImport *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 | ||
| 195 | ScopeLoop *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 | ||
| 208 | Scope *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 | ||
| 215 | ScopeSuspend *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 | ||
| 222 | ScopeFnDef *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 | ||
| 229 | Scope *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 | ||
| 235 | Scope *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 | ||
| 241 | Scope *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 | ||
| 247 | ScopeExpr *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 | ||
| 261 | ZigType *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 | ||
| 273 | ScopeTypeOf *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 | ||
| 289 | static 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 | ||
| 298 | static 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 | ||
| 307 | AstNode *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 | ||
| 345 | bool 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 | ||
| 415 | bool type_is_complete(ZigType *type_entry) { | |
| 416 | return type_is_resolved(type_entry, ResolveStatusSizeKnown); | |
| 417 | } | |
| 418 | ||
| 419 | uint64_t type_size(CodeGen *g, ZigType *type_entry) { | |
| 420 | assert(type_is_resolved(type_entry, ResolveStatusSizeKnown)); | |
| 421 | return type_entry->abi_size; | |
| 422 | } | |
| 423 | ||
| 424 | uint64_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 | ||
| 429 | uint32_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 | ||
| 434 | static bool is_slice(ZigType *type) { | |
| 435 | return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialSlice; | |
| 436 | } | |
| 437 | ||
| 438 | ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) { | |
| 439 | return get_int_type(g, false, bits_needed_for_unsigned(x)); | |
| 440 | } | |
| 441 | ||
| 442 | ZigType *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 | ||
| 467 | ZigType *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 | ||
| 486 | static 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 | ||
| 523 | ZigType *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 | ||
| 653 | ZigType *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 | ||
| 661 | ZigType *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 | ||
| 666 | ZigType *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 | ||
| 674 | ZigType *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 | ||
| 722 | static size_t align_forward(size_t addr, size_t alignment) { | |
| 723 | return (addr + alignment - 1) & ~(alignment - 1); | |
| 724 | } | |
| 725 | ||
| 726 | static 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 | ||
| 735 | ZigType *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 | ||
| 796 | ZigType *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 | ||
| 838 | ZigType *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 | ||
| 918 | static 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 | ||
| 924 | static 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 | ||
| 930 | ZigType *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 | ||
| 961 | ZigType *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 | ||
| 977 | const 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 | ||
| 1001 | bool 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 | ||
| 1027 | const 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 | ||
| 1042 | ZigType *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 | ||
| 1050 | bool 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 | ||
| 1077 | ZigType *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 | ||
| 1129 | static 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. | |
| 1144 | static 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 | ||
| 1161 | ZigType *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 | ||
| 1203 | ZigValue *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 | ||
| 1229 | Error 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 | ||
| 1325 | Error 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 | ||
| 1355 | static 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 | ||
| 1423 | Error 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 | ||
| 1428 | start_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 | ||
| 1510 | Error 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 | ||
| 1570 | static 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 | ||
| 1621 | ZigType *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 | } | |
| 1635 | abort_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 | ||
| 1646 | ZigType *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 | ||
| 1674 | CallingConvention 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 | ||
| 1685 | void 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 | ||
| 1696 | static 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 | ||
| 1716 | static 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 | ||
| 1753 | static 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 | ||
| 1848 | static 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 | ||
| 1854 | static 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 | ||
| 1860 | Error 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 | ||
| 1959 | ZigType *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 | |
| 1975 | Error 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 | ||
| 2044 | static 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 | ||
| 2237 | bool 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 | ||
| 2250 | bool 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 | ||
| 2264 | bool 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 | ||
| 2282 | struct SrcField { | |
| 2283 | const char *name; | |
| 2284 | ZigType *ty; | |
| 2285 | unsigned align; | |
| 2286 | }; | |
| 2287 | ||
| 2288 | static 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 | ||
| 2352 | static size_t get_store_size_bytes(size_t size_in_bits) { | |
| 2353 | return (size_in_bits + 7) / 8; | |
| 2354 | } | |
| 2355 | ||
| 2356 | static 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 | ||
| 2363 | static 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 | ||
| 2369 | ZigType *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 | ||
| 2380 | static 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 | ||
| 2558 | static 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 | ||
| 2668 | ZigType *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 | ||
| 2679 | static 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 | ||
| 2785 | static 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 | ||
| 2799 | static 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 | ||
| 3035 | static 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 | ||
| 3196 | static 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 | ||
| 3274 | static 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 | ||
| 3663 | static 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 | ||
| 3678 | void 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 | ||
| 3684 | static 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 | ||
| 3702 | static 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 | ||
| 3710 | ZigFn *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 | ||
| 3725 | ZigType *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 | ||
| 3736 | void 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 | ||
| 3743 | void 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 | ||
| 3770 | static 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 | ||
| 3914 | static 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 | ||
| 3921 | static 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 | ||
| 3974 | static 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 | ||
| 4004 | static 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 | ||
| 4012 | void 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 | ||
| 4023 | void 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 | ||
| 4035 | void 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 | ||
| 4133 | static 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 | ||
| 4151 | ZigType *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 | |
| 4193 | ZigVar *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 | ||
| 4234 | static 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 | ||
| 4244 | static 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 | ||
| 4348 | static 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 | ||
| 4420 | static 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 | ||
| 4429 | static 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 | ||
| 4461 | void 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 | ||
| 4514 | void 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 | ||
| 4526 | Tld *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 | ||
| 4532 | Tld *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 | ||
| 4546 | ZigVar *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 | ||
| 4579 | ZigFn *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 | ||
| 4590 | ZigPackage *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 | ||
| 4596 | TypeEnumField *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 | ||
| 4606 | TypeStructField *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 | ||
| 4626 | TypeUnionField *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 | ||
| 4637 | TypeUnionField *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 | ||
| 4649 | TypeEnumField *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 | ||
| 4661 | bool 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 | ||
| 4697 | bool is_ref(ZigType *type_entry) { | |
| 4698 | return type_entry->id == ZigTypeIdPointer && type_entry->data.pointer.ptr_len == PtrLenSingle; | |
| 4699 | } | |
| 4700 | ||
| 4701 | bool 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 | ||
| 4707 | bool 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 | ||
| 4712 | ZigType *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 | ||
| 4718 | ZigType *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 | ||
| 4732 | Error 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 | ||
| 4752 | ZigType *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 | ||
| 4761 | bool 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 | ||
| 4770 | Error 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 | ||
| 4778 | uint32_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 | ||
| 4785 | uint32_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 | ||
| 4807 | bool 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 | ||
| 4827 | AstNode *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 | ||
| 4836 | static 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 | ||
| 4883 | bool 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 | ||
| 4907 | static 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 | ||
| 4923 | bool 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 | ||
| 4929 | void 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 | |
| 4966 | static 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. | |
| 5044 | static 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 | ||
| 5113 | static 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 | ||
| 5202 | static 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 | ||
| 5244 | ZigType *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 | ||
| 5331 | void 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 | ||
| 5370 | ZigType *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 | ||
| 5388 | Error 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 | ||
| 5409 | ZigType *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 | ||
| 5455 | ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type) { | |
| 5456 | return &g->builtin_types.entry_c_int[c_int_type]; | |
| 5457 | } | |
| 5458 | ||
| 5459 | ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type) { | |
| 5460 | return *get_c_int_type_ptr(g, c_int_type); | |
| 5461 | } | |
| 5462 | ||
| 5463 | bool 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 | ||
| 5504 | static const uint32_t HASH_INIT = 0x811c9dc5U; | |
| 5505 | ||
| 5506 | template<typename T> | |
| 5507 | static 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 | ||
| 5518 | static uint32_t hash_combine_bigint(uint32_t hash, const BigInt *value) { | |
| 5519 | return hash_combine(hash, bigint_ptr(value), value->digit_count); | |
| 5520 | } | |
| 5521 | ||
| 5522 | static uint32_t hash_combine_buf(uint32_t hash, const Buf *buf) { | |
| 5523 | return hash_combine(hash, buf_ptr(buf), buf_len(buf)); | |
| 5524 | } | |
| 5525 | ||
| 5526 | uint32_t fn_table_entry_hash(ZigFn* value) { | |
| 5527 | return hash_combine(HASH_INIT, &value); | |
| 5528 | } | |
| 5529 | ||
| 5530 | bool fn_table_entry_eql(ZigFn *a, ZigFn *b) { | |
| 5531 | return a == b; | |
| 5532 | } | |
| 5533 | ||
| 5534 | uint32_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 | ||
| 5548 | bool 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 | ||
| 5570 | static 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 | ||
| 5575 | static 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 | ||
| 5618 | static uint32_t hash_combine_const_val(uint32_t hash_val, ZigValue *const_val); | |
| 5619 | static 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 | } | |
| 5660 | static 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 | ||
| 5775 | uint32_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 | ||
| 5788 | bool 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 | ||
| 5809 | static 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 | ||
| 5913 | bool 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 | ||
| 5934 | uint32_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 | ||
| 5953 | bool 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. | |
| 5991 | bool 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. | |
| 6001 | Error 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 | ||
| 6021 | bool 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. | |
| 6028 | OnePossibleValue 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 | ||
| 6118 | ZigValue *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 | ||
| 6181 | ReqCompTime 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 | ||
| 6243 | void 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 | ||
| 6270 | ZigValue *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 | ||
| 6276 | ZigValue *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 | ||
| 6281 | void 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 | ||
| 6287 | ZigValue *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 | ||
| 6294 | void 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 | ||
| 6301 | ZigValue *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 | ||
| 6307 | void 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 | ||
| 6311 | ZigValue *create_const_usize(CodeGen *g, uint64_t x) { | |
| 6312 | return create_const_unsigned_negative(g, g->builtin_types.entry_usize, x, false); | |
| 6313 | } | |
| 6314 | ||
| 6315 | void 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 | ||
| 6321 | ZigValue *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 | ||
| 6327 | void 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 | ||
| 6333 | ZigValue *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 | ||
| 6339 | void 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 | ||
| 6346 | ZigValue *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 | ||
| 6352 | void 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 | ||
| 6382 | ZigValue *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 | ||
| 6388 | void 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 | ||
| 6394 | ZigValue *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 | ||
| 6401 | void 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 | ||
| 6407 | ZigValue *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 | ||
| 6413 | void init_const_runtime(ZigValue *const_val, ZigType *type) { | |
| 6414 | const_val->special = ConstValSpecialRuntime; | |
| 6415 | const_val->type = type; | |
| 6416 | } | |
| 6417 | ||
| 6418 | ZigValue *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 | ||
| 6424 | void 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 | ||
| 6430 | ZigValue *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 | ||
| 6436 | void 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 | ||
| 6453 | ZigValue *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 | ||
| 6459 | void 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 | ||
| 6473 | ZigValue *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 | ||
| 6481 | void 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 | ||
| 6488 | ZigValue *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 | ||
| 6494 | void 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 | ||
| 6503 | ZigValue *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 | ||
| 6511 | ZigValue **alloc_const_vals_ptrs(CodeGen *g, size_t count) { | |
| 6512 | return realloc_const_vals_ptrs(g, nullptr, 0, count); | |
| 6513 | } | |
| 6514 | ||
| 6515 | ZigValue **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 | ||
| 6527 | TypeStructField **alloc_type_struct_fields(size_t count) { | |
| 6528 | return realloc_type_struct_fields(nullptr, 0, count); | |
| 6529 | } | |
| 6530 | ||
| 6531 | TypeStructField **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 | ||
| 6543 | static 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 | |
| 6563 | static 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 | ||
| 6616 | static 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 | ||
| 6637 | static 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 | ||
| 6646 | static 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 | ||
| 6979 | static 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 | ||
| 7030 | Error 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 | ||
| 7091 | bool 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 | ||
| 7121 | bool 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 | ||
| 7181 | static 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 | ||
| 7211 | bool 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 | ||
| 7331 | void 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 | ||
| 7368 | void 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 | ||
| 7382 | static 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 | ||
| 7426 | static 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 | ||
| 7434 | static 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 | ||
| 7474 | void 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 | ||
| 7692 | ZigType *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 | ||
| 7722 | uint32_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 | ||
| 7788 | bool 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 | ||
| 7860 | uint32_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 | ||
| 7892 | bool 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 | ||
| 7923 | static 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 | ||
| 7958 | void 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 | |
| 7965 | void 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 | ||
| 8021 | static 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 | ||
| 8049 | ZigTypeId type_id_at_index(size_t index) { | |
| 8050 | assert(index < array_length(all_type_ids)); | |
| 8051 | return all_type_ids[index]; | |
| 8052 | } | |
| 8053 | ||
| 8054 | size_t type_id_len() { | |
| 8055 | return array_length(all_type_ids); | |
| 8056 | } | |
| 8057 | ||
| 8058 | size_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 | ||
| 8118 | const 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 | ||
| 8176 | ZigType *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 | ||
| 8184 | uint32_t type_ptr_hash(const ZigType *ptr) { | |
| 8185 | return hash_combine(HASH_INIT, &ptr); | |
| 8186 | } | |
| 8187 | ||
| 8188 | bool type_ptr_eql(const ZigType *a, const ZigType *b) { | |
| 8189 | return a == b; | |
| 8190 | } | |
| 8191 | ||
| 8192 | uint32_t pkg_ptr_hash(const ZigPackage *ptr) { | |
| 8193 | return hash_combine(HASH_INIT, &ptr); | |
| 8194 | } | |
| 8195 | ||
| 8196 | bool pkg_ptr_eql(const ZigPackage *a, const ZigPackage *b) { | |
| 8197 | return a == b; | |
| 8198 | } | |
| 8199 | ||
| 8200 | uint32_t tld_ptr_hash(const Tld *ptr) { | |
| 8201 | return hash_combine(HASH_INIT, &ptr); | |
| 8202 | } | |
| 8203 | ||
| 8204 | bool tld_ptr_eql(const Tld *a, const Tld *b) { | |
| 8205 | return a == b; | |
| 8206 | } | |
| 8207 | ||
| 8208 | uint32_t node_ptr_hash(const AstNode *ptr) { | |
| 8209 | return hash_combine(HASH_INIT, &ptr); | |
| 8210 | } | |
| 8211 | ||
| 8212 | bool node_ptr_eql(const AstNode *a, const AstNode *b) { | |
| 8213 | return a == b; | |
| 8214 | } | |
| 8215 | ||
| 8216 | uint32_t fn_ptr_hash(const ZigFn *ptr) { | |
| 8217 | return hash_combine(HASH_INIT, &ptr); | |
| 8218 | } | |
| 8219 | ||
| 8220 | bool fn_ptr_eql(const ZigFn *a, const ZigFn *b) { | |
| 8221 | return a == b; | |
| 8222 | } | |
| 8223 | ||
| 8224 | uint32_t err_ptr_hash(const ErrorTableEntry *ptr) { | |
| 8225 | return hash_combine(HASH_INIT, &ptr); | |
| 8226 | } | |
| 8227 | ||
| 8228 | bool err_ptr_eql(const ErrorTableEntry *a, const ErrorTableEntry *b) { | |
| 8229 | return a == b; | |
| 8230 | } | |
| 8231 | ||
| 8232 | ZigValue *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 | ||
| 8248 | ZigType *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 | ||
| 8254 | bool 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 | ||
| 8260 | bool type_can_fail(ZigType *type_entry) { | |
| 8261 | return type_entry->id == ZigTypeIdErrorUnion || type_entry->id == ZigTypeIdErrorSet; | |
| 8262 | } | |
| 8263 | ||
| 8264 | bool 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 | |
| 8271 | Error 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 | ||
| 8290 | not_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 | ||
| 8300 | Error 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 | ||
| 8309 | static 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 | ||
| 8360 | static 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 | ||
| 8434 | X64CABIClass 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 | |
| 8458 | Error 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 | ||
| 8477 | bool 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 | ||
| 8486 | uint32_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 | ||
| 8496 | Error 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 | ||
| 8511 | const 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 | ||
| 8521 | bool 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 | ||
| 8530 | Buf *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 | |
| 8542 | Buf *type_h_name(ZigType *t) { | |
| 8543 | return type_bare_name(t); | |
| 8544 | } | |
| 8545 | ||
| 8546 | static 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 | ||
| 8691 | static LLVMTypeRef get_llvm_type_of_n_bytes(unsigned byte_size) { | |
| 8692 | return byte_size == 1 ? | |
| 8693 | LLVMInt8Type() : LLVMArrayType(LLVMInt8Type(), byte_size); | |
| 8694 | } | |
| 8695 | ||
| 8696 | static 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 | ||
| 8708 | static 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. | |
| 8727 | static 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 | ||
| 8794 | static 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). | |
| 9074 | static 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 | ||
| 9091 | static 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 | ||
| 9138 | static 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 | ||
| 9306 | static 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 | ||
| 9362 | static 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 | ||
| 9391 | static 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 | ||
| 9468 | static 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 | ||
| 9545 | static 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 | ||
| 9568 | static 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 | ||
| 9686 | void 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 | ||
| 9723 | static 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 | ||
| 9749 | static 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 | ||
| 9760 | static 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 | ||
| 9900 | static 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 | ||
| 9971 | LLVMTypeRef 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 | ||
| 9978 | LLVMTypeRef 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 | ||
| 9985 | ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type) { | |
| 9986 | assertNoError(type_resolve(g, type, ResolveStatusLLVMFull)); | |
| 9987 | return type->llvm_di_type; | |
| 9988 | } | |
| 9989 | ||
| 9990 | void 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 | ||
| 10004 | Error 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 | ||
| 10063 | void 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 | ||
| 10072 | void 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 | ||
| 10079 | bool is_anon_container(ZigType *ty) { | |
| 10080 | return ty->id == ZigTypeIdStruct && ( | |
| 10081 | ty->data.structure.special == StructSpecialInferredTuple || | |
| 10082 | ty->data.structure.special == StructSpecialInferredStruct); | |
| 10083 | } | |
| 10084 | ||
| 10085 | bool 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. | |
| 10091 | bool 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 | ||
| 10103 | void 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 | ||
| 10162 | bool 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 | ||
| 10179 | bool 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 | ||
| 10217 | static void dump_value_indent_error_set(ZigValue *val, int indent) { | |
| 10218 | fprintf(stderr, "<TODO dump value>\n"); | |
| 10219 | } | |
| 10220 | ||
| 10221 | static void dump_value_indent(ZigValue *val, int indent); | |
| 10222 | ||
| 10223 | static 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 | ||
| 10269 | static 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 | ||
| 10400 | void 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 | |
| 10406 | const 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 | ||
| 13 | void semantic_analyze(CodeGen *g); | |
| 14 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg); | |
| 15 | ErrorMsg *add_token_error(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg); | |
| 16 | ErrorMsg *add_token_error_offset(CodeGen *g, ZigType *owner, TokenIndex token, Buf *msg, | |
| 17 | uint32_t bad_index); | |
| 18 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, const AstNode *node, Buf *msg); | |
| 19 | ZigType *new_type_table_entry(ZigTypeId id); | |
| 20 | ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn); | |
| 21 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const); | |
| 22 | ZigType *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); | |
| 26 | ZigType *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); | |
| 31 | uint64_t type_size(CodeGen *g, ZigType *type_entry); | |
| 32 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); | |
| 33 | ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); | |
| 34 | ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type); | |
| 35 | ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type); | |
| 36 | ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type); | |
| 37 | ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id); | |
| 38 | ZigType *get_optional_type(CodeGen *g, ZigType *child_type); | |
| 39 | ZigType *get_optional_type2(CodeGen *g, ZigType *child_type); | |
| 40 | ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ZigValue *sentinel); | |
| 41 | ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type); | |
| 42 | ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, | |
| 43 | AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout); | |
| 44 | ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x); | |
| 45 | ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type); | |
| 46 | ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry); | |
| 47 | ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, Buf *bare_name); | |
| 48 | ZigType *get_test_fn_type(CodeGen *g); | |
| 49 | ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type); | |
| 50 | bool handle_is_ptr(CodeGen *g, ZigType *type_entry); | |
| 51 | Error emit_error_unless_callconv_allowed_for_target(CodeGen *g, AstNode *source_node, CallingConvention cc); | |
| 52 | uint32_t get_async_frame_align_bytes(CodeGen *g); | |
| 53 | ||
| 54 | bool type_has_bits(CodeGen *g, ZigType *type_entry); | |
| 55 | Error type_has_bits2(CodeGen *g, ZigType *type_entry, bool *result); | |
| 56 | ||
| 57 | bool fn_returns_c_abi_small_struct(FnTypeId *fn_type_id); | |
| 58 | ||
| 59 | enum ExternPosition { | |
| 60 | ExternPositionFunctionParameter, | |
| 61 | ExternPositionFunctionReturn, | |
| 62 | ExternPositionOther, // array element, struct field, optional element, etc | |
| 63 | }; | |
| 64 | ||
| 65 | Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, ExternPosition position, bool *result); | |
| 66 | bool ptr_allows_addr_zero(ZigType *ptr_type); | |
| 67 | ||
| 68 | // Deprecated, use `type_is_nonnull_ptr2` | |
| 69 | bool type_is_nonnull_ptr(CodeGen *g, ZigType *type); | |
| 70 | Error type_is_nonnull_ptr2(CodeGen *g, ZigType *type, bool *result); | |
| 71 | ||
| 72 | ZigType *get_codegen_ptr_type_bail(CodeGen *g, ZigType *type); | |
| 73 | Error get_codegen_ptr_type(CodeGen *g, ZigType *type, ZigType **result); | |
| 74 | ||
| 75 | enum SourceKind { | |
| 76 | SourceKindRoot, | |
| 77 | SourceKindPkgMain, | |
| 78 | SourceKindNonRoot, | |
| 79 | SourceKindCImport, | |
| 80 | }; | |
| 81 | ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Buf *source_code, | |
| 82 | SourceKind source_kind); | |
| 83 | ||
| 84 | ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope); | |
| 85 | Tld *find_decl(CodeGen *g, Scope *scope, Buf *name); | |
| 86 | Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name); | |
| 87 | void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy); | |
| 88 | void resolve_container_usingnamespace_decls(CodeGen *g, ScopeDecls *decls_scope); | |
| 89 | ||
| 90 | ZigType *get_src_ptr_type(ZigType *type); | |
| 91 | uint32_t get_ptr_align(CodeGen *g, ZigType *type); | |
| 92 | bool get_ptr_const(CodeGen *g, ZigType *type); | |
| 93 | ZigType *validate_var_type(CodeGen *g, AstNodeVariableDeclaration *source_node, ZigType *type_entry); | |
| 94 | ZigType *container_ref_type(ZigType *type_entry); | |
| 95 | bool type_is_complete(ZigType *type_entry); | |
| 96 | bool type_is_resolved(ZigType *type_entry, ResolveStatus status); | |
| 97 | bool type_is_invalid(ZigType *type_entry); | |
| 98 | bool type_is_global_error_set(ZigType *err_set_type); | |
| 99 | ScopeDecls *get_container_scope(ZigType *type_entry); | |
| 100 | TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name); | |
| 101 | TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name); | |
| 102 | TypeUnionField *find_union_type_field(ZigType *type_entry, Buf *name); | |
| 103 | TypeEnumField *find_enum_field_by_tag(ZigType *enum_type, const BigInt *tag); | |
| 104 | TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag); | |
| 105 | ||
| 106 | bool is_ref(ZigType *type_entry); | |
| 107 | bool is_array_ref(ZigType *type_entry); | |
| 108 | bool is_container_ref(ZigType *type_entry); | |
| 109 | Error is_valid_vector_elem_type(CodeGen *g, ZigType *elem_type, bool *result); | |
| 110 | void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); | |
| 111 | ZigFn *scope_fn_entry(Scope *scope); | |
| 112 | ZigPackage *scope_package(Scope *scope); | |
| 113 | ZigType *get_scope_import(Scope *scope); | |
| 114 | ScopeTypeOf *get_scope_typeof(Scope *scope); | |
| 115 | void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope); | |
| 116 | ZigVar *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); | |
| 118 | ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node); | |
| 119 | void append_namespace_qualification(CodeGen *g, Buf *buf, ZigType *container_type); | |
| 120 | ZigFn *create_fn(CodeGen *g, AstNode *proto_node); | |
| 121 | void init_fn_type_id(FnTypeId *fn_type_id, AstNode *proto_node, CallingConvention cc, size_t param_count_alloc); | |
| 122 | AstNode *get_param_decl_node(ZigFn *fn_entry, size_t index); | |
| 123 | Error ATTRIBUTE_MUST_USE type_resolve(CodeGen *g, ZigType *type_entry, ResolveStatus status); | |
| 124 | void complete_enum(CodeGen *g, ZigType *enum_type); | |
| 125 | bool ir_get_var_is_comptime(ZigVar *var); | |
| 126 | bool const_values_equal(CodeGen *g, ZigValue *a, ZigValue *b); | |
| 127 | void eval_min_max_value(CodeGen *g, ZigType *type_entry, ZigValue *const_val, bool is_max); | |
| 128 | void eval_min_max_value_int(CodeGen *g, ZigType *int_type, BigInt *bigint, bool is_max); | |
| 129 | ||
| 130 | void render_const_value(CodeGen *g, Buf *buf, ZigValue *const_val); | |
| 131 | ||
| 132 | ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type, ZigType *import, Buf *bare_name); | |
| 133 | ScopeBlock *create_block_scope(CodeGen *g, AstNode *node, Scope *parent); | |
| 134 | ScopeDefer *create_defer_scope(CodeGen *g, AstNode *node, Scope *parent); | |
| 135 | ScopeDeferExpr *create_defer_expr_scope(CodeGen *g, AstNode *node, Scope *parent); | |
| 136 | Scope *create_var_scope(CodeGen *g, AstNode *node, Scope *parent, ZigVar *var); | |
| 137 | ScopeCImport *create_cimport_scope(CodeGen *g, AstNode *node, Scope *parent); | |
| 138 | ScopeLoop *create_loop_scope(CodeGen *g, AstNode *node, Scope *parent); | |
| 139 | ScopeSuspend *create_suspend_scope(CodeGen *g, AstNode *node, Scope *parent); | |
| 140 | ScopeFnDef *create_fndef_scope(CodeGen *g, AstNode *node, Scope *parent, ZigFn *fn_entry); | |
| 141 | Scope *create_comptime_scope(CodeGen *g, AstNode *node, Scope *parent); | |
| 142 | Scope *create_nosuspend_scope(CodeGen *g, AstNode *node, Scope *parent); | |
| 143 | Scope *create_runtime_scope(CodeGen *g, AstNode *node, Scope *parent, Stage1ZirInst *is_comptime); | |
| 144 | Scope *create_typeof_scope(CodeGen *g, AstNode *node, Scope *parent); | |
| 145 | ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent); | |
| 146 | ||
| 147 | void init_const_str_lit(CodeGen *g, ZigValue *const_val, Buf *str, bool move_str); | |
| 148 | ZigValue *create_const_str_lit(CodeGen *g, Buf *str); | |
| 149 | ZigValue *create_sentineled_str_lit(CodeGen *g, Buf *str, ZigValue *sentinel); | |
| 150 | ||
| 151 | void init_const_bigint(ZigValue *const_val, ZigType *type, const BigInt *bigint); | |
| 152 | ZigValue *create_const_bigint(CodeGen *g, ZigType *type, const BigInt *bigint); | |
| 153 | ||
| 154 | void init_const_unsigned_negative(ZigValue *const_val, ZigType *type, uint64_t x, bool negative); | |
| 155 | ZigValue *create_const_unsigned_negative(CodeGen *g, ZigType *type, uint64_t x, bool negative); | |
| 156 | ||
| 157 | void init_const_signed(ZigValue *const_val, ZigType *type, int64_t x); | |
| 158 | ZigValue *create_const_signed(CodeGen *g, ZigType *type, int64_t x); | |
| 159 | ||
| 160 | void init_const_usize(CodeGen *g, ZigValue *const_val, uint64_t x); | |
| 161 | ZigValue *create_const_usize(CodeGen *g, uint64_t x); | |
| 162 | ||
| 163 | void init_const_float(ZigValue *const_val, ZigType *type, double value); | |
| 164 | ZigValue *create_const_float(CodeGen *g, ZigType *type, double value); | |
| 165 | ||
| 166 | void init_const_enum(ZigValue *const_val, ZigType *type, const BigInt *tag); | |
| 167 | ZigValue *create_const_enum(CodeGen *g, ZigType *type, const BigInt *tag); | |
| 168 | ||
| 169 | void init_const_bool(CodeGen *g, ZigValue *const_val, bool value); | |
| 170 | ZigValue *create_const_bool(CodeGen *g, bool value); | |
| 171 | ||
| 172 | void init_const_type(CodeGen *g, ZigValue *const_val, ZigType *type_value); | |
| 173 | ZigValue *create_const_type(CodeGen *g, ZigType *type_value); | |
| 174 | ||
| 175 | void init_const_runtime(ZigValue *const_val, ZigType *type); | |
| 176 | ZigValue *create_const_runtime(CodeGen *g, ZigType *type); | |
| 177 | ||
| 178 | void init_const_ptr_ref(CodeGen *g, ZigValue *const_val, ZigValue *pointee_val, bool is_const); | |
| 179 | ZigValue *create_const_ptr_ref(CodeGen *g, ZigValue *pointee_val, bool is_const); | |
| 180 | ||
| 181 | void init_const_ptr_hard_coded_addr(CodeGen *g, ZigValue *const_val, ZigType *pointee_type, | |
| 182 | size_t addr, bool is_const); | |
| 183 | ZigValue *create_const_ptr_hard_coded_addr(CodeGen *g, ZigType *pointee_type, | |
| 184 | size_t addr, bool is_const); | |
| 185 | ||
| 186 | void init_const_ptr_array(CodeGen *g, ZigValue *const_val, ZigValue *array_val, | |
| 187 | size_t elem_index, bool is_const, PtrLen ptr_len); | |
| 188 | ZigValue *create_const_ptr_array(CodeGen *g, ZigValue *array_val, size_t elem_index, | |
| 189 | bool is_const, PtrLen ptr_len); | |
| 190 | ||
| 191 | void init_const_slice(CodeGen *g, ZigValue *const_val, ZigValue *array_val, | |
| 192 | size_t start, size_t len, bool is_const, ZigValue *sentinel); | |
| 193 | ZigValue *create_const_slice(CodeGen *g, ZigValue *array_val, size_t start, size_t len, bool is_const, ZigValue *sentinel); | |
| 194 | ||
| 195 | void init_const_null(ZigValue *const_val, ZigType *type); | |
| 196 | ZigValue *create_const_null(CodeGen *g, ZigType *type); | |
| 197 | ||
| 198 | void init_const_fn(ZigValue *const_val, ZigFn *fn); | |
| 199 | ZigValue *create_const_fn(CodeGen *g, ZigFn *fn); | |
| 200 | ||
| 201 | ZigValue **alloc_const_vals_ptrs(CodeGen *g, size_t count); | |
| 202 | ZigValue **realloc_const_vals_ptrs(CodeGen *g, ZigValue **ptr, size_t old_count, size_t new_count); | |
| 203 | ||
| 204 | TypeStructField **alloc_type_struct_fields(size_t count); | |
| 205 | TypeStructField **realloc_type_struct_fields(TypeStructField **ptr, size_t old_count, size_t new_count); | |
| 206 | ||
| 207 | ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); | |
| 208 | void expand_undef_array(CodeGen *g, ZigValue *const_val); | |
| 209 | void expand_undef_struct(CodeGen *g, ZigValue *const_val); | |
| 210 | void update_compile_var(CodeGen *g, Buf *name, ZigValue *value); | |
| 211 | ||
| 212 | const char *type_id_name(ZigTypeId id); | |
| 213 | ZigTypeId type_id_at_index(size_t index); | |
| 214 | size_t type_id_len(); | |
| 215 | size_t type_id_index(ZigType *entry); | |
| 216 | ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id); | |
| 217 | bool optional_value_is_null(ZigValue *val); | |
| 218 | ||
| 219 | uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry); | |
| 220 | ZigType *get_align_amt_type(CodeGen *g); | |
| 221 | ZigPackage *new_anonymous_package(void); | |
| 222 | ||
| 223 | Buf *const_value_to_buffer(ZigValue *const_val); | |
| 224 | void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage, CallingConvention cc); | |
| 225 | void add_var_export(CodeGen *g, ZigVar *fn_table_entry, const char *symbol_name, GlobalLinkageId linkage); | |
| 226 | ||
| 227 | ||
| 228 | ZigValue *get_builtin_value(CodeGen *codegen, const char *name); | |
| 229 | ZigType *get_builtin_type(CodeGen *codegen, const char *name); | |
| 230 | ZigType *get_stack_trace_type(CodeGen *g); | |
| 231 | bool resolve_inferred_error_set(CodeGen *g, ZigType *err_set_type, AstNode *source_node); | |
| 232 | ||
| 233 | ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry); | |
| 234 | ||
| 235 | bool fn_type_can_fail(FnTypeId *fn_type_id); | |
| 236 | bool type_can_fail(ZigType *type_entry); | |
| 237 | bool fn_eval_cacheable(Scope *scope, ZigType *return_type); | |
| 238 | AstNode *type_decl_node(ZigType *type_entry); | |
| 239 | ||
| 240 | Error get_primitive_type(CodeGen *g, Buf *name, ZigType **result); | |
| 241 | ||
| 242 | bool calling_convention_allows_zig_types(CallingConvention cc); | |
| 243 | const char *calling_convention_name(CallingConvention cc); | |
| 244 | ||
| 245 | const char *address_space_name(AddressSpace as); | |
| 246 | ||
| 247 | Error ATTRIBUTE_MUST_USE file_fetch(CodeGen *g, Buf *resolved_path, Buf *contents); | |
| 248 | ||
| 249 | void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk); | |
| 250 | X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty); | |
| 251 | bool type_is_c_abi_int_bail(CodeGen *g, ZigType *ty); | |
| 252 | Error type_is_c_abi_int(CodeGen *g, ZigType *ty, bool *result); | |
| 253 | bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id); | |
| 254 | const char *container_string(ContainerKind kind); | |
| 255 | ||
| 256 | uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field); | |
| 257 | ||
| 258 | enum ReqCompTime { | |
| 259 | ReqCompTimeInvalid, | |
| 260 | ReqCompTimeNo, | |
| 261 | ReqCompTimeYes, | |
| 262 | }; | |
| 263 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry); | |
| 264 | ||
| 265 | OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry); | |
| 266 | ||
| 267 | Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, | |
| 268 | ZigValue *const_val, ZigType *wanted_type); | |
| 269 | ||
| 270 | void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn); | |
| 271 | Buf *type_bare_name(ZigType *t); | |
| 272 | Buf *type_h_name(ZigType *t); | |
| 273 | ||
| 274 | LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type); | |
| 275 | LLVMTypeRef get_llvm_c_abi_type(CodeGen *g, ZigType *type); | |
| 276 | ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type); | |
| 277 | ||
| 278 | void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c, | |
| 279 | FileExt source_kind); | |
| 280 | ||
| 281 | void src_assert_impl(bool ok, AstNode *source_node, const char *file, unsigned int line); | |
| 282 | bool is_container(ZigType *type_entry); | |
| 283 | ZigValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, | |
| 284 | Buf *type_name, UndefAllowed undef); | |
| 285 | ||
| 286 | void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn); | |
| 287 | bool fn_is_async(ZigFn *fn); | |
| 288 | CallingConvention cc_from_fn_proto(AstNodeFnProto *fn_proto); | |
| 289 | bool is_valid_return_type(ZigType* type); | |
| 290 | bool is_valid_param_type(ZigType* type); | |
| 291 | ||
| 292 | Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *type_val, uint32_t *abi_align); | |
| 293 | Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ZigValue *type_val, | |
| 294 | size_t *abi_size, size_t *size_in_bits); | |
| 295 | Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent_type, | |
| 296 | ZigValue *parent_type_val, bool *is_zero_bits); | |
| 297 | ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field); | |
| 298 | ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field); | |
| 299 | ||
| 300 | void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn); | |
| 301 | ||
| 302 | Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str, | |
| 303 | ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path); | |
| 304 | ZigValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry); | |
| 305 | bool is_anon_container(ZigType *ty); | |
| 306 | void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src); | |
| 307 | bool type_has_optional_repr(ZigType *ty); | |
| 308 | bool is_opt_err_set(ZigType *ty); | |
| 309 | bool type_is_numeric(ZigType *ty); | |
| 310 | const 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 | ||
| 14 | struct 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 | ||
| 24 | static Stage1ZirInst *astgen_node(Stage1AstGen *ag, AstNode *node, Scope *scope); | |
| 25 | static Stage1ZirInst *astgen_node_extra(Stage1AstGen *ag, AstNode *node, Scope *scope, LVal lval, | |
| 26 | ResultLoc *result_loc); | |
| 27 | ||
| 28 | static Stage1ZirInst *ir_lval_wrap(Stage1AstGen *ag, Scope *scope, Stage1ZirInst *value, LVal lval, | |
| 29 | ResultLoc *result_loc); | |
| 30 | static Stage1ZirInst *ir_expr_wrap(Stage1AstGen *ag, Scope *scope, Stage1ZirInst *inst, | |
| 31 | ResultLoc *result_loc); | |
| 32 | static 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); | |
| 35 | static ResultLocCast *ir_build_cast_result_loc(Stage1AstGen *ag, Stage1ZirInst *dest_type, | |
| 36 | ResultLoc *parent_result_loc); | |
| 37 | static 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); | |
| 39 | static 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 | ||
| 42 | static 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 | ||
| 47 | static 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 | ||
| 57 | static 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 | ||
| 71 | void 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 | ||
| 361 | bool 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 | ||
| 377 | static 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 | ||
| 383 | static 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 | ||
| 389 | static void ir_ref_bb(Stage1ZirBasicBlock *bb) { | |
| 390 | bb->ref_count += 1; | |
| 391 | } | |
| 392 | ||
| 393 | static 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 | ||
| 403 | static 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 | ||
| 412 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstDeclVar *) { | |
| 413 | return Stage1ZirInstIdDeclVar; | |
| 414 | } | |
| 415 | ||
| 416 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBr *) { | |
| 417 | return Stage1ZirInstIdBr; | |
| 418 | } | |
| 419 | ||
| 420 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCondBr *) { | |
| 421 | return Stage1ZirInstIdCondBr; | |
| 422 | } | |
| 423 | ||
| 424 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSwitchBr *) { | |
| 425 | return Stage1ZirInstIdSwitchBr; | |
| 426 | } | |
| 427 | ||
| 428 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSwitchVar *) { | |
| 429 | return Stage1ZirInstIdSwitchVar; | |
| 430 | } | |
| 431 | ||
| 432 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSwitchElseVar *) { | |
| 433 | return Stage1ZirInstIdSwitchElseVar; | |
| 434 | } | |
| 435 | ||
| 436 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSwitchTarget *) { | |
| 437 | return Stage1ZirInstIdSwitchTarget; | |
| 438 | } | |
| 439 | ||
| 440 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPhi *) { | |
| 441 | return Stage1ZirInstIdPhi; | |
| 442 | } | |
| 443 | ||
| 444 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUnOp *) { | |
| 445 | return Stage1ZirInstIdUnOp; | |
| 446 | } | |
| 447 | ||
| 448 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBinOp *) { | |
| 449 | return Stage1ZirInstIdBinOp; | |
| 450 | } | |
| 451 | ||
| 452 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstMergeErrSets *) { | |
| 453 | return Stage1ZirInstIdMergeErrSets; | |
| 454 | } | |
| 455 | ||
| 456 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstLoadPtr *) { | |
| 457 | return Stage1ZirInstIdLoadPtr; | |
| 458 | } | |
| 459 | ||
| 460 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstStorePtr *) { | |
| 461 | return Stage1ZirInstIdStorePtr; | |
| 462 | } | |
| 463 | ||
| 464 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFieldPtr *) { | |
| 465 | return Stage1ZirInstIdFieldPtr; | |
| 466 | } | |
| 467 | ||
| 468 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstElemPtr *) { | |
| 469 | return Stage1ZirInstIdElemPtr; | |
| 470 | } | |
| 471 | ||
| 472 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstVarPtr *) { | |
| 473 | return Stage1ZirInstIdVarPtr; | |
| 474 | } | |
| 475 | ||
| 476 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCall *) { | |
| 477 | return Stage1ZirInstIdCall; | |
| 478 | } | |
| 479 | ||
| 480 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCallArgs *) { | |
| 481 | return Stage1ZirInstIdCallArgs; | |
| 482 | } | |
| 483 | ||
| 484 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCallExtra *) { | |
| 485 | return Stage1ZirInstIdCallExtra; | |
| 486 | } | |
| 487 | ||
| 488 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAsyncCallExtra *) { | |
| 489 | return Stage1ZirInstIdAsyncCallExtra; | |
| 490 | } | |
| 491 | ||
| 492 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstConst *) { | |
| 493 | return Stage1ZirInstIdConst; | |
| 494 | } | |
| 495 | ||
| 496 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstReturn *) { | |
| 497 | return Stage1ZirInstIdReturn; | |
| 498 | } | |
| 499 | ||
| 500 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstContainerInitList *) { | |
| 501 | return Stage1ZirInstIdContainerInitList; | |
| 502 | } | |
| 503 | ||
| 504 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstContainerInitFields *) { | |
| 505 | return Stage1ZirInstIdContainerInitFields; | |
| 506 | } | |
| 507 | ||
| 508 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUnreachable *) { | |
| 509 | return Stage1ZirInstIdUnreachable; | |
| 510 | } | |
| 511 | ||
| 512 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTypeOf *) { | |
| 513 | return Stage1ZirInstIdTypeOf; | |
| 514 | } | |
| 515 | ||
| 516 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSetCold *) { | |
| 517 | return Stage1ZirInstIdSetCold; | |
| 518 | } | |
| 519 | ||
| 520 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSetRuntimeSafety *) { | |
| 521 | return Stage1ZirInstIdSetRuntimeSafety; | |
| 522 | } | |
| 523 | ||
| 524 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSetFloatMode *) { | |
| 525 | return Stage1ZirInstIdSetFloatMode; | |
| 526 | } | |
| 527 | ||
| 528 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstArrayType *) { | |
| 529 | return Stage1ZirInstIdArrayType; | |
| 530 | } | |
| 531 | ||
| 532 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAnyFrameType *) { | |
| 533 | return Stage1ZirInstIdAnyFrameType; | |
| 534 | } | |
| 535 | ||
| 536 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSliceType *) { | |
| 537 | return Stage1ZirInstIdSliceType; | |
| 538 | } | |
| 539 | ||
| 540 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAsm *) { | |
| 541 | return Stage1ZirInstIdAsm; | |
| 542 | } | |
| 543 | ||
| 544 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSizeOf *) { | |
| 545 | return Stage1ZirInstIdSizeOf; | |
| 546 | } | |
| 547 | ||
| 548 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTestNonNull *) { | |
| 549 | return Stage1ZirInstIdTestNonNull; | |
| 550 | } | |
| 551 | ||
| 552 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstOptionalUnwrapPtr *) { | |
| 553 | return Stage1ZirInstIdOptionalUnwrapPtr; | |
| 554 | } | |
| 555 | ||
| 556 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstClz *) { | |
| 557 | return Stage1ZirInstIdClz; | |
| 558 | } | |
| 559 | ||
| 560 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCtz *) { | |
| 561 | return Stage1ZirInstIdCtz; | |
| 562 | } | |
| 563 | ||
| 564 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPopCount *) { | |
| 565 | return Stage1ZirInstIdPopCount; | |
| 566 | } | |
| 567 | ||
| 568 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBswap *) { | |
| 569 | return Stage1ZirInstIdBswap; | |
| 570 | } | |
| 571 | ||
| 572 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBitReverse *) { | |
| 573 | return Stage1ZirInstIdBitReverse; | |
| 574 | } | |
| 575 | ||
| 576 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstImport *) { | |
| 577 | return Stage1ZirInstIdImport; | |
| 578 | } | |
| 579 | ||
| 580 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCImport *) { | |
| 581 | return Stage1ZirInstIdCImport; | |
| 582 | } | |
| 583 | ||
| 584 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCInclude *) { | |
| 585 | return Stage1ZirInstIdCInclude; | |
| 586 | } | |
| 587 | ||
| 588 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCDefine *) { | |
| 589 | return Stage1ZirInstIdCDefine; | |
| 590 | } | |
| 591 | ||
| 592 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCUndef *) { | |
| 593 | return Stage1ZirInstIdCUndef; | |
| 594 | } | |
| 595 | ||
| 596 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstRef *) { | |
| 597 | return Stage1ZirInstIdRef; | |
| 598 | } | |
| 599 | ||
| 600 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCompileErr *) { | |
| 601 | return Stage1ZirInstIdCompileErr; | |
| 602 | } | |
| 603 | ||
| 604 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCompileLog *) { | |
| 605 | return Stage1ZirInstIdCompileLog; | |
| 606 | } | |
| 607 | ||
| 608 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstErrName *) { | |
| 609 | return Stage1ZirInstIdErrName; | |
| 610 | } | |
| 611 | ||
| 612 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstEmbedFile *) { | |
| 613 | return Stage1ZirInstIdEmbedFile; | |
| 614 | } | |
| 615 | ||
| 616 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCmpxchg *) { | |
| 617 | return Stage1ZirInstIdCmpxchg; | |
| 618 | } | |
| 619 | ||
| 620 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFence *) { | |
| 621 | return Stage1ZirInstIdFence; | |
| 622 | } | |
| 623 | ||
| 624 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstReduce *) { | |
| 625 | return Stage1ZirInstIdReduce; | |
| 626 | } | |
| 627 | ||
| 628 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTruncate *) { | |
| 629 | return Stage1ZirInstIdTruncate; | |
| 630 | } | |
| 631 | ||
| 632 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstIntCast *) { | |
| 633 | return Stage1ZirInstIdIntCast; | |
| 634 | } | |
| 635 | ||
| 636 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFloatCast *) { | |
| 637 | return Stage1ZirInstIdFloatCast; | |
| 638 | } | |
| 639 | ||
| 640 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstIntToFloat *) { | |
| 641 | return Stage1ZirInstIdIntToFloat; | |
| 642 | } | |
| 643 | ||
| 644 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFloatToInt *) { | |
| 645 | return Stage1ZirInstIdFloatToInt; | |
| 646 | } | |
| 647 | ||
| 648 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBoolToInt *) { | |
| 649 | return Stage1ZirInstIdBoolToInt; | |
| 650 | } | |
| 651 | ||
| 652 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstVectorType *) { | |
| 653 | return Stage1ZirInstIdVectorType; | |
| 654 | } | |
| 655 | ||
| 656 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstShuffleVector *) { | |
| 657 | return Stage1ZirInstIdShuffleVector; | |
| 658 | } | |
| 659 | ||
| 660 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSelect *) { | |
| 661 | return Stage1ZirInstIdSelect; | |
| 662 | } | |
| 663 | ||
| 664 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSplat *) { | |
| 665 | return Stage1ZirInstIdSplat; | |
| 666 | } | |
| 667 | ||
| 668 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBoolNot *) { | |
| 669 | return Stage1ZirInstIdBoolNot; | |
| 670 | } | |
| 671 | ||
| 672 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstMemset *) { | |
| 673 | return Stage1ZirInstIdMemset; | |
| 674 | } | |
| 675 | ||
| 676 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstMemcpy *) { | |
| 677 | return Stage1ZirInstIdMemcpy; | |
| 678 | } | |
| 679 | ||
| 680 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSlice *) { | |
| 681 | return Stage1ZirInstIdSlice; | |
| 682 | } | |
| 683 | ||
| 684 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBreakpoint *) { | |
| 685 | return Stage1ZirInstIdBreakpoint; | |
| 686 | } | |
| 687 | ||
| 688 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstReturnAddress *) { | |
| 689 | return Stage1ZirInstIdReturnAddress; | |
| 690 | } | |
| 691 | ||
| 692 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFrameAddress *) { | |
| 693 | return Stage1ZirInstIdFrameAddress; | |
| 694 | } | |
| 695 | ||
| 696 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFrameHandle *) { | |
| 697 | return Stage1ZirInstIdFrameHandle; | |
| 698 | } | |
| 699 | ||
| 700 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFrameType *) { | |
| 701 | return Stage1ZirInstIdFrameType; | |
| 702 | } | |
| 703 | ||
| 704 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFrameSize *) { | |
| 705 | return Stage1ZirInstIdFrameSize; | |
| 706 | } | |
| 707 | ||
| 708 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAlignOf *) { | |
| 709 | return Stage1ZirInstIdAlignOf; | |
| 710 | } | |
| 711 | ||
| 712 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstOverflowOp *) { | |
| 713 | return Stage1ZirInstIdOverflowOp; | |
| 714 | } | |
| 715 | ||
| 716 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTestErr *) { | |
| 717 | return Stage1ZirInstIdTestErr; | |
| 718 | } | |
| 719 | ||
| 720 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstMulAdd *) { | |
| 721 | return Stage1ZirInstIdMulAdd; | |
| 722 | } | |
| 723 | ||
| 724 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFloatOp *) { | |
| 725 | return Stage1ZirInstIdFloatOp; | |
| 726 | } | |
| 727 | ||
| 728 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUnwrapErrCode *) { | |
| 729 | return Stage1ZirInstIdUnwrapErrCode; | |
| 730 | } | |
| 731 | ||
| 732 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUnwrapErrPayload *) { | |
| 733 | return Stage1ZirInstIdUnwrapErrPayload; | |
| 734 | } | |
| 735 | ||
| 736 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFnProto *) { | |
| 737 | return Stage1ZirInstIdFnProto; | |
| 738 | } | |
| 739 | ||
| 740 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTestComptime *) { | |
| 741 | return Stage1ZirInstIdTestComptime; | |
| 742 | } | |
| 743 | ||
| 744 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPtrCast *) { | |
| 745 | return Stage1ZirInstIdPtrCast; | |
| 746 | } | |
| 747 | ||
| 748 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBitCast *) { | |
| 749 | return Stage1ZirInstIdBitCast; | |
| 750 | } | |
| 751 | ||
| 752 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstIntToPtr *) { | |
| 753 | return Stage1ZirInstIdIntToPtr; | |
| 754 | } | |
| 755 | ||
| 756 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPtrToInt *) { | |
| 757 | return Stage1ZirInstIdPtrToInt; | |
| 758 | } | |
| 759 | ||
| 760 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstIntToEnum *) { | |
| 761 | return Stage1ZirInstIdIntToEnum; | |
| 762 | } | |
| 763 | ||
| 764 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstEnumToInt *) { | |
| 765 | return Stage1ZirInstIdEnumToInt; | |
| 766 | } | |
| 767 | ||
| 768 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstIntToErr *) { | |
| 769 | return Stage1ZirInstIdIntToErr; | |
| 770 | } | |
| 771 | ||
| 772 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstErrToInt *) { | |
| 773 | return Stage1ZirInstIdErrToInt; | |
| 774 | } | |
| 775 | ||
| 776 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCheckStatementIsVoid *) { | |
| 777 | return Stage1ZirInstIdCheckStatementIsVoid; | |
| 778 | } | |
| 779 | ||
| 780 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTypeName *) { | |
| 781 | return Stage1ZirInstIdTypeName; | |
| 782 | } | |
| 783 | ||
| 784 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstDeclRef *) { | |
| 785 | return Stage1ZirInstIdDeclRef; | |
| 786 | } | |
| 787 | ||
| 788 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPanic *) { | |
| 789 | return Stage1ZirInstIdPanic; | |
| 790 | } | |
| 791 | ||
| 792 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTagName *) { | |
| 793 | return Stage1ZirInstIdTagName; | |
| 794 | } | |
| 795 | ||
| 796 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstFieldParentPtr *) { | |
| 797 | return Stage1ZirInstIdFieldParentPtr; | |
| 798 | } | |
| 799 | ||
| 800 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstOffsetOf *) { | |
| 801 | return Stage1ZirInstIdOffsetOf; | |
| 802 | } | |
| 803 | ||
| 804 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstBitOffsetOf *) { | |
| 805 | return Stage1ZirInstIdBitOffsetOf; | |
| 806 | } | |
| 807 | ||
| 808 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstTypeInfo *) { | |
| 809 | return Stage1ZirInstIdTypeInfo; | |
| 810 | } | |
| 811 | ||
| 812 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstType *) { | |
| 813 | return Stage1ZirInstIdType; | |
| 814 | } | |
| 815 | ||
| 816 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstHasField *) { | |
| 817 | return Stage1ZirInstIdHasField; | |
| 818 | } | |
| 819 | ||
| 820 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSetEvalBranchQuota *) { | |
| 821 | return Stage1ZirInstIdSetEvalBranchQuota; | |
| 822 | } | |
| 823 | ||
| 824 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPtrType *) { | |
| 825 | return Stage1ZirInstIdPtrType; | |
| 826 | } | |
| 827 | ||
| 828 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAlignCast *) { | |
| 829 | return Stage1ZirInstIdAlignCast; | |
| 830 | } | |
| 831 | ||
| 832 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstImplicitCast *) { | |
| 833 | return Stage1ZirInstIdImplicitCast; | |
| 834 | } | |
| 835 | ||
| 836 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstResolveResult *) { | |
| 837 | return Stage1ZirInstIdResolveResult; | |
| 838 | } | |
| 839 | ||
| 840 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstResetResult *) { | |
| 841 | return Stage1ZirInstIdResetResult; | |
| 842 | } | |
| 843 | ||
| 844 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSetAlignStack *) { | |
| 845 | return Stage1ZirInstIdSetAlignStack; | |
| 846 | } | |
| 847 | ||
| 848 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstExport *) { | |
| 849 | return Stage1ZirInstIdExport; | |
| 850 | } | |
| 851 | ||
| 852 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstExtern *) { | |
| 853 | return Stage1ZirInstIdExtern; | |
| 854 | } | |
| 855 | ||
| 856 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstErrorReturnTrace *) { | |
| 857 | return Stage1ZirInstIdErrorReturnTrace; | |
| 858 | } | |
| 859 | ||
| 860 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstErrorUnion *) { | |
| 861 | return Stage1ZirInstIdErrorUnion; | |
| 862 | } | |
| 863 | ||
| 864 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAtomicRmw *) { | |
| 865 | return Stage1ZirInstIdAtomicRmw; | |
| 866 | } | |
| 867 | ||
| 868 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAtomicLoad *) { | |
| 869 | return Stage1ZirInstIdAtomicLoad; | |
| 870 | } | |
| 871 | ||
| 872 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAtomicStore *) { | |
| 873 | return Stage1ZirInstIdAtomicStore; | |
| 874 | } | |
| 875 | ||
| 876 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSaveErrRetAddr *) { | |
| 877 | return Stage1ZirInstIdSaveErrRetAddr; | |
| 878 | } | |
| 879 | ||
| 880 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAddImplicitReturnType *) { | |
| 881 | return Stage1ZirInstIdAddImplicitReturnType; | |
| 882 | } | |
| 883 | ||
| 884 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstErrSetCast *) { | |
| 885 | return Stage1ZirInstIdErrSetCast; | |
| 886 | } | |
| 887 | ||
| 888 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstCheckRuntimeScope *) { | |
| 889 | return Stage1ZirInstIdCheckRuntimeScope; | |
| 890 | } | |
| 891 | ||
| 892 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstHasDecl *) { | |
| 893 | return Stage1ZirInstIdHasDecl; | |
| 894 | } | |
| 895 | ||
| 896 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUndeclaredIdent *) { | |
| 897 | return Stage1ZirInstIdUndeclaredIdent; | |
| 898 | } | |
| 899 | ||
| 900 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAlloca *) { | |
| 901 | return Stage1ZirInstIdAlloca; | |
| 902 | } | |
| 903 | ||
| 904 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstEndExpr *) { | |
| 905 | return Stage1ZirInstIdEndExpr; | |
| 906 | } | |
| 907 | ||
| 908 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstUnionInitNamedField *) { | |
| 909 | return Stage1ZirInstIdUnionInitNamedField; | |
| 910 | } | |
| 911 | ||
| 912 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSuspendBegin *) { | |
| 913 | return Stage1ZirInstIdSuspendBegin; | |
| 914 | } | |
| 915 | ||
| 916 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSuspendFinish *) { | |
| 917 | return Stage1ZirInstIdSuspendFinish; | |
| 918 | } | |
| 919 | ||
| 920 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAwait *) { | |
| 921 | return Stage1ZirInstIdAwait; | |
| 922 | } | |
| 923 | ||
| 924 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstResume *) { | |
| 925 | return Stage1ZirInstIdResume; | |
| 926 | } | |
| 927 | ||
| 928 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSpillBegin *) { | |
| 929 | return Stage1ZirInstIdSpillBegin; | |
| 930 | } | |
| 931 | ||
| 932 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSpillEnd *) { | |
| 933 | return Stage1ZirInstIdSpillEnd; | |
| 934 | } | |
| 935 | ||
| 936 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstWasmMemorySize *) { | |
| 937 | return Stage1ZirInstIdWasmMemorySize; | |
| 938 | } | |
| 939 | ||
| 940 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstWasmMemoryGrow *) { | |
| 941 | return Stage1ZirInstIdWasmMemoryGrow; | |
| 942 | } | |
| 943 | ||
| 944 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstSrc *) { | |
| 945 | return Stage1ZirInstIdSrc; | |
| 946 | } | |
| 947 | ||
| 948 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstPrefetch *) { | |
| 949 | return Stage1ZirInstIdPrefetch; | |
| 950 | } | |
| 951 | ||
| 952 | static constexpr Stage1ZirInstId ir_inst_id(Stage1ZirInstAddrSpaceCast *) { | |
| 953 | return Stage1ZirInstIdAddrSpaceCast; | |
| 954 | } | |
| 955 | ||
| 956 | template<typename T> | |
| 957 | static 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 | ||
| 967 | template<typename T> | |
| 968 | static 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 | ||
| 974 | static 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 | ||
| 991 | static 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 | ||
| 1000 | static 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 | ||
| 1007 | static 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 | ||
| 1015 | static 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 | ||
| 1024 | static 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 | ||
| 1035 | static 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 | ||
| 1046 | static 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 | ||
| 1053 | static 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 | ||
| 1062 | static 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 | ||
| 1073 | static 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 | ||
| 1081 | static 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 | ||
| 1090 | static 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 | ||
| 1099 | static 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`. | |
| 1109 | static 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`. | |
| 1118 | static 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 | ||
| 1124 | static 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 | ||
| 1139 | static 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 | ||
| 1153 | static 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 | ||
| 1165 | static 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 | ||
| 1169 | static 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 | ||
| 1186 | static 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 | ||
| 1201 | static 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 | ||
| 1215 | static 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 | ||
| 1228 | static 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 | ||
| 1244 | static 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 | ||
| 1263 | static 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 | ||
| 1282 | static 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 | ||
| 1307 | static 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 | ||
| 1329 | static 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 | ||
| 1342 | static 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 | ||
| 1360 | static 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 | ||
| 1389 | static 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 | ||
| 1403 | static 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 | ||
| 1409 | static 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 | ||
| 1428 | static 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 | ||
| 1445 | static 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 | ||
| 1450 | static 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 | ||
| 1463 | static 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 | ||
| 1477 | static 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 | ||
| 1491 | static 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 | ||
| 1505 | static 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 | ||
| 1514 | static 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 | ||
| 1529 | static 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 | ||
| 1538 | static 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 | ||
| 1547 | static 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 | ||
| 1558 | static 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 | ||
| 1569 | static 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 | ||
| 1584 | static 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 | ||
| 1595 | static 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 | ||
| 1614 | static 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 | ||
| 1641 | static 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 | ||
| 1653 | static 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 | ||
| 1664 | static 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 | ||
| 1676 | static 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 | ||
| 1689 | static 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 | ||
| 1702 | static 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 | ||
| 1715 | static 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 | ||
| 1728 | static 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 | ||
| 1741 | static 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 | ||
| 1766 | static 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 | ||
| 1777 | static 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. | |
| 1794 | static 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 | ||
| 1805 | static 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 | ||
| 1814 | static 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 | ||
| 1823 | static 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 | ||
| 1832 | static 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 | ||
| 1846 | static 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 | ||
| 1855 | static 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 | ||
| 1860 | static 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 | ||
| 1869 | static 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 | ||
| 1880 | static 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 | ||
| 1889 | static 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 | ||
| 1898 | static 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 | ||
| 1922 | static 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 | ||
| 1931 | static 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 | ||
| 1942 | static 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 | ||
| 1955 | static 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 | ||
| 1968 | static 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 | ||
| 1981 | static 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 | ||
| 1994 | static 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 | ||
| 2007 | static 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 | ||
| 2020 | static 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 | ||
| 2029 | static 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 | ||
| 2042 | static 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 | ||
| 2059 | static 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 | ||
| 2075 | static 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 | ||
| 2088 | static 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 | ||
| 2097 | static 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 | ||
| 2112 | static 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 | ||
| 2127 | static 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 | ||
| 2147 | static 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 | ||
| 2152 | static 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 | ||
| 2157 | static 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 | ||
| 2162 | static 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 | ||
| 2167 | static 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 | ||
| 2176 | static 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 | ||
| 2185 | static 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 | ||
| 2203 | static 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 | ||
| 2215 | static 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 | ||
| 2232 | static 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 | ||
| 2241 | static 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 | ||
| 2254 | static 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 | ||
| 2265 | static 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 | ||
| 2278 | static 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 | ||
| 2302 | static 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 | ||
| 2311 | static 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 | ||
| 2326 | static 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 | ||
| 2338 | static 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 | ||
| 2350 | static 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 | ||
| 2363 | static 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 | ||
| 2374 | static 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 | ||
| 2387 | static 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 | ||
| 2399 | static 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 | ||
| 2410 | static 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 | ||
| 2422 | static 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 | ||
| 2449 | static 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 | ||
| 2461 | static 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 | ||
| 2472 | static 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 | ||
| 2480 | static 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 | ||
| 2489 | static 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 | ||
| 2498 | static 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 | ||
| 2514 | static 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 | ||
| 2527 | static 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 | ||
| 2540 | static 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 | ||
| 2549 | static 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 | ||
| 2558 | static 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 | ||
| 2569 | static 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 | ||
| 2582 | static 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 | ||
| 2595 | static 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 | ||
| 2607 | static 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 | ||
| 2616 | static 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 | ||
| 2627 | static 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 | ||
| 2648 | static 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 | ||
| 2657 | static 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 | ||
| 2670 | static 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 | ||
| 2690 | static 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 | ||
| 2705 | static 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 | ||
| 2722 | static 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 | ||
| 2727 | static 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 | ||
| 2739 | static 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 | ||
| 2752 | static 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 | ||
| 2759 | static 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 | ||
| 2770 | static 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 | ||
| 2787 | static 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 | ||
| 2801 | static 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 | ||
| 2813 | static 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 | ||
| 2817 | static 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 | ||
| 2828 | static 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 | ||
| 2841 | static 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 | ||
| 2850 | static 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 | ||
| 2862 | static 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 | ||
| 2873 | static 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 | ||
| 2882 | static 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 | ||
| 2893 | static 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 | ||
| 2899 | static 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 | ||
| 2914 | static 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 | ||
| 2952 | static 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 | ||
| 3038 | static void ir_set_cursor_at_end(Stage1AstGen *ag, Stage1ZirBasicBlock *basic_block) { | |
| 3039 | assert(basic_block); | |
| 3040 | ag->current_basic_block = basic_block; | |
| 3041 | } | |
| 3042 | ||
| 3043 | static 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 | ||
| 3049 | static 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 | ||
| 3061 | static 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 | ||
| 3073 | static 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 | ||
| 3211 | ZigVar *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 | |
| 3259 | static 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 | ||
| 3270 | static 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 | ||
| 3279 | static 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 | ||
| 3298 | static 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 | ||
| 3450 | static 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 | ||
| 3465 | static 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 | ||
| 3479 | static 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 | ||
| 3498 | static 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 | ||
| 3511 | static 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 | ||
| 3555 | static 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 | ||
| 3599 | static 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 | ||
| 3619 | static 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 | ||
| 3633 | static 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 | ||
| 3690 | static 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 | ||
| 3707 | static 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 | ||
| 3814 | static 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 | ||
| 3823 | static 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 | ||
| 3840 | static 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 | ||
| 3860 | static 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 | ||
| 3976 | static 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 | ||
| 4008 | static 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 | ||
| 4021 | static 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 | ||
| 4049 | static 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 | ||
| 4076 | static 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 | ||
| 4091 | static 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 | ||
| 4150 | static 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 | ||
| 4187 | static 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 | ||
| 5520 | static 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 | ||
| 5532 | static 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 | ||
| 5551 | static 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 | ||
| 5616 | static 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 | ||
| 5627 | static 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 | ||
| 5631 | static 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 | ||
| 5637 | static 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 | ||
| 5663 | static 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 | ||
| 5677 | static 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 | ||
| 5697 | static 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 | ||
| 5762 | static 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 | ||
| 5780 | static 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 | ||
| 5791 | static 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 | ||
| 5819 | static 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 | ||
| 5844 | static 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 | ||
| 5974 | static 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 | ||
| 5986 | static 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 | ||
| 6001 | static 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 | ||
| 6010 | static 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 | ||
| 6102 | static 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 | ||
| 6459 | static 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 | ||
| 6610 | static 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 | ||
| 6623 | static 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 | ||
| 6665 | static 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 | ||
| 6733 | static 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 | ||
| 6749 | static 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 | ||
| 6838 | static 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 | ||
| 6927 | static 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 | ||
| 7025 | static 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 | ||
| 7085 | static 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 | ||
| 7363 | static 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 | ||
| 7371 | static 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 | ||
| 7379 | static 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 | ||
| 7409 | static 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 | ||
| 7486 | static 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 | ||
| 7545 | static 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 | ||
| 7550 | static 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 | ||
| 7562 | static 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 | ||
| 7602 | static 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 | ||
| 7688 | static 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 | ||
| 7702 | Buf *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 | ||
| 7764 | static 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 | ||
| 7796 | static 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 | ||
| 7847 | static 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 | ||
| 7897 | static 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 | ||
| 7907 | static 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 | ||
| 7949 | static 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 | ||
| 7982 | static 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 | ||
| 8130 | ResultLoc *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 | ||
| 8136 | static 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 | ||
| 8250 | static Stage1ZirInst *astgen_node(Stage1AstGen *ag, AstNode *node, Scope *scope) { | |
| 8251 | return astgen_node_extra(ag, node, scope, LValNone, nullptr); | |
| 8252 | } | |
| 8253 | ||
| 8254 | bool 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 | ||
| 8296 | bool 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 | ||
| 8302 | void 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 | ||
| 8313 | AstNode *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 | ||
| 8324 | void 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 | ||
| 8331 | void 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 | ||
| 13 | bool stage1_astgen(CodeGen *g, AstNode *node, Scope *scope, Stage1Zir *stage1_zir, | |
| 14 | ZigFn *fn, bool in_c_import_scope); | |
| 15 | bool stage1_astgen_fn(CodeGen *g, ZigFn *fn_entry); | |
| 16 | ||
| 17 | bool ir_inst_src_has_side_effects(Stage1ZirInst *inst); | |
| 18 | ||
| 19 | ZigVar *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 | ||
| 23 | ResultLoc *no_result_loc(void); | |
| 24 | ||
| 25 | void invalidate_exec(Stage1Zir *exec, ErrorMsg *msg); | |
| 26 | ||
| 27 | AstNode *ast_field_to_symbol_node(AstNode *err_set_field_node); | |
| 28 | void ir_add_call_stack_errors_gen(CodeGen *codegen, Stage1Air *exec, ErrorMsg *err_msg, | |
| 29 | int limit); | |
| 30 | ||
| 31 | void destroy_instruction_src(Stage1ZirInst *inst); | |
| 32 | ||
| 33 | bool ir_should_inline(Stage1Zir *exec, Scope *scope); | |
| 34 | Buf *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 | ||
| 19 | void bigfloat_init_128(BigFloat *dest, float128_t x) { | |
| 20 | dest->value = x; | |
| 21 | } | |
| 22 | ||
| 23 | void bigfloat_init_16(BigFloat *dest, float16_t x) { | |
| 24 | f16_to_f128M(x, &dest->value); | |
| 25 | } | |
| 26 | ||
| 27 | void 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 | ||
| 33 | void 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 | ||
| 39 | void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x) { | |
| 40 | memcpy(&dest->value, &x->value, sizeof(float128_t)); | |
| 41 | } | |
| 42 | ||
| 43 | void 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 | ||
| 72 | Error 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 | ||
| 85 | void bigfloat_add(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { | |
| 86 | f128M_add(&op1->value, &op2->value, &dest->value); | |
| 87 | } | |
| 88 | ||
| 89 | void bigfloat_negate(BigFloat *dest, const BigFloat *op) { | |
| 90 | f128M_neg(&op->value, &dest->value); | |
| 91 | } | |
| 92 | ||
| 93 | void bigfloat_sub(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { | |
| 94 | f128M_sub(&op1->value, &op2->value, &dest->value); | |
| 95 | } | |
| 96 | ||
| 97 | void bigfloat_mul(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { | |
| 98 | f128M_mul(&op1->value, &op2->value, &dest->value); | |
| 99 | } | |
| 100 | ||
| 101 | void bigfloat_div(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { | |
| 102 | f128M_div(&op1->value, &op2->value, &dest->value); | |
| 103 | } | |
| 104 | ||
| 105 | void 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 | ||
| 110 | void 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 | ||
| 115 | void bigfloat_rem(BigFloat *dest, const BigFloat *op1, const BigFloat *op2) { | |
| 116 | f128M_rem(&op1->value, &op2->value, &dest->value); | |
| 117 | } | |
| 118 | ||
| 119 | void 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 | ||
| 125 | void 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 | ||
| 140 | Cmp 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 | ||
| 150 | float16_t bigfloat_to_f16(const BigFloat *bigfloat) { | |
| 151 | return f128M_to_f16(&bigfloat->value); | |
| 152 | } | |
| 153 | ||
| 154 | float 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 | ||
| 161 | double 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 | ||
| 168 | float128_t bigfloat_to_f128(const BigFloat *bigfloat) { | |
| 169 | return bigfloat->value; | |
| 170 | } | |
| 171 | ||
| 172 | Cmp 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 | ||
| 184 | bool 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 | ||
| 190 | void bigfloat_sqrt(BigFloat *dest, const BigFloat *op) { | |
| 191 | f128M_sqrt(&op->value, &dest->value); | |
| 192 | } | |
| 193 | ||
| 194 | void 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 | ||
| 206 | void 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 | ||
| 218 | bool 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 | ||
| 19 | struct BigFloat { | |
| 20 | float128_t value; | |
| 21 | }; | |
| 22 | ||
| 23 | struct Buf; | |
| 24 | ||
| 25 | void bigfloat_init_16(BigFloat *dest, float16_t x); | |
| 26 | void bigfloat_init_32(BigFloat *dest, float x); | |
| 27 | void bigfloat_init_64(BigFloat *dest, double x); | |
| 28 | void bigfloat_init_128(BigFloat *dest, float128_t x); | |
| 29 | void bigfloat_init_bigfloat(BigFloat *dest, const BigFloat *x); | |
| 30 | void bigfloat_init_bigint(BigFloat *dest, const BigInt *op); | |
| 31 | Error bigfloat_init_buf(BigFloat *dest, const uint8_t *buf_ptr); | |
| 32 | ||
| 33 | float16_t bigfloat_to_f16(const BigFloat *bigfloat); | |
| 34 | float bigfloat_to_f32(const BigFloat *bigfloat); | |
| 35 | double bigfloat_to_f64(const BigFloat *bigfloat); | |
| 36 | float128_t bigfloat_to_f128(const BigFloat *bigfloat); | |
| 37 | ||
| 38 | void bigfloat_add(BigFloat *dest, const BigFloat *op1, const BigFloat *op2); | |
| 39 | void bigfloat_negate(BigFloat *dest, const BigFloat *op); | |
| 40 | void bigfloat_sub(BigFloat *dest, const BigFloat *op1, const BigFloat *op2); | |
| 41 | void bigfloat_mul(BigFloat *dest, const BigFloat *op1, const BigFloat *op2); | |
| 42 | void bigfloat_div(BigFloat *dest, const BigFloat *op1, const BigFloat *op2); | |
| 43 | void bigfloat_div_trunc(BigFloat *dest, const BigFloat *op1, const BigFloat *op2); | |
| 44 | void bigfloat_div_floor(BigFloat *dest, const BigFloat *op1, const BigFloat *op2); | |
| 45 | void bigfloat_rem(BigFloat *dest, const BigFloat *op1, const BigFloat *op2); | |
| 46 | void bigfloat_mod(BigFloat *dest, const BigFloat *op1, const BigFloat *op2); | |
| 47 | void bigfloat_sqrt(BigFloat *dest, const BigFloat *op); | |
| 48 | void bigfloat_min(BigFloat *dest, const BigFloat *op1, const BigFloat *op2); | |
| 49 | void bigfloat_max(BigFloat *dest, const BigFloat *op1, const BigFloat *op2); | |
| 50 | void bigfloat_append_buf(Buf *buf, const BigFloat *op); | |
| 51 | Cmp bigfloat_cmp(const BigFloat *op1, const BigFloat *op2); | |
| 52 | ||
| 53 | ||
| 54 | bool bigfloat_is_nan(const BigFloat *op); | |
| 55 | ||
| 56 | // convenience functions | |
| 57 | Cmp bigfloat_cmp_zero(const BigFloat *bigfloat); | |
| 58 | bool 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 | ||
| 18 | static uint64_t bigint_as_unsigned(const BigInt *bigint); | |
| 19 | ||
| 20 | static 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 | ||
| 41 | static 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 | ||
| 51 | size_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 | ||
| 58 | static 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 | ||
| 115 | static 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 | ||
| 125 | static 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 | ||
| 151 | void 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 | ||
| 162 | void 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 | ||
| 171 | void 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 | ||
| 190 | void 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 | ||
| 205 | void bigint_deinit(BigInt *bi) { | |
| 206 | if (bi->digit_count > 1) | |
| 207 | heap::c_allocator.deallocate(bi->data.digits, bi->digit_count); | |
| 208 | } | |
| 209 | ||
| 210 | void 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 | ||
| 243 | bool 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 | ||
| 280 | void 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 | ||
| 343 | void 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) | |
| 414 | static 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 | ||
| 419 | static bool sub_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) { | |
| 420 | *result = op1 - op2; | |
| 421 | return *result > op1; | |
| 422 | } | |
| 423 | ||
| 424 | bool 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 | |
| 439 | static 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 | ||
| 444 | static 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 | ||
| 449 | bool 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 | ||
| 455 | void 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 | ||
| 465 | void 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] | |
| 478 | void 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 | ||
| 533 | void 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 | ||
| 538 | void 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 | ||
| 543 | void 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 | ||
| 548 | void 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 | ||
| 553 | void 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 | ||
| 668 | void 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 | ||
| 674 | void 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 | ||
| 680 | void 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 | ||
| 686 | static 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 | ||
| 706 | static 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 | ||
| 744 | void 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 | ||
| 785 | void 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 | ||
| 791 | enum 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 | ||
| 800 | template <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) | |
| 819 | template <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) | |
| 835 | template <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. | |
| 859 | template <typename T> | |
| 860 | std::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. | |
| 868 | constexpr 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. | |
| 873 | constexpr 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. | |
| 878 | constexpr 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. | |
| 886 | static 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 | |
| 1007 | static 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 | ||
| 1160 | void 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 | ||
| 1206 | void 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 | ||
| 1225 | void 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 | ||
| 1278 | void 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 | ||
| 1293 | void 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 | ||
| 1339 | void 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 | ||
| 1381 | void 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 | ||
| 1432 | void 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 | ||
| 1483 | void 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 | ||
| 1489 | void 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 | ||
| 1545 | void 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 | ||
| 1551 | void 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 | ||
| 1557 | void 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 | ||
| 1615 | void 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 | ||
| 1621 | Cmp 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 | ||
| 1653 | void 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 | ||
| 1706 | size_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 | ||
| 1720 | size_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 | ||
| 1737 | size_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 | ||
| 1755 | size_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 | ||
| 1773 | static 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 | ||
| 1784 | uint64_t bigint_as_u64(const BigInt *bigint) | |
| 1785 | { | |
| 1786 | return bigint_as_unsigned(bigint); | |
| 1787 | } | |
| 1788 | ||
| 1789 | uint32_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 | ||
| 1796 | uint8_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 | ||
| 1803 | size_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 | ||
| 1810 | int64_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 | ||
| 1828 | Cmp 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 | ||
| 1835 | uint32_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 | ||
| 1843 | bool bigint_eql(BigInt const *a, BigInt const *b) { | |
| 1844 | return bigint_cmp(a, b) == CmpEQ; | |
| 1845 | } | |
| 1846 | ||
| 1847 | void 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 | ||
| 1872 | void 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 | ||
| 14 | struct 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 | ||
| 23 | struct Buf; | |
| 24 | struct BigFloat; | |
| 25 | ||
| 26 | enum Cmp { | |
| 27 | CmpLT, | |
| 28 | CmpGT, | |
| 29 | CmpEQ, | |
| 30 | }; | |
| 31 | ||
| 32 | void bigint_init_unsigned(BigInt *dest, uint64_t x); | |
| 33 | void bigint_init_signed(BigInt *dest, int64_t x); | |
| 34 | void bigint_init_bigint(BigInt *dest, const BigInt *src); | |
| 35 | void bigint_init_bigfloat(BigInt *dest, const BigFloat *op); | |
| 36 | void bigint_init_data(BigInt *dest, const uint64_t *digits, size_t digit_count, bool is_negative); | |
| 37 | void bigint_deinit(BigInt *bi); | |
| 38 | ||
| 39 | // panics if number won't fit | |
| 40 | uint64_t bigint_as_u64(const BigInt *bigint); | |
| 41 | uint32_t bigint_as_u32(const BigInt *bigint); | |
| 42 | uint8_t bigint_as_u8(const BigInt *bigint); | |
| 43 | size_t bigint_as_usize(const BigInt *bigint); | |
| 44 | ||
| 45 | int64_t bigint_as_signed(const BigInt *bigint); | |
| 46 | ||
| 47 | static 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 | ||
| 55 | bool bigint_fits_in_bits(const BigInt *bn, size_t bit_count, bool is_signed); | |
| 56 | void bigint_write_twos_complement(const BigInt *big_int, uint8_t *buf, size_t bit_count, bool is_big_endian); | |
| 57 | void bigint_read_twos_complement(BigInt *dest, const uint8_t *buf, size_t bit_count, bool is_big_endian, | |
| 58 | bool is_signed); | |
| 59 | void bigint_max(BigInt* dest, const BigInt *op1, const BigInt *op2); | |
| 60 | void bigint_min(BigInt* dest, const BigInt *op1, const BigInt *op2); | |
| 61 | void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 62 | void bigint_add_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed); | |
| 63 | void bigint_sub(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 64 | void bigint_sub_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed); | |
| 65 | void bigint_mul(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 66 | void bigint_mul_wrap(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed); | |
| 67 | void bigint_div_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 68 | void bigint_div_floor(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 69 | void bigint_rem(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 70 | void bigint_mod(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 71 | ||
| 72 | void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 73 | void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 74 | void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 75 | ||
| 76 | void bigint_shl(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 77 | void bigint_shl_trunc(BigInt *dest, const BigInt *op1, const BigInt *op2, size_t bit_count, bool is_signed); | |
| 78 | void bigint_shr(BigInt *dest, const BigInt *op1, const BigInt *op2); | |
| 79 | ||
| 80 | void bigint_negate(BigInt *dest, const BigInt *op); | |
| 81 | void bigint_negate_wrap(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed); | |
| 82 | void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed); | |
| 83 | void bigint_truncate(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed); | |
| 84 | ||
| 85 | Cmp bigint_cmp(const BigInt *op1, const BigInt *op2); | |
| 86 | ||
| 87 | void bigint_append_buf(Buf *buf, const BigInt *op, uint64_t base); | |
| 88 | ||
| 89 | size_t bigint_ctz(const BigInt *bi, size_t bit_count); | |
| 90 | size_t bigint_clz(const BigInt *bi, size_t bit_count); | |
| 91 | size_t bigint_popcount_signed(const BigInt *bi, size_t bit_count); | |
| 92 | size_t bigint_popcount_unsigned(const BigInt *bi); | |
| 93 | ||
| 94 | size_t bigint_bits_needed(const BigInt *op); | |
| 95 | ||
| 96 | ||
| 97 | // convenience functions | |
| 98 | Cmp bigint_cmp_zero(const BigInt *op); | |
| 99 | ||
| 100 | void bigint_incr(BigInt *value); | |
| 101 | void bigint_decr(BigInt *value); | |
| 102 | ||
| 103 | bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result); | |
| 104 | ||
| 105 | uint32_t bigint_hash(BigInt const *x); | |
| 106 | bool bigint_eql(BigInt const *a, BigInt const *b); | |
| 107 | ||
| 108 | void bigint_add_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed); | |
| 109 | void bigint_sub_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed); | |
| 110 | void bigint_mul_sat(BigInt* dest, const BigInt *op1, const BigInt *op2, uint32_t bit_count, bool is_signed); | |
| 111 | void 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 | ||
| 13 | Buf *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 | ||
| 32 | Buf *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 | ||
| 40 | void 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 | |
| 63 | bool buf_eql_buf(Buf *buf, Buf *other) { | |
| 64 | return buf_eql_mem(buf, buf_ptr(other), buf_len(other)); | |
| 65 | } | |
| 66 | ||
| 67 | uint32_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. | |
| 21 | struct Buf { | |
| 22 | ZigList<char> list; | |
| 23 | }; | |
| 24 | ||
| 25 | Buf *buf_sprintf(const char *format, ...) | |
| 26 | ATTRIBUTE_PRINTF(1, 2); | |
| 27 | Buf *buf_vprintf(const char *format, va_list ap); | |
| 28 | ||
| 29 | static inline size_t buf_len(const Buf *buf) { | |
| 30 | assert(buf); | |
| 31 | assert(buf->list.length); | |
| 32 | return buf->list.length - 1; | |
| 33 | } | |
| 34 | ||
| 35 | static inline char *buf_ptr(Buf *buf) { | |
| 36 | assert(buf); | |
| 37 | assert(buf->list.length); | |
| 38 | return buf->list.items; | |
| 39 | } | |
| 40 | ||
| 41 | static inline const char *buf_ptr(const Buf *buf) { | |
| 42 | assert(buf); | |
| 43 | assert(buf->list.length); | |
| 44 | return buf->list.items; | |
| 45 | } | |
| 46 | ||
| 47 | static 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 | ||
| 52 | static 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 | ||
| 58 | static inline Buf *buf_alloc(void) { | |
| 59 | return buf_alloc_fixed(0); | |
| 60 | } | |
| 61 | ||
| 62 | static inline void buf_deinit(Buf *buf) { | |
| 63 | buf->list.deinit(); | |
| 64 | } | |
| 65 | ||
| 66 | static inline void buf_destroy(Buf *buf) { | |
| 67 | buf_deinit(buf); | |
| 68 | heap::c_allocator.destroy(buf); | |
| 69 | } | |
| 70 | ||
| 71 | static 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 | ||
| 78 | static inline void buf_init_from_str(Buf *buf, const char *str) { | |
| 79 | buf_init_from_mem(buf, str, strlen(str)); | |
| 80 | } | |
| 81 | ||
| 82 | static inline void buf_init_from_buf(Buf *buf, Buf *other) { | |
| 83 | buf_init_from_mem(buf, buf_ptr(other), buf_len(other)); | |
| 84 | } | |
| 85 | ||
| 86 | static 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 | ||
| 93 | static inline Buf *buf_create_from_slice(Slice<uint8_t> slice) { | |
| 94 | return buf_create_from_mem((const char *)slice.ptr, slice.len); | |
| 95 | } | |
| 96 | ||
| 97 | static inline Buf *buf_create_from_str(const char *str) { | |
| 98 | return buf_create_from_mem(str, strlen(str)); | |
| 99 | } | |
| 100 | ||
| 101 | static inline Buf *buf_create_from_buf(Buf *buf) { | |
| 102 | return buf_create_from_mem(buf_ptr(buf), buf_len(buf)); | |
| 103 | } | |
| 104 | ||
| 105 | static 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 | ||
| 118 | static 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 | ||
| 127 | static 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 | ||
| 132 | static 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 | ||
| 137 | static 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 | ||
| 142 | void buf_appendf(Buf *buf, const char *format, ...) | |
| 143 | ATTRIBUTE_PRINTF(2, 3); | |
| 144 | ||
| 145 | static 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 | ||
| 150 | static 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 | ||
| 155 | static 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 | ||
| 160 | static 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 | ||
| 165 | static 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 | ||
| 172 | static 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 | ||
| 176 | static inline bool buf_starts_with_str(Buf *buf, const char *str) { | |
| 177 | return buf_starts_with_mem(buf, str, strlen(str)); | |
| 178 | } | |
| 179 | ||
| 180 | static 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 | ||
| 184 | static inline bool buf_ends_with_str(Buf *buf, const char *str) { | |
| 185 | return buf_ends_with_mem(buf, str, strlen(str)); | |
| 186 | } | |
| 187 | ||
| 188 | bool buf_eql_buf(Buf *buf, Buf *other); | |
| 189 | uint32_t buf_hash(Buf *buf); | |
| 190 | ||
| 191 | static 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 | ||
| 197 | static 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 | ||
| 201 | static 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 | ||
| 27 | enum ResumeId { | |
| 28 | ResumeIdManual, | |
| 29 | ResumeIdReturn, | |
| 30 | ResumeIdCall, | |
| 31 | }; | |
| 32 | ||
| 33 | static 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 | ||
| 42 | ZigPackage *new_anonymous_package() { | |
| 43 | return new_package("", "", ""); | |
| 44 | } | |
| 45 | ||
| 46 | static 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 | ||
| 76 | void 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 | ||
| 83 | static LLVMValueRef get_soft_float_fn(CodeGen *g, const char *name, int param_count, LLVMTypeRef param_type, LLVMTypeRef return_type); | |
| 84 | static void render_const_val(CodeGen *g, ZigValue *const_val, const char *name); | |
| 85 | static void render_const_val_global(CodeGen *g, ZigValue *const_val, const char *name); | |
| 86 | static LLVMValueRef gen_const_val(CodeGen *g, ZigValue *const_val, const char *name); | |
| 87 | static void generate_error_name_table(CodeGen *g); | |
| 88 | static bool value_is_all_undef(CodeGen *g, ZigValue *const_val); | |
| 89 | static void gen_undef_init(CodeGen *g, ZigType *ptr_type, ZigType *value_type, LLVMValueRef ptr); | |
| 90 | static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment); | |
| 91 | static 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 | ||
| 95 | static 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 | ||
| 102 | static 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 | ||
| 110 | static 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 | ||
| 119 | static void addLLVMFnAttr(LLVMValueRef fn_val, const char *attr_name) { | |
| 120 | return addLLVMAttr(fn_val, -1, attr_name); | |
| 121 | } | |
| 122 | ||
| 123 | static 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 | ||
| 127 | static 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 | ||
| 131 | static void addLLVMArgAttr(LLVMValueRef fn_val, unsigned param_index, const char *attr_name) { | |
| 132 | return addLLVMAttr(fn_val, param_index + 1, attr_name); | |
| 133 | } | |
| 134 | ||
| 135 | static 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 | ||
| 139 | static 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 | ||
| 148 | static 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 | |
| 162 | static 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 | ||
| 228 | static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { | |
| 229 | if (g->unwind_tables) { | |
| 230 | addLLVMFnAttrInt(fn_val, "uwtable", 2); | |
| 231 | } | |
| 232 | } | |
| 233 | ||
| 234 | static 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 | ||
| 249 | struct CalcLLVMFieldIndex { | |
| 250 | uint32_t offset; | |
| 251 | uint32_t field_index; | |
| 252 | }; | |
| 253 | ||
| 254 | static 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] | |
| 281 | static 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 | ||
| 293 | static 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] | |
| 300 | static 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] | |
| 310 | static 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 | ||
| 323 | static 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 | ||
| 339 | static 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 | ||
| 345 | static 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 | ||
| 354 | static 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 | ||
| 381 | static 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 | ||
| 404 | static 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 | ||
| 671 | static 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 | ||
| 680 | static 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 | ||
| 686 | static 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 | ||
| 692 | static 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 | ||
| 764 | static void clear_debug_source_node(CodeGen *g) { | |
| 765 | ZigLLVMClearCurrentDebugLocation(g->builder); | |
| 766 | } | |
| 767 | ||
| 768 | static 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 | ||
| 810 | static 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 | ||
| 843 | static 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 | ||
| 902 | static 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 | ||
| 913 | static 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 | ||
| 919 | static 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 | ||
| 930 | static 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 | ||
| 938 | static 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 | ||
| 951 | static 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 | ||
| 958 | static 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 | ||
| 976 | static 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 | ||
| 995 | static bool ir_want_runtime_safety(CodeGen *g, Stage1AirInst *instruction) { | |
| 996 | return ir_want_runtime_safety_scope(g, instruction->scope); | |
| 997 | } | |
| 998 | ||
| 999 | static 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 | ||
| 1061 | static 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 | ||
| 1081 | static ZigType *ptr_to_stack_trace_type(CodeGen *g) { | |
| 1082 | return get_pointer_to_type(g, get_stack_trace_type(g), false); | |
| 1083 | } | |
| 1084 | ||
| 1085 | static 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 | |
| 1122 | static 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 | ||
| 1126 | static 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 | ||
| 1134 | static void gen_assertion(CodeGen *g, PanicMsgId msg_id, Stage1AirInst *source_instruction) { | |
| 1135 | return gen_assertion_scope(g, msg_id, source_instruction->scope); | |
| 1136 | } | |
| 1137 | ||
| 1138 | static 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 | ||
| 1152 | static 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 | ||
| 1169 | static 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 | ||
| 1187 | static 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 | ||
| 1200 | static 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 | ||
| 1214 | static 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 | ||
| 1234 | static 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 | ||
| 1248 | static 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 | ||
| 1335 | static 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 | ||
| 1401 | static 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 | ||
| 1538 | static 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 | ||
| 1551 | static 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 | ||
| 1581 | static 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 | ||
| 1614 | static 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 | ||
| 1635 | static 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 | ||
| 1652 | static 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 | ||
| 1677 | static 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 | ||
| 1691 | static 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 | ||
| 1702 | static 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 | ||
| 1755 | static 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 | ||
| 1877 | typedef 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. | |
| 1881 | static const BuildBinOpFunc float_op[3] = { LLVMBuildFAdd, LLVMBuildFSub, LLVMBuildFMul }; | |
| 1882 | static const BuildBinOpFunc wrap_op[3] = { LLVMBuildAdd, LLVMBuildSub, LLVMBuildMul }; | |
| 1883 | static const BuildBinOpFunc signed_op[3] = { LLVMBuildNSWAdd, LLVMBuildNSWSub, LLVMBuildNSWMul }; | |
| 1884 | static const BuildBinOpFunc unsigned_op[3] = { LLVMBuildNUWAdd, LLVMBuildNUWSub, LLVMBuildNUWMul }; | |
| 1885 | ||
| 1886 | static 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 | ||
| 1912 | static 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 | ||
| 1931 | static 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 | ||
| 1950 | static 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 | ||
| 2034 | static 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 | ||
| 2044 | static 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 | ||
| 2086 | void 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 | ||
| 2105 | static void report_errors_and_maybe_exit(CodeGen *g) { | |
| 2106 | if (g->errors.length != 0) { | |
| 2107 | codegen_report_errors_and_exit(g); | |
| 2108 | } | |
| 2109 | } | |
| 2110 | ||
| 2111 | ATTRIBUTE_NORETURN | |
| 2112 | static 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 | ||
| 2120 | static 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 | ||
| 2126 | static 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 | ||
| 2462 | var_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 | ||
| 2473 | void 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 | ||
| 2565 | static 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 | } | |
| 2714 | static 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 | ||
| 2740 | static 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 | ||
| 2763 | static 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 | ||
| 2780 | static 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 | |
| 2795 | static void set_tail_call_if_appropriate(CodeGen *g, LLVMValueRef call_inst) { | |
| 2796 | LLVMSetTailCall(call_inst, true); | |
| 2797 | } | |
| 2798 | ||
| 2799 | static 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 | ||
| 2822 | static 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 | ||
| 2924 | static 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 | ||
| 2944 | static 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 | ||
| 3000 | static 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 | ||
| 3035 | static 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 | ||
| 3066 | static 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 | ||
| 3077 | static 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 | ||
| 3101 | static 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 | ||
| 3115 | enum DivKind { | |
| 3116 | DivKindFloat, | |
| 3117 | DivKindTrunc, | |
| 3118 | DivKindFloor, | |
| 3119 | DivKindExact, | |
| 3120 | }; | |
| 3121 | ||
| 3122 | static 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 | ||
| 3154 | static 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 | ||
| 3305 | enum RemKind { | |
| 3306 | RemKindRem, | |
| 3307 | RemKindMod, | |
| 3308 | }; | |
| 3309 | ||
| 3310 | static 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 | ||
| 3374 | static 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 | ||
| 3400 | enum Icmp { | |
| 3401 | NONE, | |
| 3402 | EQ_ZERO, | |
| 3403 | NE_ZERO, | |
| 3404 | LE_ZERO, | |
| 3405 | EQ_NEG, | |
| 3406 | GE_ZERO, | |
| 3407 | EQ_ONE, | |
| 3408 | }; | |
| 3409 | ||
| 3410 | static 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 | ||
| 3443 | static 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 | ||
| 3481 | static 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 | ||
| 3528 | static 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 | ||
| 3687 | static 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 | ||
| 3952 | static 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 | ||
| 4001 | static 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 | ||
| 4104 | static 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 | ||
| 4143 | static 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 | ||
| 4169 | static 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 | ||
| 4198 | static 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 | ||
| 4215 | static 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 | ||
| 4253 | static 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 | ||
| 4259 | static 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 | ||
| 4299 | static 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 | ||
| 4316 | static 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 | ||
| 4342 | static 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 | ||
| 4353 | static 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 | ||
| 4363 | static 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 | ||
| 4368 | static 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 | ||
| 4375 | static 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 | ||
| 4399 | static 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 | ||
| 4430 | static 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 | ||
| 4436 | static 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 | ||
| 4442 | static 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 | ||
| 4450 | static 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 | ||
| 4457 | static 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 | ||
| 4518 | static 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 | ||
| 4534 | static 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 | ||
| 4571 | static 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 | ||
| 4629 | static 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 | ||
| 4638 | static 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 | ||
| 4669 | static 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 | ||
| 4701 | static 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 | ||
| 4714 | static 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 | ||
| 4741 | static 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 | ||
| 4750 | static 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 | ||
| 4856 | static 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 | ||
| 4875 | static 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 | ||
| 4892 | static 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 | ||
| 4946 | static 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 | ||
| 4978 | static 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 | ||
| 4996 | static 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 | ||
| 5019 | static 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 | ||
| 5483 | static 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 | ||
| 5535 | static 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 | ||
| 5623 | static 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 | ||
| 5642 | static 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 | ||
| 5825 | static 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 | ||
| 5842 | static 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 | ||
| 5848 | static 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 | ||
| 5896 | static 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 | ||
| 5960 | static 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 | ||
| 5972 | static 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 | ||
| 5984 | static 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 | ||
| 6014 | static 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 | ||
| 6021 | static 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 | ||
| 6033 | static 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 | ||
| 6041 | static 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 | ||
| 6069 | static 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 | ||
| 6093 | static 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 | ||
| 6113 | static 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 | ||
| 6133 | static 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 | ||
| 6242 | static 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 | ||
| 6256 | static 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 | ||
| 6283 | static 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 | ||
| 6348 | static 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 | ||
| 6359 | static 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 | ||
| 6371 | static 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 | ||
| 6390 | static 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 | ||
| 6421 | static 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 | ||
| 6488 | static 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 | ||
| 6537 | static 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 | ||
| 6640 | static 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 | ||
| 6646 | static 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 | ||
| 6661 | static 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 | ||
| 6691 | static 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 | ||
| 6713 | static 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 | ||
| 6720 | static 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 | ||
| 6730 | static 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 | ||
| 6780 | static 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 | ||
| 7016 | static 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 | ||
| 7028 | static 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 | ||
| 7033 | static 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 | ||
| 7047 | static 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 | ||
| 7061 | static 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 | ||
| 7069 | static LLVMValueRef ir_render_handle(CodeGen *g, Stage1Air *executable, Stage1AirInstFrameHandle *instruction) { | |
| 7070 | return g->cur_frame_ptr; | |
| 7071 | } | |
| 7072 | ||
| 7073 | static 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 | ||
| 7098 | static 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 | ||
| 7136 | static 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 | ||
| 7154 | static 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 | ||
| 7175 | static 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 | ||
| 7249 | static 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 | ||
| 7288 | static 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 | ||
| 7309 | static 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 | ||
| 7343 | static 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 | ||
| 7362 | static 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 | ||
| 7369 | static 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 | ||
| 7421 | static 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 | ||
| 7443 | static 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 | ||
| 7466 | static 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 | ||
| 7472 | static 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 | ||
| 7517 | static 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 | ||
| 7535 | static 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 | ||
| 7569 | static 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 | ||
| 7593 | static 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 | ||
| 7601 | static 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 | ||
| 7636 | static 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 | ||
| 7676 | static 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 | ||
| 7687 | static 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 | ||
| 7712 | static 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 | ||
| 7721 | static 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 | ||
| 7734 | static 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 | ||
| 7778 | static 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 | ||
| 7869 | static 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 | ||
| 7878 | static 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 | ||
| 7885 | static 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 | ||
| 7905 | static 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 | ||
| 7922 | static 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 | ||
| 7930 | static 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 | ||
| 7941 | static 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 | ||
| 8130 | static 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 | ||
| 8164 | static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ZigValue *struct_const_val, size_t field_index); | |
| 8165 | static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_const_val, size_t index); | |
| 8166 | static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ZigValue *union_const_val); | |
| 8167 | static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ZigValue *err_union_const_val); | |
| 8168 | static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ZigValue *err_union_const_val); | |
| 8169 | static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ZigValue *optional_const_val); | |
| 8170 | ||
| 8171 | static 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 | ||
| 8202 | static 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 | ||
| 8217 | static 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 | ||
| 8236 | static 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 | ||
| 8248 | static 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 | ||
| 8260 | static 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 | ||
| 8272 | static 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 | ||
| 8289 | static 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 | |
| 8428 | static 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 | ||
| 8432 | static 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 | ||
| 8548 | static 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 | ||
| 8553 | static 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 | ||
| 9060 | static 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 | ||
| 9068 | static 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 | ||
| 9086 | static 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 | ||
| 9132 | static 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 | ||
| 9151 | static 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 | ||
| 9173 | static 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 | ||
| 9182 | static 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 | ||
| 9646 | static 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 | ||
| 9696 | struct CIntTypeInfo { | |
| 9697 | CIntType id; | |
| 9698 | const char *name; | |
| 9699 | bool is_signed; | |
| 9700 | }; | |
| 9701 | ||
| 9702 | static 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 | ||
| 9713 | static const bool is_signed_list[] = { false, true, }; | |
| 9714 | ||
| 9715 | struct GlobalLinkageValue { | |
| 9716 | GlobalLinkageId id; | |
| 9717 | const char *name; | |
| 9718 | }; | |
| 9719 | ||
| 9720 | static 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 | ||
| 9737 | static 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 | ||
| 10039 | static 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 | ||
| 10068 | static 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 | ||
| 10077 | static 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 | ||
| 10191 | static const char *bool_to_str(bool b) { | |
| 10192 | return b ? "true" : "false"; | |
| 10193 | } | |
| 10194 | ||
| 10195 | static 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 | ||
| 10205 | static 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" | |
| 10221 | TargetSubsystem 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 | ||
| 10237 | static 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 | ||
| 10243 | static 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 | ||
| 10262 | Buf *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 | ||
| 10414 | static ZigPackage *create_test_runner_pkg(CodeGen *g) { | |
| 10415 | return codegen_create_package(g, buf_ptr(g->zig_lib_dir), "test_runner.zig", ""); | |
| 10416 | } | |
| 10417 | ||
| 10418 | static 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 | ||
| 10485 | static 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 | ||
| 10643 | static 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 | ||
| 10709 | static 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 | ||
| 10724 | static 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 | ||
| 10814 | void 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 | ||
| 10831 | void 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 | ||
| 10838 | void 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 | ||
| 10883 | ZigPackage *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 | ||
| 10899 | void 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 | ||
| 10907 | CodeGen *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 | ||
| 10993 | bool 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 | ||
| 10999 | bool 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 | ||
| 11009 | void 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 | ||
| 11016 | ZigValue *CodeGen::Intern::for_undefined() { | |
| 11017 | return &this->x_undefined; | |
| 11018 | } | |
| 11019 | ||
| 11020 | ZigValue *CodeGen::Intern::for_void() { | |
| 11021 | return &this->x_void; | |
| 11022 | } | |
| 11023 | ||
| 11024 | ZigValue *CodeGen::Intern::for_null() { | |
| 11025 | return &this->x_null; | |
| 11026 | } | |
| 11027 | ||
| 11028 | ZigValue *CodeGen::Intern::for_unreachable() { | |
| 11029 | return &this->x_unreachable; | |
| 11030 | } | |
| 11031 | ||
| 11032 | ZigValue *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 | ||
| 18 | CodeGen *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 | ||
| 21 | void codegen_build_object(CodeGen *g); | |
| 22 | void codegen_destroy(CodeGen *); | |
| 23 | ||
| 24 | void codegen_add_time_event(CodeGen *g, const char *name); | |
| 25 | void codegen_print_timing_report(CodeGen *g, FILE *f); | |
| 26 | ||
| 27 | ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path, | |
| 28 | const char *pkg_path); | |
| 29 | ||
| 30 | TargetSubsystem detect_subsystem(CodeGen *g); | |
| 31 | ||
| 32 | bool codegen_fn_has_err_ret_tracing_arg(CodeGen *g, ZigType *return_type); | |
| 33 | bool codegen_fn_has_err_ret_tracing_stack(CodeGen *g, ZigFn *fn, bool is_async); | |
| 34 | ||
| 35 | ATTRIBUTE_NORETURN | |
| 36 | void codegen_report_errors_and_exit(CodeGen *g); | |
| 37 | ||
| 38 | void 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 deletedsrc/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 | ||
| 13 | enum ErrType { | |
| 14 | ErrTypeError, | |
| 15 | ErrTypeNote, | |
| 16 | }; | |
| 17 | ||
| 18 | static 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 | ||
| 91 | void print_err_msg(ErrorMsg *err, ErrColor color) { | |
| 92 | print_err_msg_type(err, color, ErrTypeError); | |
| 93 | } | |
| 94 | ||
| 95 | void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note) { | |
| 96 | parent->notes.append(note); | |
| 97 | } | |
| 98 | ||
| 99 | ErrorMsg *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 | ||
| 15 | struct 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 | ||
| 25 | void print_err_msg(ErrorMsg *msg, ErrColor color); | |
| 26 | ||
| 27 | void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note); | |
| 28 | ErrorMsg *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 | ||
| 10 | const 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 | ||
| 13 | const 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 | ||
| 15 | template<typename K> | |
| 16 | struct MakePointer { | |
| 17 | typedef K const *Type; | |
| 18 | static Type convert(K const &val) { | |
| 19 | return &val; | |
| 20 | } | |
| 21 | }; | |
| 22 | ||
| 23 | template<typename K> | |
| 24 | struct MakePointer<K*> { | |
| 25 | typedef K *Type; | |
| 26 | static Type convert(K * const &val) { | |
| 27 | return val; | |
| 28 | } | |
| 29 | }; | |
| 30 | ||
| 31 | template<typename K> | |
| 32 | struct MakePointer<K const *> { | |
| 33 | typedef K const *Type; | |
| 34 | static Type convert(K const * const &val) { | |
| 35 | return val; | |
| 36 | } | |
| 37 | }; | |
| 38 | ||
| 39 | template<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)> | |
| 42 | class HashMap { | |
| 43 | public: | |
| 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 | ||
| 205 | private: | |
| 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 | ||
| 13 | namespace heap { | |
| 14 | ||
| 15 | extern 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 | ||
| 23 | void BootstrapAllocator::init(const char *name) {} | |
| 24 | void BootstrapAllocator::deinit() {} | |
| 25 | ||
| 26 | void *BootstrapAllocator::internal_allocate(const mem::TypeInfo &info, size_t count) { | |
| 27 | return mem::os::calloc(count, info.size); | |
| 28 | } | |
| 29 | ||
| 30 | void *BootstrapAllocator::internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) { | |
| 31 | return mem::os::malloc(count * info.size); | |
| 32 | } | |
| 33 | ||
| 34 | void *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 | ||
| 41 | void *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 | ||
| 45 | void BootstrapAllocator::internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) { | |
| 46 | mem::os::free(ptr); | |
| 47 | } | |
| 48 | ||
| 49 | void CAllocator::init(const char *name) { } | |
| 50 | ||
| 51 | void CAllocator::deinit() { } | |
| 52 | ||
| 53 | CAllocator *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 | ||
| 59 | void CAllocator::destruct(mem::Allocator *allocator) { | |
| 60 | this->deinit(); | |
| 61 | allocator->destroy(this); | |
| 62 | } | |
| 63 | ||
| 64 | void *CAllocator::internal_allocate(const mem::TypeInfo &info, size_t count) { | |
| 65 | return mem::os::calloc(count, info.size); | |
| 66 | } | |
| 67 | ||
| 68 | void *CAllocator::internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) { | |
| 69 | return mem::os::malloc(count * info.size); | |
| 70 | } | |
| 71 | ||
| 72 | void *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 | ||
| 79 | void *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 | ||
| 83 | void CAllocator::internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) { | |
| 84 | mem::os::free(ptr); | |
| 85 | } | |
| 86 | ||
| 87 | struct 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 | ||
| 144 | void *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 | ||
| 164 | void *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 | ||
| 189 | void ArenaAllocator::Impl::new_segment() { | |
| 190 | this->segment = this->backing->create<Segment>(); | |
| 191 | this->segment_offset = 0; | |
| 192 | this->track_segment(); | |
| 193 | } | |
| 194 | ||
| 195 | void 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 | ||
| 207 | void 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 | ||
| 218 | void 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 | ||
| 227 | void 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 | ||
| 277 | ArenaAllocator *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 | ||
| 283 | void ArenaAllocator::destruct(mem::Allocator *allocator) { | |
| 284 | this->deinit(); | |
| 285 | allocator->destroy(this); | |
| 286 | } | |
| 287 | ||
| 288 | void *ArenaAllocator::internal_allocate(const mem::TypeInfo &info, size_t count) { | |
| 289 | return this->impl->allocate(info, count); | |
| 290 | } | |
| 291 | ||
| 292 | void *ArenaAllocator::internal_allocate_nonzero(const mem::TypeInfo &info, size_t count) { | |
| 293 | return this->impl->allocate(info, count); | |
| 294 | } | |
| 295 | ||
| 296 | void *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 | ||
| 300 | void *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 | ||
| 304 | void ArenaAllocator::internal_deallocate(const mem::TypeInfo &info, void *ptr, size_t count) { | |
| 305 | // noop | |
| 306 | } | |
| 307 | ||
| 308 | BootstrapAllocator bootstrap_allocator_state; | |
| 309 | mem::Allocator &bootstrap_allocator = bootstrap_allocator_state; | |
| 310 | ||
| 311 | CAllocator c_allocator_state; | |
| 312 | mem::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 | ||
| 14 | namespace heap { | |
| 15 | ||
| 16 | struct BootstrapAllocator final : mem::Allocator { | |
| 17 | void init(const char *name); | |
| 18 | void deinit(); | |
| 19 | void destruct(Allocator *allocator) {} | |
| 20 | ||
| 21 | private: | |
| 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 | ||
| 29 | struct 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 | ||
| 37 | private: | |
| 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 | // | |
| 54 | struct 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 | ||
| 62 | private: | |
| 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 | ||
| 73 | extern BootstrapAllocator bootstrap_allocator_state; | |
| 74 | extern mem::Allocator &bootstrap_allocator; | |
| 75 | ||
| 76 | extern CAllocator c_allocator_state; | |
| 77 | extern 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 | ||
| 25 | struct 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 | ||
| 34 | struct 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 | ||
| 59 | enum 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 | ||
| 93 | struct ConstCastOnly; | |
| 94 | struct ConstCastArg { | |
| 95 | size_t arg_index; | |
| 96 | ZigType *actual_param_type; | |
| 97 | ZigType *expected_param_type; | |
| 98 | ConstCastOnly *child; | |
| 99 | }; | |
| 100 | ||
| 101 | struct ConstCastArgNoAlias { | |
| 102 | size_t arg_index; | |
| 103 | }; | |
| 104 | ||
| 105 | struct ConstCastOptionalMismatch; | |
| 106 | struct ConstCastPointerMismatch; | |
| 107 | struct ConstCastSliceMismatch; | |
| 108 | struct ConstCastErrUnionErrSetMismatch; | |
| 109 | struct ConstCastErrUnionPayloadMismatch; | |
| 110 | struct ConstCastErrSetMismatch; | |
| 111 | struct ConstCastTypeMismatch; | |
| 112 | struct ConstCastArrayMismatch; | |
| 113 | struct ConstCastBadAllowsZero; | |
| 114 | struct ConstCastBadNullTermArrays; | |
| 115 | struct ConstCastBadCV; | |
| 116 | struct ConstCastPtrSentinel; | |
| 117 | struct ConstCastIntShorten; | |
| 118 | ||
| 119 | struct 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 | ||
| 142 | struct ConstCastTypeMismatch { | |
| 143 | ZigType *wanted_type; | |
| 144 | ZigType *actual_type; | |
| 145 | }; | |
| 146 | ||
| 147 | struct ConstCastOptionalMismatch { | |
| 148 | ConstCastOnly child; | |
| 149 | ZigType *wanted_child; | |
| 150 | ZigType *actual_child; | |
| 151 | }; | |
| 152 | ||
| 153 | struct ConstCastPointerMismatch { | |
| 154 | ConstCastOnly child; | |
| 155 | ZigType *wanted_child; | |
| 156 | ZigType *actual_child; | |
| 157 | }; | |
| 158 | ||
| 159 | struct ConstCastSliceMismatch { | |
| 160 | ConstCastOnly child; | |
| 161 | ZigType *wanted_child; | |
| 162 | ZigType *actual_child; | |
| 163 | }; | |
| 164 | ||
| 165 | struct ConstCastArrayMismatch { | |
| 166 | ConstCastOnly child; | |
| 167 | ZigType *wanted_child; | |
| 168 | ZigType *actual_child; | |
| 169 | }; | |
| 170 | ||
| 171 | struct ConstCastErrUnionErrSetMismatch { | |
| 172 | ConstCastOnly child; | |
| 173 | ZigType *wanted_err_set; | |
| 174 | ZigType *actual_err_set; | |
| 175 | }; | |
| 176 | ||
| 177 | struct ConstCastErrUnionPayloadMismatch { | |
| 178 | ConstCastOnly child; | |
| 179 | ZigType *wanted_payload; | |
| 180 | ZigType *actual_payload; | |
| 181 | }; | |
| 182 | ||
| 183 | struct ConstCastErrSetMismatch { | |
| 184 | ZigList<ErrorTableEntry *> missing_errors; | |
| 185 | }; | |
| 186 | ||
| 187 | struct ConstCastBadAllowsZero { | |
| 188 | ZigType *wanted_type; | |
| 189 | ZigType *actual_type; | |
| 190 | }; | |
| 191 | ||
| 192 | struct ConstCastBadNullTermArrays { | |
| 193 | ConstCastOnly child; | |
| 194 | ZigType *wanted_type; | |
| 195 | ZigType *actual_type; | |
| 196 | }; | |
| 197 | ||
| 198 | struct ConstCastBadCV { | |
| 199 | ZigType *wanted_type; | |
| 200 | ZigType *actual_type; | |
| 201 | }; | |
| 202 | ||
| 203 | struct ConstCastPtrSentinel { | |
| 204 | ZigType *wanted_type; | |
| 205 | ZigType *actual_type; | |
| 206 | }; | |
| 207 | ||
| 208 | struct ConstCastIntShorten { | |
| 209 | ZigType *wanted_type; | |
| 210 | ZigType *actual_type; | |
| 211 | }; | |
| 212 | ||
| 213 | // for debugging purposes | |
| 214 | struct DbgIrBreakPoint { | |
| 215 | const char *src_file; | |
| 216 | uint32_t line; | |
| 217 | }; | |
| 218 | ||
| 219 | static Stage1AirInst *ir_implicit_cast(IrAnalyze *ira, Stage1AirInst *value, ZigType *expected_type); | |
| 220 | static Stage1AirInst *ir_implicit_cast2(IrAnalyze *ira, Scope *scope, AstNode *source_node, | |
| 221 | Stage1AirInst *value, ZigType *expected_type); | |
| 222 | static Stage1AirInst *ir_get_deref(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *ptr, | |
| 223 | ResultLoc *result_loc); | |
| 224 | static 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); | |
| 227 | static Stage1AirInst *ir_get_var_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigVar *var); | |
| 228 | static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, Stage1AirInst *op); | |
| 229 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); | |
| 230 | static ZigType *adjust_ptr_const(CodeGen *g, ZigType *ptr_type, bool is_const); | |
| 231 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); | |
| 232 | static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, uint8_t *buf, ZigValue *val); | |
| 233 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ZigValue *val); | |
| 234 | static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, | |
| 235 | ZigValue *out_val, ZigValue *ptr_val); | |
| 236 | static 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); | |
| 239 | static ZigValue *ir_resolve_const(IrAnalyze *ira, Stage1AirInst *value, UndefAllowed undef_allowed); | |
| 240 | static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align); | |
| 241 | static Stage1AirInst *ir_analyze_int_to_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *target, | |
| 242 | ZigType *ptr_type); | |
| 243 | static Stage1AirInst *ir_analyze_bit_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value, | |
| 244 | ZigType *dest_type); | |
| 245 | static 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); | |
| 247 | static 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); | |
| 249 | static Stage1AirInst *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, Scope *scope, AstNode *source_node, | |
| 250 | Stage1AirInst *base_ptr, bool safety_check_on, bool initializing); | |
| 251 | static Stage1AirInst *ir_analyze_unwrap_error_payload(IrAnalyze *ira, Scope *scope, AstNode *source_node, | |
| 252 | Stage1AirInst *base_ptr, bool safety_check_on, bool initializing); | |
| 253 | static Stage1AirInst *ir_analyze_unwrap_err_code(IrAnalyze *ira, Scope *scope, AstNode *source_node, | |
| 254 | Stage1AirInst *base_ptr, bool initializing); | |
| 255 | static Stage1AirInst *ir_analyze_store_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, | |
| 256 | Stage1AirInst *ptr, Stage1AirInst *uncasted_value, bool allow_write_through_const); | |
| 257 | static void ir_reset_result(ResultLoc *result_loc); | |
| 258 | static Stage1AirInst *ir_analyze_struct_field_ptr(IrAnalyze *ira, Scope *scope, AstNode *source_node, | |
| 259 | TypeStructField *field, Stage1AirInst *struct_ptr, ZigType *struct_type, bool initializing); | |
| 260 | static Stage1AirInst *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_name, | |
| 261 | Scope *scope, AstNode *source_node, Stage1AirInst *container_ptr, ZigType *container_type); | |
| 262 | static Stage1AirInst *ir_analyze_test_non_null(IrAnalyze *ira, Scope *scope, AstNode *source_node, Stage1AirInst *value); | |
| 263 | static Stage1AirInst *ir_error_dependency_loop(IrAnalyze *ira, AstNode *source_node); | |
| 264 | static Stage1AirInst *ir_const_undef(IrAnalyze *ira, Scope *scope, AstNode *source_node, ZigType *ty); | |
| 265 | static 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); | |
| 268 | static Stage1AirInst *ir_analyze_struct_value_field_value(IrAnalyze *ira, Scope *scope, AstNode *source_node, | |
| 269 | Stage1AirInst *struct_operand, TypeStructField *field); | |
| 270 | static bool value_cmp_numeric_val_any(ZigValue *left, Cmp predicate, ZigValue *right); | |
| 271 | static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *right); | |
| 272 | static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field); | |
| 273 | static void value_to_bigfloat(BigFloat *out, ZigValue *val); | |
| 274 | ||
| 275 | static Error ir_resolve_lazy_recurse(AstNode *source_node, ZigValue *val); | |
| 276 | static Error ir_resolve_lazy_recurse_array(AstNode *source_node, ZigValue *val, size_t len); | |
| 277 | ||
| 278 | ||
| 279 | static 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 | ||
| 286 | void 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 | ||
| 476 | static void ira_ref(IrAnalyze *ira) { | |
| 477 | ira->ref_count += 1; | |
| 478 | } | |
| 479 | static 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 | ||
| 515 | static 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 | ||
| 594 | static 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 | ||
| 614 | static bool is_tuple(ZigType *type) { | |
| 615 | return type->id == ZigTypeIdStruct && type->data.structure.special == StructSpecialInferredTuple; | |
| 616 | } | |
| 617 | ||
| 618 | static 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. | |
| 624 | static 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 | ||
| 682 | static 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 | ||
| 688 | static 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 | ||
| 694 | static bool value_is_comptime(ZigValue *const_val) { | |
| 695 | return const_val->special != ConstValSpecialRuntime; | |
| 696 | } | |
| 697 | ||
| 698 | static bool instr_is_comptime(Stage1AirInst *instruction) { | |
| 699 | return value_is_comptime(instruction->value); | |
| 700 | } | |
| 701 | ||
| 702 | static void ir_ref_inst_gen(Stage1AirInst *instruction) { | |
| 703 | assert(instruction->id != Stage1AirInstIdInvalid); | |
| 704 | instruction->ref_count += 1; | |
| 705 | } | |
| 706 | ||
| 707 | static 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 | ||
| 724 | ZigType *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 | ||
| 746 | static 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 | ||
| 754 | static 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 | ||
| 760 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstDeclVar *) { | |
| 761 | return Stage1AirInstIdDeclVar; | |
| 762 | } | |
| 763 | ||
| 764 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBr *) { | |
| 765 | return Stage1AirInstIdBr; | |
| 766 | } | |
| 767 | ||
| 768 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstCondBr *) { | |
| 769 | return Stage1AirInstIdCondBr; | |
| 770 | } | |
| 771 | ||
| 772 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSwitchBr *) { | |
| 773 | return Stage1AirInstIdSwitchBr; | |
| 774 | } | |
| 775 | ||
| 776 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPhi *) { | |
| 777 | return Stage1AirInstIdPhi; | |
| 778 | } | |
| 779 | ||
| 780 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBinaryNot *) { | |
| 781 | return Stage1AirInstIdBinaryNot; | |
| 782 | } | |
| 783 | ||
| 784 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstNegation *) { | |
| 785 | return Stage1AirInstIdNegation; | |
| 786 | } | |
| 787 | ||
| 788 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBinOp *) { | |
| 789 | return Stage1AirInstIdBinOp; | |
| 790 | } | |
| 791 | ||
| 792 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstLoadPtr *) { | |
| 793 | return Stage1AirInstIdLoadPtr; | |
| 794 | } | |
| 795 | ||
| 796 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstStorePtr *) { | |
| 797 | return Stage1AirInstIdStorePtr; | |
| 798 | } | |
| 799 | ||
| 800 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstVectorStoreElem *) { | |
| 801 | return Stage1AirInstIdVectorStoreElem; | |
| 802 | } | |
| 803 | ||
| 804 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstStructFieldPtr *) { | |
| 805 | return Stage1AirInstIdStructFieldPtr; | |
| 806 | } | |
| 807 | ||
| 808 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstUnionFieldPtr *) { | |
| 809 | return Stage1AirInstIdUnionFieldPtr; | |
| 810 | } | |
| 811 | ||
| 812 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstElemPtr *) { | |
| 813 | return Stage1AirInstIdElemPtr; | |
| 814 | } | |
| 815 | ||
| 816 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstVarPtr *) { | |
| 817 | return Stage1AirInstIdVarPtr; | |
| 818 | } | |
| 819 | ||
| 820 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstReturnPtr *) { | |
| 821 | return Stage1AirInstIdReturnPtr; | |
| 822 | } | |
| 823 | ||
| 824 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstCall *) { | |
| 825 | return Stage1AirInstIdCall; | |
| 826 | } | |
| 827 | ||
| 828 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstReturn *) { | |
| 829 | return Stage1AirInstIdReturn; | |
| 830 | } | |
| 831 | ||
| 832 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstCast *) { | |
| 833 | return Stage1AirInstIdCast; | |
| 834 | } | |
| 835 | ||
| 836 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstUnreachable *) { | |
| 837 | return Stage1AirInstIdUnreachable; | |
| 838 | } | |
| 839 | ||
| 840 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAsm *) { | |
| 841 | return Stage1AirInstIdAsm; | |
| 842 | } | |
| 843 | ||
| 844 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstTestNonNull *) { | |
| 845 | return Stage1AirInstIdTestNonNull; | |
| 846 | } | |
| 847 | ||
| 848 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstOptionalUnwrapPtr *) { | |
| 849 | return Stage1AirInstIdOptionalUnwrapPtr; | |
| 850 | } | |
| 851 | ||
| 852 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstOptionalWrap *) { | |
| 853 | return Stage1AirInstIdOptionalWrap; | |
| 854 | } | |
| 855 | ||
| 856 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstUnionTag *) { | |
| 857 | return Stage1AirInstIdUnionTag; | |
| 858 | } | |
| 859 | ||
| 860 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstClz *) { | |
| 861 | return Stage1AirInstIdClz; | |
| 862 | } | |
| 863 | ||
| 864 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstCtz *) { | |
| 865 | return Stage1AirInstIdCtz; | |
| 866 | } | |
| 867 | ||
| 868 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPopCount *) { | |
| 869 | return Stage1AirInstIdPopCount; | |
| 870 | } | |
| 871 | ||
| 872 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBswap *) { | |
| 873 | return Stage1AirInstIdBswap; | |
| 874 | } | |
| 875 | ||
| 876 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBitReverse *) { | |
| 877 | return Stage1AirInstIdBitReverse; | |
| 878 | } | |
| 879 | ||
| 880 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstRef *) { | |
| 881 | return Stage1AirInstIdRef; | |
| 882 | } | |
| 883 | ||
| 884 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstErrName *) { | |
| 885 | return Stage1AirInstIdErrName; | |
| 886 | } | |
| 887 | ||
| 888 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstCmpxchg *) { | |
| 889 | return Stage1AirInstIdCmpxchg; | |
| 890 | } | |
| 891 | ||
| 892 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFence *) { | |
| 893 | return Stage1AirInstIdFence; | |
| 894 | } | |
| 895 | ||
| 896 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstReduce *) { | |
| 897 | return Stage1AirInstIdReduce; | |
| 898 | } | |
| 899 | ||
| 900 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstTruncate *) { | |
| 901 | return Stage1AirInstIdTruncate; | |
| 902 | } | |
| 903 | ||
| 904 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstShuffleVector *) { | |
| 905 | return Stage1AirInstIdShuffleVector; | |
| 906 | } | |
| 907 | ||
| 908 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSelect *) { | |
| 909 | return Stage1AirInstIdSelect; | |
| 910 | } | |
| 911 | ||
| 912 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSplat *) { | |
| 913 | return Stage1AirInstIdSplat; | |
| 914 | } | |
| 915 | ||
| 916 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBoolNot *) { | |
| 917 | return Stage1AirInstIdBoolNot; | |
| 918 | } | |
| 919 | ||
| 920 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstMemset *) { | |
| 921 | return Stage1AirInstIdMemset; | |
| 922 | } | |
| 923 | ||
| 924 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstMemcpy *) { | |
| 925 | return Stage1AirInstIdMemcpy; | |
| 926 | } | |
| 927 | ||
| 928 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSlice *) { | |
| 929 | return Stage1AirInstIdSlice; | |
| 930 | } | |
| 931 | ||
| 932 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBreakpoint *) { | |
| 933 | return Stage1AirInstIdBreakpoint; | |
| 934 | } | |
| 935 | ||
| 936 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstReturnAddress *) { | |
| 937 | return Stage1AirInstIdReturnAddress; | |
| 938 | } | |
| 939 | ||
| 940 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFrameAddress *) { | |
| 941 | return Stage1AirInstIdFrameAddress; | |
| 942 | } | |
| 943 | ||
| 944 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFrameHandle *) { | |
| 945 | return Stage1AirInstIdFrameHandle; | |
| 946 | } | |
| 947 | ||
| 948 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFrameSize *) { | |
| 949 | return Stage1AirInstIdFrameSize; | |
| 950 | } | |
| 951 | ||
| 952 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstOverflowOp *) { | |
| 953 | return Stage1AirInstIdOverflowOp; | |
| 954 | } | |
| 955 | ||
| 956 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstTestErr *) { | |
| 957 | return Stage1AirInstIdTestErr; | |
| 958 | } | |
| 959 | ||
| 960 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstMulAdd *) { | |
| 961 | return Stage1AirInstIdMulAdd; | |
| 962 | } | |
| 963 | ||
| 964 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFloatOp *) { | |
| 965 | return Stage1AirInstIdFloatOp; | |
| 966 | } | |
| 967 | ||
| 968 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstUnwrapErrCode *) { | |
| 969 | return Stage1AirInstIdUnwrapErrCode; | |
| 970 | } | |
| 971 | ||
| 972 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstUnwrapErrPayload *) { | |
| 973 | return Stage1AirInstIdUnwrapErrPayload; | |
| 974 | } | |
| 975 | ||
| 976 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstErrWrapCode *) { | |
| 977 | return Stage1AirInstIdErrWrapCode; | |
| 978 | } | |
| 979 | ||
| 980 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstErrWrapPayload *) { | |
| 981 | return Stage1AirInstIdErrWrapPayload; | |
| 982 | } | |
| 983 | ||
| 984 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPtrCast *) { | |
| 985 | return Stage1AirInstIdPtrCast; | |
| 986 | } | |
| 987 | ||
| 988 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstBitCast *) { | |
| 989 | return Stage1AirInstIdBitCast; | |
| 990 | } | |
| 991 | ||
| 992 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstWidenOrShorten *) { | |
| 993 | return Stage1AirInstIdWidenOrShorten; | |
| 994 | } | |
| 995 | ||
| 996 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstIntToPtr *) { | |
| 997 | return Stage1AirInstIdIntToPtr; | |
| 998 | } | |
| 999 | ||
| 1000 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPtrToInt *) { | |
| 1001 | return Stage1AirInstIdPtrToInt; | |
| 1002 | } | |
| 1003 | ||
| 1004 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstIntToEnum *) { | |
| 1005 | return Stage1AirInstIdIntToEnum; | |
| 1006 | } | |
| 1007 | ||
| 1008 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstIntToErr *) { | |
| 1009 | return Stage1AirInstIdIntToErr; | |
| 1010 | } | |
| 1011 | ||
| 1012 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstErrToInt *) { | |
| 1013 | return Stage1AirInstIdErrToInt; | |
| 1014 | } | |
| 1015 | ||
| 1016 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPanic *) { | |
| 1017 | return Stage1AirInstIdPanic; | |
| 1018 | } | |
| 1019 | ||
| 1020 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstTagName *) { | |
| 1021 | return Stage1AirInstIdTagName; | |
| 1022 | } | |
| 1023 | ||
| 1024 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstFieldParentPtr *) { | |
| 1025 | return Stage1AirInstIdFieldParentPtr; | |
| 1026 | } | |
| 1027 | ||
| 1028 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAlignCast *) { | |
| 1029 | return Stage1AirInstIdAlignCast; | |
| 1030 | } | |
| 1031 | ||
| 1032 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstErrorReturnTrace *) { | |
| 1033 | return Stage1AirInstIdErrorReturnTrace; | |
| 1034 | } | |
| 1035 | ||
| 1036 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAtomicRmw *) { | |
| 1037 | return Stage1AirInstIdAtomicRmw; | |
| 1038 | } | |
| 1039 | ||
| 1040 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAtomicLoad *) { | |
| 1041 | return Stage1AirInstIdAtomicLoad; | |
| 1042 | } | |
| 1043 | ||
| 1044 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAtomicStore *) { | |
| 1045 | return Stage1AirInstIdAtomicStore; | |
| 1046 | } | |
| 1047 | ||
| 1048 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSaveErrRetAddr *) { | |
| 1049 | return Stage1AirInstIdSaveErrRetAddr; | |
| 1050 | } | |
| 1051 | ||
| 1052 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstVectorToArray *) { | |
| 1053 | return Stage1AirInstIdVectorToArray; | |
| 1054 | } | |
| 1055 | ||
| 1056 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstArrayToVector *) { | |
| 1057 | return Stage1AirInstIdArrayToVector; | |
| 1058 | } | |
| 1059 | ||
| 1060 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAssertZero *) { | |
| 1061 | return Stage1AirInstIdAssertZero; | |
| 1062 | } | |
| 1063 | ||
| 1064 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAssertNonNull *) { | |
| 1065 | return Stage1AirInstIdAssertNonNull; | |
| 1066 | } | |
| 1067 | ||
| 1068 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPtrOfArrayToSlice *) { | |
| 1069 | return Stage1AirInstIdPtrOfArrayToSlice; | |
| 1070 | } | |
| 1071 | ||
| 1072 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSuspendBegin *) { | |
| 1073 | return Stage1AirInstIdSuspendBegin; | |
| 1074 | } | |
| 1075 | ||
| 1076 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSuspendFinish *) { | |
| 1077 | return Stage1AirInstIdSuspendFinish; | |
| 1078 | } | |
| 1079 | ||
| 1080 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAwait *) { | |
| 1081 | return Stage1AirInstIdAwait; | |
| 1082 | } | |
| 1083 | ||
| 1084 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstResume *) { | |
| 1085 | return Stage1AirInstIdResume; | |
| 1086 | } | |
| 1087 | ||
| 1088 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSpillBegin *) { | |
| 1089 | return Stage1AirInstIdSpillBegin; | |
| 1090 | } | |
| 1091 | ||
| 1092 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstSpillEnd *) { | |
| 1093 | return Stage1AirInstIdSpillEnd; | |
| 1094 | } | |
| 1095 | ||
| 1096 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstVectorExtractElem *) { | |
| 1097 | return Stage1AirInstIdVectorExtractElem; | |
| 1098 | } | |
| 1099 | ||
| 1100 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstAlloca *) { | |
| 1101 | return Stage1AirInstIdAlloca; | |
| 1102 | } | |
| 1103 | ||
| 1104 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstConst *) { | |
| 1105 | return Stage1AirInstIdConst; | |
| 1106 | } | |
| 1107 | ||
| 1108 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstWasmMemorySize *) { | |
| 1109 | return Stage1AirInstIdWasmMemorySize; | |
| 1110 | } | |
| 1111 | ||
| 1112 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstWasmMemoryGrow *) { | |
| 1113 | return Stage1AirInstIdWasmMemoryGrow; | |
| 1114 | } | |
| 1115 | ||
| 1116 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstExtern *) { | |
| 1117 | return Stage1AirInstIdExtern; | |
| 1118 | } | |
| 1119 | ||
| 1120 | static constexpr Stage1AirInstId ir_inst_id(Stage1AirInstPrefetch *) { | |
| 1121 | return Stage1AirInstIdPrefetch; | |
| 1122 | } | |
| 1123 | ||
| 1124 | template<typename T> | |
| 1125 | static 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 | ||
| 1135 | template<typename T> | |
| 1136 | static 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 | ||
| 1145 | template<typename T> | |
| 1146 | static 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 | ||
| 1152 | template<typename T> | |
| 1153 | static 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 | ||
| 1160 | template<typename T> | |
| 1161 | static 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 | ||
| 1168 | Stage1AirInst *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 | ||
| 1183 | static 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 | ||
| 1196 | static 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 | ||
| 1209 | static 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 | ||
| 1218 | static 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 | ||
| 1236 | static 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 | ||
| 1245 | static 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 | ||
| 1251 | static 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 | ||
| 1266 | static 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 | ||
| 1279 | static 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 | ||
| 1295 | static 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 | ||
| 1321 | static 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 | ||
| 1366 | static 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 | ||
| 1373 | static 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 | ||
| 1385 | static 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 | ||
| 1398 | static 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 | ||
| 1403 | static 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 | ||
| 1415 | static 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 | ||
| 1431 | static 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 | ||
| 1446 | static 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 | ||
| 1459 | static 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 | ||
| 1474 | static 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 | ||
| 1504 | static 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 | ||
| 1515 | static 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 | ||
| 1530 | static 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 | ||
| 1545 | static 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 | ||
| 1560 | static 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 | ||
| 1575 | static 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 | ||
| 1586 | static 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 | ||
| 1597 | static 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 | ||
| 1610 | static 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 | ||
| 1623 | static 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 | ||
| 1636 | static 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 | ||
| 1655 | static 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 | ||
| 1668 | static 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 | ||
| 1683 | static 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 | ||
| 1696 | static 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 | ||
| 1719 | static 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 | ||
| 1727 | static 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 | ||
| 1739 | static 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 | ||
| 1744 | static 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 | ||
| 1750 | static 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 | ||
| 1755 | static 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 | ||
| 1761 | static 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 | ||
| 1767 | static 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 | ||
| 1780 | static 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 | ||
| 1796 | static 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 | ||
| 1812 | static 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 | ||
| 1825 | static 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 | ||
| 1836 | static 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 | ||
| 1852 | static 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 | ||
| 1868 | static 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 | ||
| 1890 | static 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 | ||
| 1896 | static 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 | ||
| 1902 | static 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 | ||
| 1908 | static 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 | ||
| 1914 | static 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 | ||
| 1925 | static 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 | ||
| 1945 | static 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 | ||
| 1959 | static 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 | ||
| 1976 | static 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 | ||
| 1987 | static 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 | ||
| 1999 | static 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 | ||
| 2013 | static 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 | ||
| 2027 | static 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 | ||
| 2040 | static 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 | ||
| 2052 | static 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 | ||
| 2064 | static 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 | ||
| 2074 | static 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 | ||
| 2086 | static 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 | ||
| 2098 | static 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 | ||
| 2110 | static 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 | ||
| 2120 | static 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 | ||
| 2133 | static 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 | ||
| 2147 | static 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 | ||
| 2159 | static 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 | ||
| 2169 | static 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 | ||
| 2185 | static 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 | ||
| 2199 | static 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 | ||
| 2215 | static 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 | ||
| 2230 | static 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 | ||
| 2245 | static 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 | ||
| 2258 | static 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 | ||
| 2271 | static 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 | ||
| 2284 | static 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 | ||
| 2295 | static 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 | ||
| 2305 | static 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 | ||
| 2321 | static 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 | ||
| 2331 | static 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 | ||
| 2344 | static 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 | ||
| 2357 | static 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 | ||
| 2372 | static 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 | ||
| 2383 | static 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 | ||
| 2396 | static 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 | |
| 2490 | static 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 | ||
| 2557 | static 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 | ||
| 2574 | static 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 | ||
| 2589 | static 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 | ||
| 2598 | static 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 | ||
| 2602 | static 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 | ||
| 2609 | static 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. | |
| 2615 | static 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 | ||
| 2631 | ZigValue *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 | ||
| 2658 | static 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 | ||
| 2687 | static 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 | ||
| 2695 | static 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 | ||
| 2702 | static 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 | ||
| 2736 | static 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 | ||
| 2783 | static 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 | ||
| 2839 | static 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 | ||
| 2869 | static 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 | ||
| 2897 | static 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 | ||
| 2932 | static 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 | ||
| 2967 | static 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 | ||
| 3003 | static 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 | ||
| 3034 | static 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 | ||
| 3057 | static 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 | |
| 3118 | static 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 | ||
| 3180 | static 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 | ||
| 3210 | static 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 | ||
| 3240 | static 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 | ||
| 3270 | static 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 | ||
| 3300 | static 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 | ||
| 3333 | static 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) | |
| 3367 | static 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) | |
| 3377 | static 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) | |
| 3385 | static 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 | ||
| 3392 | static 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) | |
| 3423 | static 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) | |
| 3433 | static 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) | |
| 3441 | static 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 | ||
| 3448 | static 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 | ||
| 3478 | static 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 | ||
| 3538 | static 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 | ||
| 3598 | static 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 | ||
| 3627 | void 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 | ||
| 3664 | void 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 | ||
| 3707 | static 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 | ||
| 3743 | static 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 | ||
| 4058 | static 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 | ||
| 4065 | static 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 | ||
| 4074 | static 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 | ||
| 4082 | static 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 | ||
| 4135 | static 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 | ||
| 4539 | static 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 | ||
| 4545 | static 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 | ||
| 5340 | static 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 | ||
| 5448 | static 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 | ||
| 5458 | static 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. | |
| 5467 | static 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 | ||
| 5473 | static 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 | ||
| 5494 | static 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 | ||
| 5533 | static 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 | ||
| 5626 | static 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 | ||
| 5641 | static 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 | ||
| 5654 | static 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 | ||
| 5664 | static 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 | ||
| 5694 | static 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 | ||
| 5717 | static 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 | ||
| 5766 | static 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 | ||
| 5777 | static 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 | ||
| 5785 | static 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 | ||
| 5806 | static 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 | ||
| 5817 | static 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 | ||
| 5823 | static 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 | ||
| 5832 | static 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 | ||
| 5845 | static 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 | ||
| 5851 | static 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 | ||
| 5857 | static 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 | ||
| 5863 | static 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 | ||
| 5869 | static 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 | ||
| 5875 | static 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 | ||
| 5881 | static 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 | ||
| 5895 | static 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 | ||
| 5929 | static 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 | ||
| 5939 | Error 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 | ||
| 6005 | static 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 | ||
| 6023 | static 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 | ||
| 6034 | static 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 | ||
| 6054 | static 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 | ||
| 6062 | static 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 | ||
| 6076 | static 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 | ||
| 6086 | static 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 | ||
| 6107 | static 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 | ||
| 6135 | static 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 | ||
| 6156 | static 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 | ||
| 6200 | static 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 | ||
| 6247 | static 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 | ||
| 6288 | static 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 | ||
| 6305 | static 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 | ||
| 6316 | static 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 | ||
| 6361 | static 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 | ||
| 6381 | static 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 | ||
| 6397 | static 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 | ||
| 6431 | static 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 | ||
| 6437 | static 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 | ||
| 6456 | static 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 | ||
| 6468 | static 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 | ||
| 6515 | static 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 | ||
| 6546 | static 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 | ||
| 6554 | static 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 | ||
| 6650 | static bool value_numeric_fits_in_type(ZigValue *value, ZigType *type_entry); | |
| 6651 | ||
| 6652 | static 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 | ||
| 6724 | static 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 | ||
| 6770 | static 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 | ||
| 6788 | static 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 | ||
| 6850 | static 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 | ||
| 6923 | static 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 | ||
| 6969 | static 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 | ||
| 7163 | static 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 | ||
| 7176 | static 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 | ||
| 7196 | static 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 | ||
| 7229 | static 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 | ||
| 7240 | static 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 | ||
| 7263 | static 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 | ||
| 7349 | static 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 | ||
| 7499 | static 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. | |
| 7574 | static 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 | ||
| 7608 | static 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 | ||
| 7621 | static 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 | ||
| 7630 | static 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 | ||
| 8363 | static 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 | ||
| 8380 | static 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 | ||
| 8384 | static 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 | ||
| 8398 | static 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 | ||
| 8497 | static 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 | ||
| 8520 | static 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 | ||
| 8549 | static 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 | ||
| 8565 | static 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 | ||
| 8569 | static 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 | ||
| 8585 | static 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 | ||
| 8593 | static 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 | ||
| 8611 | static 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 | ||
| 8629 | static 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 | ||
| 8647 | static 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 | ||
| 8665 | static 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 | ||
| 8683 | static 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 | ||
| 8725 | static 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 | ||
| 8739 | static 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 | ||
| 8782 | static 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 | ||
| 8786 | static 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 | ||
| 8833 | static 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 | ||
| 8852 | static 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 | ||
| 8865 | static 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 | ||
| 8881 | static 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 | ||
| 8924 | static 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 | |
| 8969 | static 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 | ||
| 9046 | static 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 | } | |
| 9094 | never_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 | ||
| 9184 | static 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 | ||
| 9496 | static 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 | ||
| 9544 | static 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 | ||
| 9579 | static 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 | ||
| 9624 | static 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 | ||
| 9679 | static 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 | ||
| 9937 | static 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. | |
| 10159 | static 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 | ||
| 10195 | static 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 | ||
| 10289 | static 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 | ||
| 10455 | static 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 | ||
| 10502 | static 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 | ||
| 10521 | static 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. | |
| 10545 | static 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 | ||
| 10568 | static 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 | ||
| 10607 | static bool value_cmp_numeric_val_any(ZigValue *left, Cmp predicate, ZigValue *right) { | |
| 10608 | return value_cmp_numeric_val(left, predicate, right, true); | |
| 10609 | } | |
| 10610 | ||
| 10611 | static bool value_cmp_numeric_val_all(ZigValue *left, Cmp predicate, ZigValue *right) { | |
| 10612 | return value_cmp_numeric_val(left, predicate, right, false); | |
| 10613 | } | |
| 10614 | ||
| 10615 | static 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 | ||
| 10878 | static 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 | ||
| 10974 | static 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 | ||
| 11203 | static 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 | ||
| 11301 | static 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 | } | |
| 11396 | skip_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 | ||
| 11404 | static 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 | ||
| 11443 | static 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 | ||
| 11494 | static 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 | ||
| 11662 | static 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 | ||
| 11938 | static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node); | |
| 11939 | ||
| 11940 | static 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 | ||
| 12058 | static 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 | ||
| 12063 | static 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 | ||
| 12086 | static 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 | ||
| 12106 | static 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 | ||
| 12149 | static 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 | ||
| 12169 | static 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 | ||
| 12190 | static 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 | ||
| 12200 | static 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 | ||
| 12229 | static 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 | ||
| 12248 | static 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 | |
| 12264 | static 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 | ||
| 12605 | static 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 | ||
| 12737 | static 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 | ||
| 12803 | static 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 | ||
| 12838 | static 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 | ||
| 12843 | static 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 | ||
| 12857 | static 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 | } | |
| 12902 | static 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 | ||
| 12935 | static 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 | ||
| 13032 | static 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. | |
| 13087 | static 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 | ||
| 13100 | static 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 | ||
| 13221 | static 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 | ||
| 13255 | static 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 | ||
| 13847 | static 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 | ||
| 13880 | static 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 | ||
| 13982 | static 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 | ||
| 14028 | static 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 | ||
| 14055 | static 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 | ||
| 14069 | static 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 | ||
| 14083 | static 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 | ||
| 14097 | static 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 | |
| 14149 | static 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 | ||
| 14259 | static 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 | ||
| 14275 | static 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 | ||
| 14310 | static 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 | ||
| 14376 | static 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 | ||
| 14423 | static 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 | ||
| 14465 | static 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 | ||
| 14472 | static 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 | ||
| 14478 | static 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 | ||
| 14498 | static 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 | ||
| 14552 | static 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 | ||
| 14566 | static 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 | ||
| 14797 | static 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 | ||
| 14812 | static 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 | ||
| 14826 | static 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 | ||
| 14840 | static 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 | ||
| 14847 | static 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 | ||
| 14861 | static 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 | ||
| 14875 | static 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 | ||
| 14889 | static 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 | ||
| 14927 | static 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 | ||
| 15388 | static 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 | ||
| 15466 | static 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 | ||
| 15479 | static 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 | ||
| 15591 | static 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 | ||
| 15631 | static 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 | ||
| 15762 | static 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 | ||
| 15771 | static 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 | ||
| 15776 | static 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 | ||
| 15820 | static 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 | ||
| 15831 | static 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 | ||
| 16019 | static 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 | ||
| 16031 | static 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 | ||
| 16038 | static 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 | ||
| 16067 | static 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 | ||
| 16096 | static 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 | ||
| 16153 | static 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 | ||
| 16208 | static 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 | ||
| 16220 | static 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 | ||
| 16253 | static 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 | ||
| 16272 | static 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 | ||
| 16353 | static 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 | ||
| 16379 | static 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 | ||
| 16396 | static 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 | ||
| 16432 | static 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 | ||
| 16440 | static 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 | ||
| 16564 | static 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 | ||
| 16575 | static 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 | ||
| 16651 | static 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 | ||
| 16727 | static 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 | ||
| 16812 | static 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 | ||
| 16849 | static 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 | ||
| 16946 | static 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 | ||
| 17076 | static 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 | ||
| 17199 | static 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 | ||
| 17281 | static 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 | ||
| 17317 | static 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 | ||
| 17333 | static 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 | ||
| 17376 | static 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 | ||
| 17526 | static 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 | ||
| 17685 | static 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 | ||
| 17705 | static 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 | ||
| 17716 | static 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 | ||
| 17746 | static 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 | ||
| 17779 | static 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 | ||
| 17845 | static 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 | ||
| 17935 | static 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 | ||
| 17977 | static 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 | ||
| 17992 | static 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 | ||
| 18006 | static 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 | ||
| 18018 | static 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 | ||
| 18051 | static 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 | ||
| 18146 | static 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 | ||
| 18158 | static 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 | ||
| 18171 | static 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 | ||
| 18254 | static 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 | ||
| 18272 | static 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 | ||
| 18913 | static 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 | ||
| 18939 | static 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 | ||
| 18952 | static 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 | ||
| 18974 | static 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 | ||
| 18985 | static 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 | ||
| 18994 | static 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 | ||
| 19003 | static 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 | ||
| 19016 | static 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 | ||
| 19052 | static 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 | ||
| 19718 | static 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 | ||
| 19738 | static 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 | ||
| 19752 | static 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 | ||
| 19766 | static 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 | ||
| 19848 | static 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 | ||
| 19866 | static 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 | ||
| 19897 | static 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 | ||
| 19915 | static 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 | ||
| 19956 | static 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 | ||
| 20093 | static 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 | ||
| 20221 | static 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 | ||
| 20286 | static 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 | ||
| 20304 | static 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 | ||
| 20319 | static 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 | ||
| 20352 | static 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 | ||
| 20366 | static 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 | ||
| 20416 | static 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 | ||
| 20440 | static 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 | ||
| 20465 | static 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 | ||
| 20489 | static 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 | ||
| 20517 | static 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 | ||
| 20534 | static 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 | ||
| 20546 | static 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 | ||
| 20569 | static 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 | ||
| 20583 | static 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 | ||
| 20762 | static 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 | ||
| 20782 | static 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 | ||
| 20876 | static 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 | ||
| 20915 | static 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 | ||
| 20937 | static 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 | ||
| 21056 | static 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 | ||
| 21234 | static 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 | ||
| 21244 | static 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 | } | |
| 21414 | done_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 | ||
| 21811 | static 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 | ||
| 21839 | static 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 | ||
| 21860 | static 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 | ||
| 21889 | static 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 | ||
| 21893 | static 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 | ||
| 21897 | static 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 | ||
| 21901 | static 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 | ||
| 21915 | static 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 | ||
| 21930 | static 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 | ||
| 21946 | static 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 | ||
| 21967 | static 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 | ||
| 22087 | static 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 | ||
| 22116 | static 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 | ||
| 22204 | static 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 | ||
| 22253 | static 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 | ||
| 22327 | static 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 | ||
| 22334 | static 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 | ||
| 22413 | static 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 | ||
| 22424 | static 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 | ||
| 22504 | static 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 | ||
| 22512 | static 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 | ||
| 22816 | static 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 | ||
| 22835 | static 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 | ||
| 22856 | static 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 | ||
| 22950 | static 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 | ||
| 23107 | static 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 | ||
| 23130 | static 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 | ||
| 23144 | static 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 | ||
| 23283 | static 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 | ||
| 23308 | static 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 | ||
| 23481 | static 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 | ||
| 23549 | static 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 | ||
| 23600 | static 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 | ||
| 23630 | static 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 | ||
| 23643 | static 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 | ||
| 23691 | static 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 | ||
| 23709 | static 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 | ||
| 23750 | static 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 | ||
| 23775 | static 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 | ||
| 23793 | static 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 | ||
| 23819 | static 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 | ||
| 23858 | static 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 | ||
| 23909 | static 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 | ||
| 23956 | static 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 | ||
| 24108 | static 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 | ||
| 24143 | static 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 | ||
| 24196 | static 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 | ||
| 24200 | static 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 | ||
| 24537 | static 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 | ||
| 24599 | static 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 | ||
| 24685 | static 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 | ||
| 24740 | static 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 | ||
| 24748 | static 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 | ||
| 24779 | static 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 | ||
| 24801 | static 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 | ||
| 24828 | static 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 | ||
| 24844 | static 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 | ||
| 24854 | static 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 | ||
| 24899 | static 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 | ||
| 24911 | static 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 | ||
| 24931 | static 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 | ||
| 24960 | static 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 | ||
| 24964 | static 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 | ||
| 24981 | static 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 | ||
| 25027 | static 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 | ||
| 25072 | static 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 | ||
| 25097 | static 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 | ||
| 25119 | static 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 | ||
| 25137 | static 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 | ||
| 25191 | static 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 | ||
| 25237 | static 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. | |
| 25532 | ZigType *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 | ||
| 25643 | bool 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 | ||
| 25763 | bool 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 | ||
| 25929 | static 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 | ||
| 26028 | static 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 | ||
| 26502 | static 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 | ||
| 26521 | static 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 | ||
| 26591 | Error 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 | ||
| 26602 | void 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 | ||
| 26611 | void 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 | ||
| 26621 | void 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 | ||
| 13 | Stage1AirInst *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node, ZigFn *fn, | |
| 14 | ZigType *var_type, const char *name_hint); | |
| 15 | ||
| 16 | Error 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 | ||
| 21 | Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ZigValue *val); | |
| 22 | ||
| 23 | ZigType *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 | ||
| 28 | bool ir_inst_gen_has_side_effects(Stage1AirInst *inst); | |
| 29 | ||
| 30 | struct IrAnalyze; | |
| 31 | ZigValue *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 | ||
| 15 | static uint32_t hash_inst_src_ptr(Stage1ZirInst* instruction) { | |
| 16 | return (uint32_t)(uintptr_t)instruction; | |
| 17 | } | |
| 18 | ||
| 19 | static uint32_t hash_inst_gen_ptr(Stage1AirInst* instruction) { | |
| 20 | return (uint32_t)(uintptr_t)instruction; | |
| 21 | } | |
| 22 | ||
| 23 | static bool inst_src_ptr_eql(Stage1ZirInst* a, Stage1ZirInst* b) { | |
| 24 | return a == b; | |
| 25 | } | |
| 26 | ||
| 27 | static bool inst_gen_ptr_eql(Stage1AirInst* a, Stage1AirInst* b) { | |
| 28 | return a == b; | |
| 29 | } | |
| 30 | ||
| 31 | using InstSetSrc = HashMap<Stage1ZirInst*, uint8_t, hash_inst_src_ptr, inst_src_ptr_eql>; | |
| 32 | using InstSetGen = HashMap<Stage1AirInst*, uint8_t, hash_inst_gen_ptr, inst_gen_ptr_eql>; | |
| 33 | using InstListSrc = ZigList<Stage1ZirInst*>; | |
| 34 | using InstListGen = ZigList<Stage1AirInst*>; | |
| 35 | ||
| 36 | struct IrPrintSrc { | |
| 37 | CodeGen *codegen; | |
| 38 | FILE *f; | |
| 39 | int indent; | |
| 40 | int indent_size; | |
| 41 | }; | |
| 42 | ||
| 43 | struct 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 | ||
| 57 | static void ir_print_other_inst_src(IrPrintSrc *irp, Stage1ZirInst *inst); | |
| 58 | static void ir_print_other_inst_gen(IrPrintGen *irp, Stage1AirInst *inst); | |
| 59 | ||
| 60 | static 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 | ||
| 90 | const 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 | ||
| 382 | const 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 | ||
| 572 | static void ir_print_indent_src(IrPrintSrc *irp) { | |
| 573 | for (int i = 0; i < irp->indent; i += 1) { | |
| 574 | fprintf(irp->f, " "); | |
| 575 | } | |
| 576 | } | |
| 577 | ||
| 578 | static void ir_print_indent_gen(IrPrintGen *irp) { | |
| 579 | for (int i = 0; i < irp->indent; i += 1) { | |
| 580 | fprintf(irp->f, " "); | |
| 581 | } | |
| 582 | } | |
| 583 | ||
| 584 | static 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 | ||
| 599 | static 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 | ||
| 609 | static void ir_print_var_src(IrPrintSrc *irp, Stage1ZirInst *inst) { | |
| 610 | fprintf(irp->f, "#%" PRIu32 "", inst->debug_id); | |
| 611 | } | |
| 612 | ||
| 613 | static 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 | ||
| 621 | static 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 | ||
| 629 | static 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 | ||
| 636 | static 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 | ||
| 644 | static 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 | ||
| 652 | static 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 | ||
| 660 | static 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 | ||
| 665 | static 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 | ||
| 670 | static void ir_print_const(IrPrintSrc *irp, Stage1ZirInstConst *const_instruction) { | |
| 671 | ir_print_const_value(irp->codegen, irp->f, const_instruction->value); | |
| 672 | } | |
| 673 | ||
| 674 | static void ir_print_const(IrPrintGen *irp, Stage1AirInstConst *const_instruction) { | |
| 675 | ir_print_const_value(irp->codegen, irp->f, const_instruction->base.value); | |
| 676 | } | |
| 677 | ||
| 678 | static 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 | ||
| 758 | static 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 | ||
| 776 | static 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 | ||
| 781 | static 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 | ||
| 790 | static 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 | ||
| 799 | static 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 | ||
| 808 | static 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 | ||
| 831 | static 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 | ||
| 845 | static 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 | ||
| 850 | static 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 | ||
| 856 | static 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 | ||
| 862 | static 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 | ||
| 868 | static 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 | ||
| 874 | static 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 | ||
| 880 | static 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 | ||
| 907 | static 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 | ||
| 918 | static 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 | ||
| 935 | static 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 | ||
| 951 | static 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 | ||
| 970 | static 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 | ||
| 989 | static 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 | ||
| 1002 | static 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 | ||
| 1011 | static 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 | ||
| 1020 | static 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 | ||
| 1025 | static 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 | ||
| 1039 | static 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 | ||
| 1053 | static 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 | ||
| 1069 | static 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 | ||
| 1081 | static void ir_print_unreachable(IrPrintSrc *irp, Stage1ZirInstUnreachable *instruction) { | |
| 1082 | fprintf(irp->f, "unreachable"); | |
| 1083 | } | |
| 1084 | ||
| 1085 | static void ir_print_unreachable(IrPrintGen *irp, Stage1AirInstUnreachable *instruction) { | |
| 1086 | fprintf(irp->f, "unreachable"); | |
| 1087 | } | |
| 1088 | ||
| 1089 | static 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 | ||
| 1100 | static 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 | ||
| 1111 | static void ir_print_var_ptr(IrPrintSrc *irp, Stage1ZirInstVarPtr *instruction) { | |
| 1112 | fprintf(irp->f, "&%s", instruction->var->name); | |
| 1113 | } | |
| 1114 | ||
| 1115 | static void ir_print_var_ptr(IrPrintGen *irp, Stage1AirInstVarPtr *instruction) { | |
| 1116 | fprintf(irp->f, "&%s", instruction->var->name); | |
| 1117 | } | |
| 1118 | ||
| 1119 | static void ir_print_return_ptr(IrPrintGen *irp, Stage1AirInstReturnPtr *instruction) { | |
| 1120 | fprintf(irp->f, "@ReturnPtr"); | |
| 1121 | } | |
| 1122 | ||
| 1123 | static void ir_print_load_ptr(IrPrintSrc *irp, Stage1ZirInstLoadPtr *instruction) { | |
| 1124 | ir_print_other_inst_src(irp, instruction->ptr); | |
| 1125 | fprintf(irp->f, ".*"); | |
| 1126 | } | |
| 1127 | ||
| 1128 | static 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 | ||
| 1135 | static 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 | ||
| 1142 | static 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 | ||
| 1149 | static 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 | ||
| 1158 | static 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 | ||
| 1170 | static void ir_print_binary_not(IrPrintGen *irp, Stage1AirInstBinaryNot *instruction) { | |
| 1171 | fprintf(irp->f, "~"); | |
| 1172 | ir_print_other_inst_gen(irp, instruction->operand); | |
| 1173 | } | |
| 1174 | ||
| 1175 | static 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 | ||
| 1180 | static 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 | ||
| 1195 | static 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 | ||
| 1202 | static 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 | ||
| 1209 | static 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 | ||
| 1215 | static 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 | ||
| 1221 | static 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 | ||
| 1229 | static 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 | ||
| 1240 | static 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 | ||
| 1246 | static 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 | ||
| 1255 | static 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 | ||
| 1298 | static 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 | ||
| 1340 | static 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 | ||
| 1349 | static 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 | ||
| 1354 | static 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 | ||
| 1359 | static 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 | ||
| 1368 | static 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 | ||
| 1377 | static 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 | ||
| 1385 | static 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 | ||
| 1391 | static 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 | ||
| 1399 | static 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 | ||
| 1405 | static 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 | ||
| 1413 | static 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 | ||
| 1419 | static 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 | ||
| 1427 | static 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 | ||
| 1433 | static 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 | ||
| 1441 | static 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 | ||
| 1447 | static 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 | ||
| 1466 | static 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 | ||
| 1481 | static 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 | ||
| 1490 | static 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 | ||
| 1495 | static 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 | ||
| 1500 | static 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 | ||
| 1505 | static 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 | ||
| 1511 | static void ir_print_ref(IrPrintSrc *irp, Stage1ZirInstRef *instruction) { | |
| 1512 | fprintf(irp->f, "ref "); | |
| 1513 | ir_print_other_inst_src(irp, instruction->value); | |
| 1514 | } | |
| 1515 | ||
| 1516 | static 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 | ||
| 1523 | static 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 | ||
| 1529 | static 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 | ||
| 1540 | static 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 | ||
| 1546 | static 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 | ||
| 1552 | static void ir_print_c_import(IrPrintSrc *irp, Stage1ZirInstCImport *instruction) { | |
| 1553 | fprintf(irp->f, "@cImport(...)"); | |
| 1554 | } | |
| 1555 | ||
| 1556 | static 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 | ||
| 1562 | static 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 | ||
| 1570 | static 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 | ||
| 1576 | static 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 | ||
| 1582 | static 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 | ||
| 1597 | static 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 | ||
| 1608 | static 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 | ||
| 1614 | static 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 | ||
| 1622 | static 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 | ||
| 1634 | static void ir_print_fence(IrPrintGen *irp, Stage1AirInstFence *instruction) { | |
| 1635 | fprintf(irp->f, "fence %s", atomic_order_str(instruction->order)); | |
| 1636 | } | |
| 1637 | ||
| 1638 | static 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 | ||
| 1651 | static 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 | ||
| 1657 | static 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 | ||
| 1665 | static 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 | ||
| 1671 | static 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 | ||
| 1679 | static 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 | ||
| 1687 | static 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 | ||
| 1695 | static 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 | ||
| 1703 | static 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 | ||
| 1711 | static 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 | ||
| 1717 | static 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 | ||
| 1725 | static 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 | ||
| 1737 | static 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 | ||
| 1747 | static 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 | ||
| 1759 | static 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 | ||
| 1769 | static 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 | ||
| 1777 | static 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 | ||
| 1783 | static void ir_print_bool_not(IrPrintSrc *irp, Stage1ZirInstBoolNot *instruction) { | |
| 1784 | fprintf(irp->f, "! "); | |
| 1785 | ir_print_other_inst_src(irp, instruction->value); | |
| 1786 | } | |
| 1787 | ||
| 1788 | static void ir_print_bool_not(IrPrintGen *irp, Stage1AirInstBoolNot *instruction) { | |
| 1789 | fprintf(irp->f, "! "); | |
| 1790 | ir_print_other_inst_gen(irp, instruction->value); | |
| 1791 | } | |
| 1792 | ||
| 1793 | static 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 | ||
| 1799 | static 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 | ||
| 1805 | static 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 | ||
| 1813 | static 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 | ||
| 1821 | static void ir_print_builtin_src(IrPrintSrc *irp, Stage1ZirInstSrc *instruction) { | |
| 1822 | fprintf(irp->f, "@src()"); | |
| 1823 | } | |
| 1824 | ||
| 1825 | static 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 | ||
| 1835 | static 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 | ||
| 1845 | static 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 | ||
| 1855 | static 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 | ||
| 1865 | static 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 | ||
| 1876 | static 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 | ||
| 1887 | static void ir_print_breakpoint(IrPrintSrc *irp, Stage1ZirInstBreakpoint *instruction) { | |
| 1888 | fprintf(irp->f, "@breakpoint()"); | |
| 1889 | } | |
| 1890 | ||
| 1891 | static void ir_print_breakpoint(IrPrintGen *irp, Stage1AirInstBreakpoint *instruction) { | |
| 1892 | fprintf(irp->f, "@breakpoint()"); | |
| 1893 | } | |
| 1894 | ||
| 1895 | static void ir_print_frame_address(IrPrintSrc *irp, Stage1ZirInstFrameAddress *instruction) { | |
| 1896 | fprintf(irp->f, "@frameAddress()"); | |
| 1897 | } | |
| 1898 | ||
| 1899 | static void ir_print_frame_address(IrPrintGen *irp, Stage1AirInstFrameAddress *instruction) { | |
| 1900 | fprintf(irp->f, "@frameAddress()"); | |
| 1901 | } | |
| 1902 | ||
| 1903 | static void ir_print_handle(IrPrintSrc *irp, Stage1ZirInstFrameHandle *instruction) { | |
| 1904 | fprintf(irp->f, "@frame()"); | |
| 1905 | } | |
| 1906 | ||
| 1907 | static void ir_print_handle(IrPrintGen *irp, Stage1AirInstFrameHandle *instruction) { | |
| 1908 | fprintf(irp->f, "@frame()"); | |
| 1909 | } | |
| 1910 | ||
| 1911 | static 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 | ||
| 1917 | static 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 | ||
| 1923 | static 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 | ||
| 1929 | static void ir_print_return_address(IrPrintSrc *irp, Stage1ZirInstReturnAddress *instruction) { | |
| 1930 | fprintf(irp->f, "@returnAddress()"); | |
| 1931 | } | |
| 1932 | ||
| 1933 | static void ir_print_return_address(IrPrintGen *irp, Stage1AirInstReturnAddress *instruction) { | |
| 1934 | fprintf(irp->f, "@returnAddress()"); | |
| 1935 | } | |
| 1936 | ||
| 1937 | static 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 | ||
| 1943 | static 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 | ||
| 1968 | static 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 | ||
| 1991 | static 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 | ||
| 1997 | static 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 | ||
| 2003 | static 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 | ||
| 2009 | static 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 | ||
| 2015 | static 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 | ||
| 2021 | static 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 | ||
| 2027 | static 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 | ||
| 2034 | static 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 | ||
| 2041 | static 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 | ||
| 2048 | static 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 | ||
| 2069 | static 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 | ||
| 2075 | static 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 | ||
| 2085 | static 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 | ||
| 2091 | static 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 | ||
| 2098 | static 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 | ||
| 2105 | static 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 | ||
| 2111 | static 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 | ||
| 2117 | static 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 | ||
| 2123 | static 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 | ||
| 2129 | static 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 | ||
| 2137 | static 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 | ||
| 2143 | static 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 | ||
| 2151 | static 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 | ||
| 2157 | static 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 | ||
| 2163 | static 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 | ||
| 2171 | static 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 | ||
| 2177 | static 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 | ||
| 2184 | static 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 | ||
| 2191 | static 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 | ||
| 2197 | static 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 | ||
| 2203 | static 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 | ||
| 2209 | static 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 | ||
| 2213 | static 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 | ||
| 2221 | static 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 | ||
| 2226 | static 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 | ||
| 2231 | static 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 | ||
| 2236 | static 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 | ||
| 2241 | static 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 | ||
| 2260 | static 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 | ||
| 2266 | static 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 | ||
| 2271 | static 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 | ||
| 2276 | static 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 | ||
| 2281 | static 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 | ||
| 2295 | static 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 | ||
| 2304 | static 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 | ||
| 2309 | static 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 | ||
| 2315 | static 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 | ||
| 2321 | static 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 | ||
| 2331 | static 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 | ||
| 2337 | static 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 | ||
| 2345 | static 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 | ||
| 2353 | static 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 | ||
| 2359 | static 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 | ||
| 2365 | static 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 | ||
| 2373 | static 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 | ||
| 2379 | static 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 | ||
| 2387 | static 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 | ||
| 2395 | static 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 | ||
| 2401 | static 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 | ||
| 2407 | static 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 | ||
| 2413 | static 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 | ||
| 2419 | static 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 | ||
| 2433 | static 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 | ||
| 2441 | static void ir_print_extern(IrPrintGen *irp, Stage1AirInstExtern *instruction) { | |
| 2442 | fprintf(irp->f, "@extern(...)"); | |
| 2443 | } | |
| 2444 | ||
| 2445 | static 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 | ||
| 2453 | static 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 | ||
| 2461 | static void ir_print_prefetch(IrPrintGen *irp, Stage1AirInstPrefetch *instruction) { | |
| 2462 | fprintf(irp->f, "@prefetch(...)"); | |
| 2463 | } | |
| 2464 | ||
| 2465 | static 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 | ||
| 2478 | static 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 | ||
| 2491 | static 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 | ||
| 2497 | static 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 | ||
| 2511 | static 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 | ||
| 2519 | static 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 | ||
| 2529 | static 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 | ||
| 2535 | static 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 | ||
| 2547 | static 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 | ||
| 2556 | static void ir_print_save_err_ret_addr(IrPrintSrc *irp, Stage1ZirInstSaveErrRetAddr *instruction) { | |
| 2557 | fprintf(irp->f, "@saveErrRetAddr()"); | |
| 2558 | } | |
| 2559 | ||
| 2560 | static void ir_print_save_err_ret_addr(IrPrintGen *irp, Stage1AirInstSaveErrRetAddr *instruction) { | |
| 2561 | fprintf(irp->f, "@saveErrRetAddr()"); | |
| 2562 | } | |
| 2563 | ||
| 2564 | static 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 | ||
| 2570 | static 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 | ||
| 2576 | static 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 | ||
| 2582 | static 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 | ||
| 2594 | static 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 | ||
| 2604 | static 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 | ||
| 2614 | static 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 | ||
| 2622 | static void ir_print_undeclared_ident(IrPrintSrc *irp, Stage1ZirInstUndeclaredIdent *instruction) { | |
| 2623 | fprintf(irp->f, "@undeclaredIdent(%s)", buf_ptr(instruction->name)); | |
| 2624 | } | |
| 2625 | ||
| 2626 | static 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 | ||
| 2638 | static void ir_print_suspend_begin(IrPrintSrc *irp, Stage1ZirInstSuspendBegin *instruction) { | |
| 2639 | fprintf(irp->f, "@suspendBegin()"); | |
| 2640 | } | |
| 2641 | ||
| 2642 | static void ir_print_suspend_begin(IrPrintGen *irp, Stage1AirInstSuspendBegin *instruction) { | |
| 2643 | fprintf(irp->f, "@suspendBegin()"); | |
| 2644 | } | |
| 2645 | ||
| 2646 | static void ir_print_suspend_finish(IrPrintSrc *irp, Stage1ZirInstSuspendFinish *instruction) { | |
| 2647 | fprintf(irp->f, "@suspendFinish()"); | |
| 2648 | } | |
| 2649 | ||
| 2650 | static void ir_print_suspend_finish(IrPrintGen *irp, Stage1AirInstSuspendFinish *instruction) { | |
| 2651 | fprintf(irp->f, "@suspendFinish()"); | |
| 2652 | } | |
| 2653 | ||
| 2654 | static void ir_print_resume(IrPrintSrc *irp, Stage1ZirInstResume *instruction) { | |
| 2655 | fprintf(irp->f, "resume "); | |
| 2656 | ir_print_other_inst_src(irp, instruction->frame); | |
| 2657 | } | |
| 2658 | ||
| 2659 | static void ir_print_resume(IrPrintGen *irp, Stage1AirInstResume *instruction) { | |
| 2660 | fprintf(irp->f, "resume "); | |
| 2661 | ir_print_other_inst_gen(irp, instruction->frame); | |
| 2662 | } | |
| 2663 | ||
| 2664 | static 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 | ||
| 2672 | static 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 | ||
| 2680 | static 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 | ||
| 2686 | static 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 | ||
| 2692 | static 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 | ||
| 2698 | static 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 | ||
| 2704 | static 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 | ||
| 2712 | static 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 | ||
| 3147 | static 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 | ||
| 3430 | static 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 | ||
| 3438 | static 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 | ||
| 3450 | void 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 | ||
| 3460 | void 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 | ||
| 3476 | void 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 | ||
| 3489 | void 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 | ||
| 3508 | void 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 | ||
| 3519 | void 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 | ||
| 3533 | void 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 | ||
| 15 | void ir_print_src(CodeGen *codegen, FILE *f, Stage1Zir *executable, int indent_size); | |
| 16 | void ir_print_gen(CodeGen *codegen, FILE *f, Stage1Air *executable, int indent_size); | |
| 17 | void ir_print_inst_src(CodeGen *codegen, FILE *f, Stage1ZirInst *inst, int indent_size); | |
| 18 | void ir_print_inst_gen(CodeGen *codegen, FILE *f, Stage1AirInst *inst, int indent_size); | |
| 19 | void ir_print_basic_block_src(CodeGen *codegen, FILE *f, Stage1ZirBasicBlock *bb, int indent_size); | |
| 20 | void ir_print_basic_block_gen(CodeGen *codegen, FILE *f, Stage1AirBasicBlock *bb, int indent_size); | |
| 21 | ||
| 22 | const char* ir_inst_src_type_str(Stage1ZirInstId id); | |
| 23 | const 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 | ||
| 13 | template<typename T> | |
| 14 | struct 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 | ||
| 11 | namespace mem { | |
| 12 | ||
| 13 | void init() { | |
| 14 | heap::bootstrap_allocator_state.init("heap::bootstrap_allocator"); | |
| 15 | heap::c_allocator_state.init("heap::c_allocator"); | |
| 16 | } | |
| 17 | ||
| 18 | void 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 | // | |
| 36 | namespace mem { | |
| 37 | ||
| 38 | // initialize mem module before any use | |
| 39 | void init(); | |
| 40 | ||
| 41 | // deinitialize mem module to free memory and print report | |
| 42 | void deinit(); | |
| 43 | ||
| 44 | // isolate system/libc allocators | |
| 45 | namespace os { | |
| 46 | ||
| 47 | ATTRIBUTE_RETURNS_NOALIAS | |
| 48 | inline 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 | ||
| 60 | inline void free(void *ptr) { | |
| 61 | ::free(ptr); | |
| 62 | } | |
| 63 | ||
| 64 | ATTRIBUTE_RETURNS_NOALIAS | |
| 65 | inline 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 | ||
| 77 | inline 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 | ||
| 91 | struct 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 | ||
| 129 | protected: | |
| 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 | ||
| 13 | namespace mem { | |
| 14 | ||
| 15 | template<typename K, typename V, uint32_t (*HashFunction)(K key), bool (*EqualFn)(K a, K b)> | |
| 16 | class HashMap { | |
| 17 | public: | |
| 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 | ||
| 157 | private: | |
| 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 | ||
| 13 | namespace mem { | |
| 14 | ||
| 15 | template<typename T> | |
| 16 | struct 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 | ||
| 11 | namespace mem { | |
| 12 | ||
| 13 | struct 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) | |
| 49 | typedef 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) | |
| 84 | static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le); | |
| 85 | static size_t utf8_to_utf16le(WCHAR *utf16_le, Slice<uint8_t> utf8); | |
| 86 | static uint64_t windows_perf_freq; | |
| 87 | #elif defined(__MACH__) | |
| 88 | static clock_serv_t macos_calendar_clock; | |
| 89 | static 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) | |
| 97 | extern char **environ; | |
| 98 | #endif | |
| 99 | ||
| 100 | void os_path_dirname(Buf *full_path, Buf *out_dirname) { | |
| 101 | return os_path_split(full_path, out_dirname, nullptr); | |
| 102 | } | |
| 103 | ||
| 104 | bool 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 | ||
| 112 | void 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 | ||
| 144 | void 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 | ||
| 174 | void 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		 | |
| 190 | static 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 | ||
| 209 | enum WindowsPathKind { | |
| 210 | WindowsPathKindNone, | |
| 211 | WindowsPathKindDrive, | |
| 212 | WindowsPathKindNetworkShare, | |
| 213 | }; | |
| 214 | ||
| 215 | struct WindowsPath { | |
| 216 | Slice<uint8_t> disk_designator; | |
| 217 | WindowsPathKind kind; | |
| 218 | bool is_abs; | |
| 219 | }; | |
| 220 | ||
| 221 | ||
| 222 | // Ported from std/os/path.zig | |
| 223 | static 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 | |
| 297 | static 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 | |
| 305 | static 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 | |
| 316 | static 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 | |
| 339 | static 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 | |
| 540 | static 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 | |
| 622 | Buf 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 | ||
| 632 | Error 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 | ||
| 655 | Error 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 | ||
| 673 | static 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 | ||
| 693 | Error 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 | ||
| 735 | Error 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 | ||
| 764 | Error 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) | |
| 788 | static 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 | ||
| 843 | bool 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 | ||
| 854 | Error 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 | ||
| 872 | OsTimeStamp 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 | ||
| 897 | Error 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 | ||
| 931 | Error 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 | ||
| 960 | int 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 | ||
| 981 | static 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) | |
| 1006 | bool got_orig_console_attrs = false; | |
| 1007 | WORD original_console_attributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE; | |
| 1008 | #endif | |
| 1009 | ||
| 1010 | void 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 | |
| 1055 | struct Utf16LeIterator { | |
| 1056 | uint8_t *bytes; | |
| 1057 | size_t i; | |
| 1058 | }; | |
| 1059 | ||
| 1060 | // Ported from std/unicode.zig | |
| 1061 | static Utf16LeIterator Utf16LeIterator_init(WCHAR *ptr) { | |
| 1062 | return {(uint8_t*)ptr, 0}; | |
| 1063 | } | |
| 1064 | ||
| 1065 | // Ported from std/unicode.zig | |
| 1066 | static 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 | |
| 1086 | static 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 | |
| 1095 | static 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 | |
| 1104 | static 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 | |
| 1138 | static 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 | |
| 1152 | static 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 | |
| 1171 | static 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 | |
| 1193 | static 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 | |
| 1212 | static 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 | |
| 1230 | static 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 | |
| 1253 | PathSpace 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 | ||
| 70 | enum TermColor { | |
| 71 | TermColorRed, | |
| 72 | TermColorGreen, | |
| 73 | TermColorCyan, | |
| 74 | TermColorWhite, | |
| 75 | TermColorBold, | |
| 76 | TermColorReset, | |
| 77 | }; | |
| 78 | ||
| 79 | struct OsTimeStamp { | |
| 80 | int64_t sec; | |
| 81 | int64_t nsec; | |
| 82 | }; | |
| 83 | ||
| 84 | int os_init(void); | |
| 85 | ||
| 86 | void os_path_dirname(Buf *full_path, Buf *out_dirname); | |
| 87 | void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename); | |
| 88 | void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname); | |
| 89 | void os_path_join(Buf *dirname, Buf *basename, Buf *out_full_path); | |
| 90 | Buf os_path_resolve(Buf **paths_ptr, size_t paths_len); | |
| 91 | bool os_path_is_absolute(Buf *path); | |
| 92 | ||
| 93 | Error ATTRIBUTE_MUST_USE os_make_path(Buf *path); | |
| 94 | Error ATTRIBUTE_MUST_USE os_make_dir(Buf *path); | |
| 95 | ||
| 96 | Error ATTRIBUTE_MUST_USE os_write_file(Buf *full_path, Buf *contents); | |
| 97 | Error ATTRIBUTE_MUST_USE os_copy_file(Buf *src_path, Buf *dest_path); | |
| 98 | ||
| 99 | Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents); | |
| 100 | Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents); | |
| 101 | ||
| 102 | Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd); | |
| 103 | ||
| 104 | bool os_stderr_supports_color(void); | |
| 105 | void os_stderr_set_color(TermColor color); | |
| 106 | ||
| 107 | Error os_rename(Buf *src_path, Buf *dest_path); | |
| 108 | OsTimeStamp os_timestamp_monotonic(void); | |
| 109 | ||
| 110 | bool os_is_sep(uint8_t c); | |
| 111 | ||
| 112 | const size_t PATH_MAX_WIDE = 32767; | |
| 113 | ||
| 114 | struct PathSpace { | |
| 115 | Array<wchar_t, PATH_MAX_WIDE> data; | |
| 116 | size_t len; | |
| 117 | }; | |
| 118 | ||
| 119 | PathSpace 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 | |
| 52 | union 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 | |
| 66 | union 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 | ||
| 83 | struct 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 | ||
| 112 | static 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 | ||
| 123 | static 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 | ||
| 136 | static 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 | ||
| 143 | static 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 | ||
| 163 | static 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 | ||
| 203 | static 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 | ||
| 211 | static 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 | ||
| 222 | static 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 | ||
| 230 | static 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 | ||
| 329 | static 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 | ||
| 339 | static 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 | ||
| 348 | static 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 | ||
| 357 | static 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 | ||
| 365 | static 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 | ||
| 372 | static 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 | ||
| 378 | static 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 | ||
| 390 | static 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 | ||
| 436 | static float128_t fabsf128(float128_t x) | |
| 437 | { | |
| 438 | union ldshape u = {x}; | |
| 439 | ||
| 440 | u.i.se &= 0x7fff; | |
| 441 | return u.f; | |
| 442 | } | |
| 443 | ||
| 444 | static 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 | ||
| 788 | static 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 | ||
| 981 | static int isspace(int c) | |
| 982 | { | |
| 983 | return c == ' ' || (unsigned)c-'\t' < 5; | |
| 984 | } | |
| 985 | ||
| 986 | static 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 | ||
| 993 | static 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 | ||
| 1001 | float128_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 | ||
| 1077 | float128_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 | ||
| 19 | ZIG_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 | ||
| 17 | struct 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 | ||
| 30 | struct PtrPayload { | |
| 31 | TokenIndex asterisk; | |
| 32 | TokenIndex payload; | |
| 33 | }; | |
| 34 | ||
| 35 | struct PtrIndexPayload { | |
| 36 | TokenIndex asterisk; | |
| 37 | TokenIndex payload; | |
| 38 | TokenIndex index; | |
| 39 | }; | |
| 40 | ||
| 41 | static AstNode *ast_parse_root(ParseContext *pc); | |
| 42 | static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc); | |
| 43 | static AstNode *ast_parse_test_decl(ParseContext *pc); | |
| 44 | static AstNode *ast_parse_top_level_comptime(ParseContext *pc); | |
| 45 | static AstNode *ast_parse_top_level_decl(ParseContext *pc, VisibMod visib_mod, | |
| 46 | TokenIndex doc_comments); | |
| 47 | static AstNode *ast_parse_fn_proto(ParseContext *pc); | |
| 48 | static AstNode *ast_parse_var_decl(ParseContext *pc); | |
| 49 | static AstNode *ast_parse_container_field(ParseContext *pc); | |
| 50 | static AstNode *ast_parse_statement(ParseContext *pc); | |
| 51 | static AstNode *ast_parse_if_statement(ParseContext *pc); | |
| 52 | static AstNode *ast_parse_labeled_statement(ParseContext *pc); | |
| 53 | static AstNode *ast_parse_loop_statement(ParseContext *pc); | |
| 54 | static AstNode *ast_parse_for_statement(ParseContext *pc); | |
| 55 | static AstNode *ast_parse_while_statement(ParseContext *pc); | |
| 56 | static AstNode *ast_parse_block_expr_statement(ParseContext *pc); | |
| 57 | static AstNode *ast_parse_block_expr(ParseContext *pc); | |
| 58 | static AstNode *ast_parse_assign_expr(ParseContext *pc); | |
| 59 | static AstNode *ast_parse_expr(ParseContext *pc); | |
| 60 | static AstNode *ast_parse_bool_or_expr(ParseContext *pc); | |
| 61 | static AstNode *ast_parse_bool_and_expr(ParseContext *pc); | |
| 62 | static AstNode *ast_parse_compare_expr(ParseContext *pc); | |
| 63 | static AstNode *ast_parse_bitwise_expr(ParseContext *pc); | |
| 64 | static AstNode *ast_parse_bit_shift_expr(ParseContext *pc); | |
| 65 | static AstNode *ast_parse_addition_expr(ParseContext *pc); | |
| 66 | static AstNode *ast_parse_multiply_expr(ParseContext *pc); | |
| 67 | static AstNode *ast_parse_prefix_expr(ParseContext *pc); | |
| 68 | static AstNode *ast_parse_primary_expr(ParseContext *pc); | |
| 69 | static AstNode *ast_parse_if_expr(ParseContext *pc); | |
| 70 | static AstNode *ast_parse_block(ParseContext *pc); | |
| 71 | static AstNode *ast_parse_loop_expr(ParseContext *pc); | |
| 72 | static AstNode *ast_parse_for_expr(ParseContext *pc); | |
| 73 | static AstNode *ast_parse_while_expr(ParseContext *pc); | |
| 74 | static AstNode *ast_parse_curly_suffix_expr(ParseContext *pc); | |
| 75 | static AstNode *ast_parse_init_list(ParseContext *pc); | |
| 76 | static AstNode *ast_parse_type_expr(ParseContext *pc); | |
| 77 | static AstNode *ast_parse_error_union_expr(ParseContext *pc); | |
| 78 | static AstNode *ast_parse_suffix_expr(ParseContext *pc); | |
| 79 | static AstNode *ast_parse_primary_type_expr(ParseContext *pc); | |
| 80 | static AstNode *ast_parse_container_decl(ParseContext *pc); | |
| 81 | static AstNode *ast_parse_error_set_decl(ParseContext *pc); | |
| 82 | static AstNode *ast_parse_grouped_expr(ParseContext *pc); | |
| 83 | static AstNode *ast_parse_if_type_expr(ParseContext *pc); | |
| 84 | static AstNode *ast_parse_labeled_type_expr(ParseContext *pc); | |
| 85 | static AstNode *ast_parse_loop_type_expr(ParseContext *pc); | |
| 86 | static AstNode *ast_parse_for_type_expr(ParseContext *pc); | |
| 87 | static AstNode *ast_parse_while_type_expr(ParseContext *pc); | |
| 88 | static AstNode *ast_parse_switch_expr(ParseContext *pc); | |
| 89 | static AstNode *ast_parse_asm_expr(ParseContext *pc); | |
| 90 | static AstNode *ast_parse_anon_lit(ParseContext *pc); | |
| 91 | static AstNode *ast_parse_asm_output(ParseContext *pc); | |
| 92 | static AsmOutput *ast_parse_asm_output_item(ParseContext *pc); | |
| 93 | static AstNode *ast_parse_asm_input(ParseContext *pc); | |
| 94 | static AsmInput *ast_parse_asm_input_item(ParseContext *pc); | |
| 95 | static AstNode *ast_parse_asm_clobbers(ParseContext *pc); | |
| 96 | static TokenIndex ast_parse_break_label(ParseContext *pc); | |
| 97 | static TokenIndex ast_parse_block_label(ParseContext *pc); | |
| 98 | static AstNode *ast_parse_field_init(ParseContext *pc); | |
| 99 | static AstNode *ast_parse_while_continue_expr(ParseContext *pc); | |
| 100 | static AstNode *ast_parse_link_section(ParseContext *pc); | |
| 101 | static AstNode *ast_parse_callconv(ParseContext *pc); | |
| 102 | static AstNode *ast_parse_param_decl(ParseContext *pc); | |
| 103 | static AstNode *ast_parse_param_type(ParseContext *pc); | |
| 104 | static AstNode *ast_parse_if_prefix(ParseContext *pc); | |
| 105 | static AstNode *ast_parse_while_prefix(ParseContext *pc); | |
| 106 | static AstNode *ast_parse_for_prefix(ParseContext *pc); | |
| 107 | static TokenIndex ast_parse_payload(ParseContext *pc); | |
| 108 | static Optional<PtrPayload> ast_parse_ptr_payload(ParseContext *pc); | |
| 109 | static Optional<PtrIndexPayload> ast_parse_ptr_index_payload(ParseContext *pc); | |
| 110 | static AstNode *ast_parse_switch_prong(ParseContext *pc); | |
| 111 | static AstNode *ast_parse_switch_case(ParseContext *pc); | |
| 112 | static AstNode *ast_parse_switch_item(ParseContext *pc); | |
| 113 | static AstNode *ast_parse_assign_op(ParseContext *pc); | |
| 114 | static AstNode *ast_parse_compare_op(ParseContext *pc); | |
| 115 | static AstNode *ast_parse_bitwise_op(ParseContext *pc); | |
| 116 | static AstNode *ast_parse_bit_shift_op(ParseContext *pc); | |
| 117 | static AstNode *ast_parse_addition_op(ParseContext *pc); | |
| 118 | static AstNode *ast_parse_multiply_op(ParseContext *pc); | |
| 119 | static AstNode *ast_parse_prefix_op(ParseContext *pc); | |
| 120 | static AstNode *ast_parse_prefix_type_op(ParseContext *pc); | |
| 121 | static AstNode *ast_parse_suffix_op(ParseContext *pc); | |
| 122 | static AstNode *ast_parse_fn_call_arguments(ParseContext *pc); | |
| 123 | static AstNode *ast_parse_array_type_start(ParseContext *pc); | |
| 124 | static AstNode *ast_parse_ptr_type_start(ParseContext *pc); | |
| 125 | static AstNode *ast_parse_container_decl_auto(ParseContext *pc); | |
| 126 | static AstNode *ast_parse_container_decl_type(ParseContext *pc); | |
| 127 | static AstNode *ast_parse_byte_align(ParseContext *pc); | |
| 128 | ||
| 129 | ATTRIBUTE_NORETURN | |
| 130 | static 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 | ||
| 142 | ATTRIBUTE_PRINTF(3, 4) | |
| 143 | ATTRIBUTE_NORETURN | |
| 144 | static 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 | ||
| 154 | ATTRIBUTE_NORETURN | |
| 155 | static 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 | ||
| 159 | static 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 | ||
| 166 | static 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 | ||
| 173 | static 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 | ||
| 180 | static TokenIndex peek_token(ParseContext *pc) { | |
| 181 | return pc->current_token; | |
| 182 | } | |
| 183 | ||
| 184 | static TokenIndex eat_token(ParseContext *pc) { | |
| 185 | TokenIndex res = peek_token(pc); | |
| 186 | pc->current_token += 1; | |
| 187 | return res; | |
| 188 | } | |
| 189 | ||
| 190 | static 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 | ||
| 199 | static 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 | ||
| 208 | static void put_back_token(ParseContext *pc) { | |
| 209 | pc->current_token -= 1; | |
| 210 | } | |
| 211 | ||
| 212 | static 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 | ||
| 237 | static 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? | |
| 243 | template<typename T> | |
| 244 | static 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 | ||
| 259 | static 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 | ||
| 266 | enum BinOpChain { | |
| 267 | BinOpChainOnce, | |
| 268 | BinOpChainInf, | |
| 269 | }; | |
| 270 | ||
| 271 | // Op* Child | |
| 272 | static 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)(*/?) | |
| 334 | static 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)? | |
| 370 | static 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) | |
| 411 | static 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)? | |
| 437 | static 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)? | |
| 454 | static 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 | ||
| 474 | template<TokenId id, BinOpType op> | |
| 475 | AstNode *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 | ||
| 485 | AstNode *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 | |
| 500 | static 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 | ||
| 517 | static 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 | ||
| 526 | static TokenIndex ast_parse_doc_comments(ParseContext *pc) { | |
| 527 | return ast_parse_multi_tok(pc, TokenIdDocComment); | |
| 528 | } | |
| 529 | ||
| 530 | static TokenIndex ast_parse_container_doc_comments(ParseContext *pc) { | |
| 531 | return ast_parse_multi_tok(pc, TokenIdContainerDocComment); | |
| 532 | } | |
| 533 | ||
| 534 | enum 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 | // / | |
| 550 | static 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 | |
| 630 | static 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 | |
| 644 | static 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 | |
| 666 | static 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) | |
| 794 | static 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 | |
| 845 | static 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)? | |
| 876 | static 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 | |
| 914 | static 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 ) | |
| 989 | static 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) | |
| 1044 | static 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) | |
| 1074 | static 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 ) | |
| 1098 | static 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 ) | |
| 1132 | static 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 | |
| 1170 | static 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 | |
| 1185 | static 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)? | |
| 1198 | static 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 | |
| 1203 | static 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)* | |
| 1221 | static 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)* | |
| 1231 | static 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)? | |
| 1241 | static 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)* | |
| 1246 | static 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)* | |
| 1251 | static 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)* | |
| 1256 | static 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)* | |
| 1261 | static 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 | |
| 1266 | static 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 | |
| 1286 | static 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)? | |
| 1378 | static 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 | |
| 1383 | static 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) | |
| 1401 | static 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)? | |
| 1410 | static 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)? | |
| 1415 | static AstNode *ast_parse_while_expr(ParseContext *pc) { | |
| 1416 | return ast_parse_while_expr_helper(pc, ast_parse_expr); | |
| 1417 | } | |
| 1418 | ||
| 1419 | // CurlySuffixExpr <- TypeExpr InitList? | |
| 1420 | static 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 | |
| 1438 | static 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 | |
| 1483 | static 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)? | |
| 1492 | static 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)* | |
| 1511 | static 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 | |
| 1624 | static 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 | |
| 1730 | static 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 | |
| 1753 | static 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 | |
| 1785 | static 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)? | |
| 1799 | static 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 | |
| 1806 | static 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) | |
| 1840 | static 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)? | |
| 1849 | static 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)? | |
| 1854 | static 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 | |
| 1859 | static 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 | |
| 1878 | static 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 | ||
| 1897 | static 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? | |
| 1917 | static 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 | |
| 1931 | static 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? | |
| 1961 | static 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 | |
| 1975 | static 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 | |
| 1995 | static 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 | |
| 2014 | static 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 | |
| 2022 | static 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 | |
| 2038 | static 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 | |
| 2066 | static 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 | |
| 2078 | static 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 | |
| 2090 | static 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 | |
| 2102 | static 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 | |
| 2146 | static 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? | |
| 2172 | static 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? | |
| 2193 | static 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 | |
| 2217 | static 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 | |
| 2240 | static 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 | |
| 2250 | static 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 | |
| 2265 | static 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 | |
| 2284 | static 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 | |
| 2307 | static 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)? | |
| 2340 | static 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 | |
| 2376 | static 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 | |
| 2418 | static 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? | |
| 2444 | static 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 | |
| 2476 | static 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 | |
| 2501 | static 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 | |
| 2530 | static 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 | |
| 2559 | static 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)* | |
| 2596 | static 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 | |
| 2721 | static 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 | |
| 2767 | static 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 | |
| 2782 | static 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 | |
| 2805 | static 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 | |
| 2869 | static 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 | |
| 2889 | static 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 | |
| 2957 | static 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 | ||
| 2967 | static void visit_field(AstNode **node, void (*visit)(AstNode **, void *context), void *context) { | |
| 2968 | if (*node) { | |
| 2969 | visit(node, context); | |
| 2970 | } | |
| 2971 | } | |
| 2972 | ||
| 2973 | static 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 | ||
| 2981 | void 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 | ||
| 3192 | Error 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 | ||
| 3336 | static 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 | ||
| 3372 | Error 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 | ||
| 3481 | static 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 | ||
| 3519 | Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token) { | |
| 3520 | bool trash; | |
| 3521 | return token_identifier_buf2(root_struct, token, &trash); | |
| 3522 | } | |
| 3523 | ||
| 3524 | Buf *node_identifier_buf(AstNode *node) { | |
| 3525 | bool trash; | |
| 3526 | return node_identifier_buf2(node, &trash); | |
| 3527 | } | |
| 3528 | ||
| 3529 | Buf *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 | ||
| 3544 | void 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 | ||
| 15 | AstNode * ast_parse(Buf *buf, ZigType *owner, ErrColor err_color); | |
| 16 | ||
| 17 | void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context); | |
| 18 | ||
| 19 | Buf *node_identifier_buf(AstNode *node); | |
| 20 | Buf *node_identifier_buf2(AstNode *node, bool *is_at_syntax); | |
| 21 | ||
| 22 | Buf *token_identifier_buf(RootStruct *root_struct, TokenIndex token); | |
| 23 | ||
| 24 | void token_number_literal_bigint(RootStruct *root_struct, BigInt *result, TokenIndex token); | |
| 25 | ||
| 26 | Error source_string_literal_buf(const char *source, Buf *out, size_t *bad_index); | |
| 27 | Error 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 | ||
| 3 | AstNode *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 | ||
| 23 | static 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 | ||
| 35 | void 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 | ||
| 42 | bool 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 | ||
| 13 | struct Range { | |
| 14 | BigInt first; | |
| 15 | BigInt last; | |
| 16 | }; | |
| 17 | ||
| 18 | struct RangeWithSrc { | |
| 19 | Range range; | |
| 20 | AstNode *source_node; | |
| 21 | }; | |
| 22 | ||
| 23 | struct RangeSet { | |
| 24 | ZigList<RangeWithSrc> src_range_list; | |
| 25 | }; | |
| 26 | ||
| 27 | AstNode *rangeset_add_range(RangeSet *rs, BigInt *first, BigInt *last, AstNode *source_node); | |
| 28 | bool 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 | ||
| 11 | extern "C" { | |
| 12 | #include "softfloat.h" | |
| 13 | } | |
| 14 | ||
| 15 | #include "zigendian.h" | |
| 16 | ||
| 17 | static 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 | ||
| 24 | static 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 | ||
| 31 | static 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. | |
| 40 | static 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 | ||
| 48 | static 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 | ||
| 54 | static 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 | ||
| 73 | static 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 | ||
| 4 | extern "C" { | |
| 5 | #include "softfloat.h" | |
| 6 | } | |
| 7 | ||
| 8 | void 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 | ||
| 21 | void 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 | ||
| 31 | void 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 | ||
| 44 | void 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 | ||
| 50 | void 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 | ||
| 60 | void 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 | ||
| 66 | float16_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 | ||
| 6 | void f128M_abs(const float128_t *aPtr, float128_t *zPtr); | |
| 7 | void f128M_trunc(const float128_t *aPtr, float128_t *zPtr); | |
| 8 | void f128M_neg(const float128_t *aPtr, float128_t *zPtr); | |
| 9 | ||
| 10 | void extF80M_abs(const extFloat80_t *aPtr, extFloat80_t *zPtr); | |
| 11 | void extF80M_trunc(const extFloat80_t *aPtr, extFloat80_t *zPtr); | |
| 12 | void extF80M_neg(const extFloat80_t *aPtr, extFloat80_t *zPtr); | |
| 13 | ||
| 14 | float16_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 | ||
| 13 | void zig_stage1_os_init(void) { | |
| 14 | os_init(); | |
| 15 | mem::init(); | |
| 16 | init_all_targets(); | |
| 17 | } | |
| 18 | ||
| 19 | struct 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 | ||
| 34 | void zig_stage1_destroy(struct ZigStage1 *stage1) { | |
| 35 | CodeGen *codegen = reinterpret_cast<CodeGen *>(stage1); | |
| 36 | codegen_destroy(codegen); | |
| 37 | } | |
| 38 | ||
| 39 | static 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 | ||
| 68 | void 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 | |
| 24 | enum ErrColor { | |
| 25 | ErrColorAuto, | |
| 26 | ErrColorOff, | |
| 27 | ErrColorOn, | |
| 28 | }; | |
| 29 | ||
| 30 | // ABI warning | |
| 31 | enum CodeModel { | |
| 32 | CodeModelDefault, | |
| 33 | CodeModelTiny, | |
| 34 | CodeModelSmall, | |
| 35 | CodeModelKernel, | |
| 36 | CodeModelMedium, | |
| 37 | CodeModelLarge, | |
| 38 | }; | |
| 39 | ||
| 40 | // ABI warning | |
| 41 | enum 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 | |
| 60 | enum 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 | |
| 108 | struct 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 | |
| 122 | struct Stage2Progress; | |
| 123 | // ABI warning | |
| 124 | struct Stage2ProgressNode; | |
| 125 | ||
| 126 | enum BuildMode { | |
| 127 | BuildModeDebug, | |
| 128 | BuildModeSafeRelease, | |
| 129 | BuildModeFastRelease, | |
| 130 | BuildModeSmallRelease, | |
| 131 | }; | |
| 132 | ||
| 133 | ||
| 134 | struct 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. | |
| 148 | struct 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 | ||
| 218 | ZIG_EXTERN_C void zig_stage1_os_init(void); | |
| 219 | ||
| 220 | ZIG_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 | ||
| 226 | ZIG_EXTERN_C void zig_stage1_build_object(struct ZigStage1 *); | |
| 227 | ||
| 228 | ZIG_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 | |
| 35 | enum 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 | |
| 120 | struct 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 | |
| 132 | ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len); | |
| 133 | ||
| 134 | // ABI warning | |
| 135 | ZIG_EXTERN_C struct Stage2Progress *stage2_progress_create(void); | |
| 136 | // ABI warning | |
| 137 | ZIG_EXTERN_C void stage2_progress_disable_tty(struct Stage2Progress *progress); | |
| 138 | // ABI warning | |
| 139 | ZIG_EXTERN_C void stage2_progress_destroy(struct Stage2Progress *progress); | |
| 140 | // ABI warning | |
| 141 | ZIG_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 | |
| 144 | ZIG_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 | |
| 147 | ZIG_EXTERN_C void stage2_progress_end(struct Stage2ProgressNode *node); | |
| 148 | // ABI warning | |
| 149 | ZIG_EXTERN_C void stage2_progress_complete_one(struct Stage2ProgressNode *node); | |
| 150 | // ABI warning | |
| 151 | ZIG_EXTERN_C void stage2_progress_update_node(struct Stage2ProgressNode *node, | |
| 152 | size_t completed_count, size_t estimated_total_items); | |
| 153 | ||
| 154 | // ABI warning | |
| 155 | struct Stage2SemVer { | |
| 156 | uint32_t major; | |
| 157 | uint32_t minor; | |
| 158 | uint32_t patch; | |
| 159 | }; | |
| 160 | ||
| 161 | // ABI warning | |
| 162 | ZIG_EXTERN_C const char *stage2_version_string(void); | |
| 163 | ||
| 164 | // ABI warning | |
| 165 | ZIG_EXTERN_C Stage2SemVer stage2_version(void); | |
| 166 | ||
| 167 | // ABI warning | |
| 168 | ZIG_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 | |
| 172 | ZIG_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 | |
| 176 | ZIG_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 | |
| 181 | ZIG_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 | |
| 186 | ZIG_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 | ||
| 16 | static 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 | ||
| 78 | static 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 | ||
| 94 | static 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 | |
| 142 | static 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 | ||
| 185 | static 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 | ||
| 197 | size_t target_oformat_count(void) { | |
| 198 | return array_length(oformat_list); | |
| 199 | } | |
| 200 | ||
| 201 | ZigLLVM_ObjectFormatType target_oformat_enum(size_t index) { | |
| 202 | assert(index < array_length(oformat_list)); | |
| 203 | return oformat_list[index]; | |
| 204 | } | |
| 205 | ||
| 206 | const 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 | ||
| 221 | size_t target_arch_count(void) { | |
| 222 | return array_length(arch_list); | |
| 223 | } | |
| 224 | ||
| 225 | ZigLLVM_ArchType target_arch_enum(size_t index) { | |
| 226 | assert(index < array_length(arch_list)); | |
| 227 | return arch_list[index]; | |
| 228 | } | |
| 229 | ||
| 230 | size_t target_vendor_count(void) { | |
| 231 | return array_length(vendor_list); | |
| 232 | } | |
| 233 | ||
| 234 | ZigLLVM_VendorType target_vendor_enum(size_t index) { | |
| 235 | assert(index < array_length(vendor_list)); | |
| 236 | return vendor_list[index]; | |
| 237 | } | |
| 238 | ||
| 239 | size_t target_os_count(void) { | |
| 240 | return array_length(os_list); | |
| 241 | } | |
| 242 | Os target_os_enum(size_t index) { | |
| 243 | assert(index < array_length(os_list)); | |
| 244 | return os_list[index]; | |
| 245 | } | |
| 246 | ||
| 247 | ZigLLVM_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 | ||
| 335 | const 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 | ||
| 390 | size_t target_abi_count(void) { | |
| 391 | return array_length(abi_list); | |
| 392 | } | |
| 393 | ZigLLVM_EnvironmentType target_abi_enum(size_t index) { | |
| 394 | assert(index < array_length(abi_list)); | |
| 395 | return abi_list[index]; | |
| 396 | } | |
| 397 | const char *target_abi_name(ZigLLVM_EnvironmentType abi) { | |
| 398 | if (abi == ZigLLVM_UnknownEnvironment) | |
| 399 | return "none"; | |
| 400 | return ZigLLVMGetEnvironmentTypeName(abi); | |
| 401 | } | |
| 402 | ||
| 403 | Error 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 | ||
| 415 | Error 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 | ||
| 460 | Error 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 | ||
| 472 | const char *target_arch_name(ZigLLVM_ArchType arch) { | |
| 473 | return ZigLLVMGetArchTypeName(arch); | |
| 474 | } | |
| 475 | ||
| 476 | void init_all_targets(void) { | |
| 477 | LLVMInitializeAllTargets(); | |
| 478 | LLVMInitializeAllTargetInfos(); | |
| 479 | LLVMInitializeAllTargetMCs(); | |
| 480 | LLVMInitializeAllAsmPrinters(); | |
| 481 | LLVMInitializeAllAsmParsers(); | |
| 482 | } | |
| 483 | ||
| 484 | void 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 | ||
| 492 | void 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 | ||
| 501 | bool 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 | ||
| 513 | ZigLLVM_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 | |
| 529 | uint32_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 | ||
| 602 | uint32_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 | ||
| 677 | uint32_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 | ||
| 815 | bool target_allows_addr_zero(const ZigTarget *target) { | |
| 816 | return target->os == OsFreestanding || target->os == OsUefi; | |
| 817 | } | |
| 818 | ||
| 819 | const 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 | ||
| 829 | const char *target_asm_file_ext(const ZigTarget *target) { | |
| 830 | return ".s"; | |
| 831 | } | |
| 832 | ||
| 833 | const char *target_llvm_ir_file_ext(const ZigTarget *target) { | |
| 834 | return ".ll"; | |
| 835 | } | |
| 836 | ||
| 837 | bool target_is_android(const ZigTarget *target) { | |
| 838 | return target->abi == ZigLLVM_Android; | |
| 839 | } | |
| 840 | ||
| 841 | const 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 | ||
| 915 | bool 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. | |
| 986 | bool 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 | ||
| 999 | bool target_is_wasm(const ZigTarget *target) { | |
| 1000 | return target->arch == ZigLLVM_wasm32 || target->arch == ZigLLVM_wasm64; | |
| 1001 | } | |
| 1002 | ||
| 1003 | bool target_is_bpf(const ZigTarget *target) { | |
| 1004 | return target->arch == ZigLLVM_bpfel || target->arch == ZigLLVM_bpfeb; | |
| 1005 | } | |
| 1006 | ||
| 1007 | ZigLLVM_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 | ||
| 1065 | bool target_has_debug_info(const ZigTarget *target) { | |
| 1066 | return true; | |
| 1067 | } | |
| 1068 | ||
| 1069 | bool 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 | ||
| 1103 | bool 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 | ||
| 1114 | bool target_is_riscv(const ZigTarget *target) { | |
| 1115 | return target->arch == ZigLLVM_riscv32 || target->arch == ZigLLVM_riscv64; | |
| 1116 | } | |
| 1117 | ||
| 1118 | bool target_is_sparc(const ZigTarget *target) { | |
| 1119 | return target->arch == ZigLLVM_sparc || target->arch == ZigLLVM_sparcv9; | |
| 1120 | } | |
| 1121 | ||
| 1122 | bool 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 | ||
| 1127 | bool 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. | |
| 1134 | unsigned 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. | |
| 1140 | unsigned 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 | ||
| 13 | struct Buf; | |
| 14 | ||
| 15 | enum CIntType { | |
| 16 | CIntTypeShort, | |
| 17 | CIntTypeUShort, | |
| 18 | CIntTypeInt, | |
| 19 | CIntTypeUInt, | |
| 20 | CIntTypeLong, | |
| 21 | CIntTypeULong, | |
| 22 | CIntTypeLongLong, | |
| 23 | CIntTypeULongLong, | |
| 24 | ||
| 25 | CIntTypeCount, | |
| 26 | }; | |
| 27 | ||
| 28 | Error target_parse_arch(ZigLLVM_ArchType *arch, const char *arch_ptr, size_t arch_len); | |
| 29 | Error target_parse_os(Os *os, const char *os_ptr, size_t os_len); | |
| 30 | Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len); | |
| 31 | ||
| 32 | size_t target_arch_count(void); | |
| 33 | ZigLLVM_ArchType target_arch_enum(size_t index); | |
| 34 | const char *target_arch_name(ZigLLVM_ArchType arch); | |
| 35 | ||
| 36 | const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch); | |
| 37 | ||
| 38 | size_t target_vendor_count(void); | |
| 39 | ZigLLVM_VendorType target_vendor_enum(size_t index); | |
| 40 | ||
| 41 | size_t target_os_count(void); | |
| 42 | Os target_os_enum(size_t index); | |
| 43 | const char *target_os_name(Os os_type); | |
| 44 | ||
| 45 | size_t target_abi_count(void); | |
| 46 | ZigLLVM_EnvironmentType target_abi_enum(size_t index); | |
| 47 | const char *target_abi_name(ZigLLVM_EnvironmentType abi); | |
| 48 | ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os); | |
| 49 | ||
| 50 | ||
| 51 | size_t target_oformat_count(void); | |
| 52 | ZigLLVM_ObjectFormatType target_oformat_enum(size_t index); | |
| 53 | const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat); | |
| 54 | ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target); | |
| 55 | ||
| 56 | void target_triple_llvm(Buf *triple, const ZigTarget *target); | |
| 57 | void target_triple_zig(Buf *triple, const ZigTarget *target); | |
| 58 | ||
| 59 | void init_all_targets(void); | |
| 60 | ||
| 61 | void resolve_target_object_format(ZigTarget *target); | |
| 62 | ||
| 63 | uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id); | |
| 64 | ||
| 65 | const char *target_o_file_ext(const ZigTarget *target); | |
| 66 | const char *target_asm_file_ext(const ZigTarget *target); | |
| 67 | const char *target_llvm_ir_file_ext(const ZigTarget *target); | |
| 68 | ||
| 69 | ZigLLVM_OSType get_llvm_os_type(Os os_type); | |
| 70 | ||
| 71 | bool target_is_arm(const ZigTarget *target); | |
| 72 | bool target_is_mips(const ZigTarget *target); | |
| 73 | bool target_is_ppc(const ZigTarget *target); | |
| 74 | bool target_allows_addr_zero(const ZigTarget *target); | |
| 75 | bool target_has_valgrind_support(const ZigTarget *target); | |
| 76 | bool target_os_is_darwin(Os os); | |
| 77 | bool target_is_wasm(const ZigTarget *target); | |
| 78 | bool target_is_bpf(const ZigTarget *target); | |
| 79 | bool target_is_riscv(const ZigTarget *target); | |
| 80 | bool target_is_sparc(const ZigTarget *target); | |
| 81 | bool target_is_android(const ZigTarget *target); | |
| 82 | bool target_has_debug_info(const ZigTarget *target); | |
| 83 | bool target_long_double_is_f128(const ZigTarget *target); | |
| 84 | bool target_has_f80(const ZigTarget *target); | |
| 85 | ||
| 86 | uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch); | |
| 87 | uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch); | |
| 88 | ||
| 89 | unsigned target_fn_ptr_align(const ZigTarget *target); | |
| 90 | unsigned 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 | ||
| 139 | struct ZigKeyword { | |
| 140 | const char *text; | |
| 141 | TokenId token_id; | |
| 142 | }; | |
| 143 | ||
| 144 | static 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. | |
| 196 | static 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 | ||
| 205 | enum 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 | ||
| 272 | struct Tokenize { | |
| 273 | Tokenization *out; | |
| 274 | size_t pos; | |
| 275 | TokenizeState state; | |
| 276 | uint32_t line; | |
| 277 | uint32_t column; | |
| 278 | }; | |
| 279 | ||
| 280 | ATTRIBUTE_PRINTF(2, 3) | |
| 281 | static 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 | ||
| 292 | static 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 | ||
| 301 | static void cancel_token(Tokenize *t) { | |
| 302 | t->out->ids.pop(); | |
| 303 | t->out->locs.pop(); | |
| 304 | } | |
| 305 | ||
| 306 | static 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 | ||
| 329 | static void invalid_eof(Tokenize *t) { | |
| 330 | return tokenize_error(t, "unexpected End-Of-File"); | |
| 331 | } | |
| 332 | ||
| 333 | static 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 | ||
| 357 | void 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 | } | |
| 1495 | eof:; | |
| 1496 | ||
| 1497 | begin_token(&t, TokenIdEof); | |
| 1498 | } | |
| 1499 | ||
| 1500 | const 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 | ||
| 15 | enum 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 | ||
| 140 | typedef uint32_t TokenIndex; | |
| 141 | ||
| 142 | struct TokenLoc { | |
| 143 | uint32_t offset; | |
| 144 | uint32_t line; | |
| 145 | uint32_t column; | |
| 146 | }; | |
| 147 | ||
| 148 | struct 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 | ||
| 157 | void tokenize(const char *source, Tokenization *out_tokenization); | |
| 158 | ||
| 159 | const 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 | ||
| 14 | void 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. | |
| 25 | bool 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. | |
| 35 | Optional<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. | |
| 61 | Optional<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 | |
| 85 | Slice<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 | |
| 95 | SplitIterator memSplit(Slice<uint8_t> buffer, Slice<uint8_t> split_bytes) { | |
| 96 | return SplitIterator{0, buffer, split_bytes}; | |
| 97 | } | |
| 98 | ||
| 99 | void 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) | |
| 28 | static 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 | } | |
| 42 | static 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 | ||
| 61 | template <typename T, size_t n> | |
| 62 | constexpr size_t array_length(const T (&)[n]) { | |
| 63 | return n; | |
| 64 | } | |
| 65 | ||
| 66 | template <typename T> | |
| 67 | static inline T max(T a, T b) { | |
| 68 | return (a >= b) ? a : b; | |
| 69 | } | |
| 70 | ||
| 71 | template <typename T> | |
| 72 | static inline T min(T a, T b) { | |
| 73 | return (a <= b) ? a : b; | |
| 74 | } | |
| 75 | ||
| 76 | template<typename T> | |
| 77 | static inline T clamp(T min_value, T value, T max_value) { | |
| 78 | return max(min(value, max_value), min_value); | |
| 79 | } | |
| 80 | ||
| 81 | static 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 | } | |
| 86 | static 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 | ||
| 96 | static 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 | ||
| 100 | static inline bool str_eql_str(const char *a, const char* b) { | |
| 101 | return mem_eql_mem(a, strlen(a), b, strlen(b)); | |
| 102 | } | |
| 103 | ||
| 104 | static 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 | ||
| 108 | static inline bool is_power_of_2(uint64_t x) { | |
| 109 | return x != 0 && ((x & (~x + 1)) == x); | |
| 110 | } | |
| 111 | ||
| 112 | static 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 | ||
| 117 | static 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 | ||
| 121 | static 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 | ||
| 132 | static inline uint8_t log2_u64(uint64_t x) { | |
| 133 | return (63 - clzll(x)); | |
| 134 | } | |
| 135 | ||
| 136 | void zig_pretty_print_bytes(FILE *f, double n); | |
| 137 | ||
| 138 | template<typename T> | |
| 139 | struct 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 | ||
| 157 | template<typename T> | |
| 158 | struct 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 | ||
| 189 | template<typename T, size_t n> | |
| 190 | struct 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 | ||
| 202 | static inline Slice<uint8_t> str(const char *literal) { | |
| 203 | return {(uint8_t*)(literal), strlen(literal)}; | |
| 204 | } | |
| 205 | ||
| 206 | // Ported from std/mem.zig | |
| 207 | template<typename T> | |
| 208 | static 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 | |
| 219 | template<typename T> | |
| 220 | static 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 | |
| 227 | template<typename T> | |
| 228 | static 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 | |
| 235 | struct SplitIterator { | |
| 236 | size_t index; | |
| 237 | Slice<uint8_t> buffer; | |
| 238 | Slice<uint8_t> split_bytes; | |
| 239 | }; | |
| 240 | ||
| 241 | bool SplitIterator_isSplitByte(SplitIterator *self, uint8_t byte); | |
| 242 | Optional< Slice<uint8_t> > SplitIterator_next(SplitIterator *self); | |
| 243 | Optional< Slice<uint8_t> > SplitIterator_next_separate(SplitIterator *self); | |
| 244 | Slice<uint8_t> SplitIterator_rest(SplitIterator *self); | |
| 245 | SplitIterator 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 | ||
| 46 | ATTRIBUTE_COLD | |
| 47 | ATTRIBUTE_NORETURN | |
| 48 | ATTRIBUTE_PRINTF(1, 2) | |
| 49 | void zig_panic(const char *format, ...); | |
| 50 | ||
| 51 | static 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 | ||
| 28 | static 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 | ||
| 33 | static 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 | ||
| 62 | static 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 | ||
| 145 | static 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 | ||
| 166 | static const char* get_baseline_llvm_cpu_name(ZigLLVM_ArchType arch) { | |
| 167 | return ""; | |
| 168 | } | |
| 169 | ||
| 170 | static 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 | ||
| 177 | static 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 | ||
| 246 | static 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 | ||
| 254 | int 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 | ||
| 261 | int 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 | ||
| 501 | void 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 | ||
| 508 | struct Stage2Progress { | |
| 509 | int trash; | |
| 510 | }; | |
| 511 | ||
| 512 | struct Stage2ProgressNode { | |
| 513 | int trash; | |
| 514 | }; | |
| 515 | ||
| 516 | Stage2Progress *stage2_progress_create(void) { | |
| 517 | return nullptr; | |
| 518 | } | |
| 519 | ||
| 520 | void stage2_progress_destroy(Stage2Progress *progress) {} | |
| 521 | ||
| 522 | Stage2ProgressNode *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 | } | |
| 527 | Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, | |
| 528 | const char *name_ptr, size_t name_len, size_t estimated_total_items) | |
| 529 | { | |
| 530 | return nullptr; | |
| 531 | } | |
| 532 | void stage2_progress_end(Stage2ProgressNode *node) {} | |
| 533 | void stage2_progress_complete_one(Stage2ProgressNode *node) {} | |
| 534 | void stage2_progress_disable_tty(Stage2Progress *progress) {} | |
| 535 | void stage2_progress_update_node(Stage2ProgressNode *node, size_t completed_count, size_t estimated_total_items){} | |
| 536 | ||
| 537 | const 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 | ||
| 552 | Error 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 | ||
| 560 | const 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 | ||
| 567 | const char *stage2_version_string(void) { | |
| 568 | return ZIG_VERSION_STRING; | |
| 569 | } | |
| 570 | ||
| 571 | struct Stage2SemVer stage2_version(void) { | |
| 572 | return {ZIG_VERSION_MAJOR, ZIG_VERSION_MINOR, ZIG_VERSION_PATCH}; | |
| 573 | } | |
| 574 | ||
| 575 | Error 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 |