aboutsummaryrefslogtreecommitdiff
path: root/tinycc
diff options
context:
space:
mode:
Diffstat (limited to 'tinycc')
-rw-r--r--tinycc/.gitignore64
-rw-r--r--tinycc/COPYING504
-rw-r--r--tinycc/Changelog456
-rw-r--r--tinycc/CodingStyle71
-rw-r--r--tinycc/README96
-rw-r--r--tinycc/RELICENSING63
-rw-r--r--tinycc/TODO106
-rw-r--r--tinycc/USES20
-rw-r--r--tinycc/VERSION1
-rw-r--r--tinycc/coff.h446
-rw-r--r--tinycc/configure602
-rw-r--r--tinycc/dwarf.h1046
-rw-r--r--tinycc/elf.h3320
-rw-r--r--tinycc/i386-asm.c1744
-rw-r--r--tinycc/i386-asm.h487
-rw-r--r--tinycc/i386-gen.c1140
-rw-r--r--tinycc/i386-link.c325
-rw-r--r--tinycc/i386-tok.h332
-rw-r--r--tinycc/il-gen.c657
-rw-r--r--tinycc/il-opcodes.h251
-rw-r--r--tinycc/include/float.h75
-rw-r--r--tinycc/include/stdalign.h16
-rw-r--r--tinycc/include/stdarg.h14
-rw-r--r--tinycc/include/stdatomic.h172
-rw-r--r--tinycc/include/stdbool.h11
-rw-r--r--tinycc/include/stddef.h41
-rw-r--r--tinycc/include/stdnoreturn.h7
-rw-r--r--tinycc/include/tccdefs.h325
-rw-r--r--tinycc/include/tgmath.h89
-rw-r--r--tinycc/include/varargs.h12
-rw-r--r--tinycc/lib/Makefile94
-rw-r--r--tinycc/lib/alloca-bt.S96
-rw-r--r--tinycc/lib/alloca.S85
-rw-r--r--tinycc/lib/armeabi.c544
-rw-r--r--tinycc/lib/armflush.c51
-rw-r--r--tinycc/lib/atomic.S858
-rw-r--r--tinycc/lib/bcheck.c2270
-rw-r--r--tinycc/lib/bt-dll.c74
-rw-r--r--tinycc/lib/bt-exe.c74
-rw-r--r--tinycc/lib/bt-log.c47
-rw-r--r--tinycc/lib/builtin.c164
-rw-r--r--tinycc/lib/dsohandle.c1
-rw-r--r--tinycc/lib/lib-arm64.c677
-rw-r--r--tinycc/lib/libtcc1.c641
-rw-r--r--tinycc/lib/stdatomic.c166
-rw-r--r--tinycc/lib/tcov.c428
-rw-r--r--tinycc/lib/va_list.c67
-rw-r--r--tinycc/libtcc.c2248
-rw-r--r--tinycc/libtcc.h111
-rw-r--r--tinycc/stab.def234
-rw-r--r--tinycc/stab.h17
-rw-r--r--tinycc/tcc-doc.texi1396
-rw-r--r--tinycc/tcc.c412
-rw-r--r--tinycc/tcc.h1937
-rw-r--r--tinycc/tccasm.c1363
-rw-r--r--tinycc/tcccoff.c951
-rw-r--r--tinycc/tccdbg.c2176
-rw-r--r--tinycc/tccelf.c3936
-rw-r--r--tinycc/tccgen.c8678
-rw-r--r--tinycc/tcclib.h80
-rw-r--r--tinycc/tccmacho.c2480
-rw-r--r--tinycc/tccpe.c2036
-rw-r--r--tinycc/tccpp.c3999
-rw-r--r--tinycc/tccrun.c1461
-rw-r--r--tinycc/tcctok.h420
-rw-r--r--tinycc/tcctools.c631
-rw-r--r--tinycc/texi2pod.pl427
-rw-r--r--tinycc/x86_64-asm.h544
-rw-r--r--tinycc/x86_64-gen.c2328
-rw-r--r--tinycc/x86_64-link.c403
70 files changed, 0 insertions, 57098 deletions
diff --git a/tinycc/.gitignore b/tinycc/.gitignore
deleted file mode 100644
index 3bff153..0000000
--- a/tinycc/.gitignore
+++ /dev/null
@@ -1,64 +0,0 @@
-*~
-\#*
-.#*
-*.o
-*.a
-*.exe
-*.dll
-*.obj
-*.pdb
-*.lib
-*.exp
-*.log
-*.bz2
-*.zip
-.gdb_history
-a.out
-tcc_g
-tcc
-*-tcc
-libtcc*.def
-
-config*.h
-*_.h
-config*.mak
-config.texi
-conftest*
-c2str
-tags
-TAGS
-tcc.1
-*.pod
-tcc-doc.html
-tcc-doc.info
-
-win32/doc
-win32/examples/libtcc_test.c
-win32/libtcc
-win32/lib/32
-win32/lib/64
-win32/include/float.h
-win32/include/stdalign.h
-win32/include/stdarg.h
-win32/include/stdbool.h
-win32/include/stddef.h
-win32/include/stdnoreturn.h
-win32/include/varargs.h
-win32/include/tcclib.h
-
-tests/tcctest[1234]
-tests/tcctest.gcc
-tests/*.out*
-tests/*.ref
-tests/*.txt
-tests/*.gcc
-tests/*-cc*
-tests/*-tcc*
-tests/libtcc_test
-tests/libtcc_test_mt
-tests/asm-c-connect
-tests/asm-c-connect-sep
-tests/vla_test
-tests/hello
-tests/tests2/fred.txt
-libtcc.dylib
diff --git a/tinycc/COPYING b/tinycc/COPYING
deleted file mode 100644
index 223ede7..0000000
--- a/tinycc/COPYING
+++ /dev/null
@@ -1,504 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it. You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it. And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that
-there is no warranty for the free library. Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License. We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom. The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
- We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License. It also provides other free software developers Less
-of an advantage over competing non-free programs. These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free
-library does the same job as widely used non-free libraries. In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software. For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
- Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library". The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
- A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
- The "Library", below, refers to any such software library or work
-which has been distributed under these terms. A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language. (Hereinafter, translation is
-included without limitation in the term "modification".)
-
- "Source code" for a work means the preferred form of the work for
-making modifications to it. For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
- Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it). Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
- 1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
- You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
- 2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) The modified work must itself be a software library.
-
- b) You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c) You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d) If a facility in the modified Library refers to a function or a
- table of data to be supplied by an application program that uses
- the facility, other than as an argument passed when the facility
- is invoked, then you must make a good faith effort to ensure that,
- in the event an application does not supply such function or
- table, the facility still operates, and performs whatever part of
- its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots has
- a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function must
- be optional: if the application does not supply it, the square
- root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library. To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License. (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.) Do not make any other change in
-these notices.
-
- Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library". Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
- However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library". The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
- When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library. The
-threshold for this to be true is not precisely defined by law.
-
- If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work. (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License. You must supply a copy of this License. If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License. Also, you must do one
-of these things:
-
- a) Accompany the work with the complete corresponding
- machine-readable source code for the Library including whatever
- changes were used in the work (which must be distributed under
- Sections 1 and 2 above); and, if the work is an executable linked
- with the Library, with the complete machine-readable "work that
- uses the Library", as object code and/or source code, so that the
- user can modify the Library and then relink to produce a modified
- executable containing the modified Library. (It is understood
- that the user who changes the contents of definitions files in the
- Library will not necessarily be able to recompile the application
- to use the modified definitions.)
-
- b) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run time a
- copy of the library already present on the user's computer system,
- rather than copying library functions into the executable, and (2)
- will operate properly with a modified version of the library, if
- the user installs one, as long as the modified version is
- interface-compatible with the version that the work was made with.
-
- c) Accompany the work with a written offer, valid for at
- least three years, to give the same user the materials
- specified in Subsection 6a, above, for a charge no more
- than the cost of performing this distribution.
-
- d) If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the above
- specified materials from the same place.
-
- e) Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it. However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
- It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system. Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
- 7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
- a) Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b) Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License. Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License. However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
- 9. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Library or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all. For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded. In such case, this License incorporates the limitation as if
-written in the body of this License.
-
- 13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation. If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission. For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this. Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Libraries
-
- If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
- To apply these terms, attach the following notices to the library. It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
- <one line to give the library's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
- <signature of Ty Coon>, 1 April 1990
- Ty Coon, President of Vice
-
-That's all there is to it!
-
-
diff --git a/tinycc/Changelog b/tinycc/Changelog
deleted file mode 100644
index 342484c..0000000
--- a/tinycc/Changelog
+++ /dev/null
@@ -1,456 +0,0 @@
-version 0.9.28:
-
-User interface:
-- new tcc -ar x and t flags (herman ten brugge)
-
-Platforms:
-- new RISC-V (riscv64) target
-- native macOS support for x86_64/arm64 (Herman ten Brugge)
-
-Features:
-- Improved support for C11
-- C11 _Static_assert support (matthias)
-
-Fixes:
-- fix preprocessor line (#line) directive (Herman ten Brugge)
-Many more! see also git shortlog release_0_9_27...HEAD
-
-Version 0.9.27:
-
-User interface:
-- -x[c|a|n] filetype option (Sergey Korshunoff)
-- -P[1], -dD, -dM preprocessor options (Sergey Korshunoff)
-- -Wl,-(no-)whole-archive linker option (Reuben Thomas)
-- -mms-bitfields option (David Mertens)
-- -include <file> option (Michael Matz)
-- -mno-sse on x86-64 disables use of SSE instructions
-- @listfile support (Vlad Vissoultchev)
-- tcc -ar/-impdef - formerly tiny_xxx tools integrated (grischka)
-- CPATH, C_INCLUDE_PATH and LIBRARY_PATH environment variables support
- (Andrew Aladjev, Urs Janssen)
-
-Platforms:
-- new AARCH64 (arm64) target (Edmund Grimley Evans)
-- vastly improved support for ARM hard float calling convention
- (Thomas Preud'homme, Daniel Glöckner)
-- provide a runtime library for ARM (Thomas Preud'homme)
-- many x86_64 ABI fixes incl. XMM register passing and tests (James Lyon)
-- ABI tests with native compiler using libtcc (James Lyon)
-- UNICODE startup code supports wmain and wWinMain (YX Hao)
-- shared libraries for x86_64 (Michael Matz)
-- Bootstrap native Windows 32/64 compiler using Cygwin+gcc (Christian Jullien)
-
-Features:
-- VLA (variable length array) improved (James Lyon, Pip Cet)
-- import functions by ordinal in .def files on windows (YX Hao)
-- x86/x86_64 assembler much improved (Michael Matz)
-- simple dead code suppression (Edmund Grimley Evans, Michael Matz, grischka)
-- implement round/fmin/fmax etc. math on windows (Avi Halachmi)
-- #pragma once support (Sergey Korshunoff, Vlad Vissoultchev, ...)
-- switch/case code improved (Zdenek Pavlas)
-- ~15% faster by TinyAlloc fast memory allocator (Vlad Vissoultchev)
-- standard conforming (and GCC compatible) struct initialization
- (Michael Matz)
-- bit-field layout made compatible with GCC (Michael Matz)
-- UTF8 in string literals supported (Zdenek Pavlas)
-_ _Generic(...) supported (Matthias Gatto)
-
-Licensing:
-- TinyCC partly relicensed to MIT license (See RELICENSING file).
-
-version 0.9.26:
-
-User interface:
-- -MD/-MF (automatically generate dependencies for make)
-- -pthread option (same as -D_REENTRANT -lpthread) (Henry Kroll III)
-- -m32/-m64 to re-exec cross compiler (Henry Kroll III)
-- -Wl, Mimic all GNU -option forms supported by ld (Kirill Smelkov)
-- new LIBTCCAPI tcc_set_options() (grischka)
-
-Platforms:
-- Many improvements for x86-64 target (Shinichiro Hamaji, Michael Matz, grischka)
-- x86-64 assembler (Frederic Feret)
-- Many improvements for ARM target (Daniel Glöckner, Thomas Preud'homme)
-- Support WinCE PE ARM (Timo VJ Lahde)
-- Support ARM hardfloat calling convention (Thomas Preud'homme)
-- Support SELinux (Security-Enhanced Linux) (Henry Kroll III)
-- Support Debian GNU/kFreeBSD kernels (Pierre Chifflier)
-- Support GNU/Hurd kernels (Thomas Preud'homme)
-- Support OSX (tcc -run only) (Milutin Jovanovic)
-- Support multiarch configuration (Thomas Preud'homme)
-- Support out-of-tree build (Akim Demaille)
-
-Features:
-- C99 variable length arrays (Thomas Preud'homme & Joe Soroka)
-- Asm labels for variables and functions (Thomas Preud'homme)
-- STT_GNU_IFUNC (Indirect functions as externals) (Thomas Preud'homme)
-- More tests (tests2) (Milutin Jovanovic)
-
-version 0.9.25:
-
-- first support for x86-64 target (Shinichiro Hamaji)
-- support µClibc
-- split tcc.c into tcc.h libtcc.c tccpp.c tccgen.c tcc.c
-- improved preprocess output with linenumbers and spaces preserved
-- tcc_relocate now copies code into user buffer
-- fix bitfields with non-int types and in unions
-- improve ARM cross-compiling (Daniel Glöckner)
-- link stabstr sections from multiple objects
-- better (still limited) support for multiple TCCStates
-
-version 0.9.24:
-
-- added verbosity levels -v, -vv, -vvv
-- Accept standard input as an inputstream (Hanzac Chen)
-- Support c89 compilers other than gcc (Hanzac Chen)
-- -soname linker option (Marc Andre Tanner)
-- Just warn about unknown directives, ignore quotes in #error/#warning
-- Define __STDC_VERSION__=199901L (477)
-- Switch to newer tccpe.c (includes support for resources)
-- Handle backslashes within #include/#error/#warning
-- Import changesets (part 4) 428,457,460,467: defines for openbsd etc.
-- Use _WIN32 for a windows hosted tcc and define it for the PE target,
- otherwise define __unix / __linux (Detlef Riekenberg)
-- Import changesets (part 3) 409,410: ARM EABI by Daniel Glöckner
-- Some in-between fixes:
- TCC -E no longer hangs with macro calls involving newlines.
- (next_nomacro1 now advances the read-pointer with TOK_LINEFEED)
- Global cast (int g_i = 1LL;) no longer crashes tcc.
- (nocode_wanted is initially 1, and only 0 for gen_function)
- On win32 now tcc.exe finds 'include' & 'lib' even if itself is in 'bin'.
- (new function w32_tcc_lib_path removes 'bin' if detected)
- Added quick build batch file for mingw (win32/build-tcc.bat)
- Last added case label optimization (455) produced wrong code. Reverted.
-
-- Import more changesets from Rob Landley's fork (part 2):
- 487: Handle long long constants in gen_opic() (Rob Landley)
- 484: Handle parentheses within __attribute__((...)) (Rob Landley)
- 480: Remove a goto in decl_initializer_alloc (Rob Landley)
- 475: Fix dereferences in inline assembly output (Joshua Phillips)
- 474: Cast ptrs to ints of different sizes correctly (Joshua Phillips)
- 473: Fix size of structs with empty array member (Joshua Phillips)
- 470: No warning for && and || with mixed pointers/integers (Rob Landley)
- 469: Fix symbol visibility problems in the linker (Vincent Pit)
- 468: Allow && and || involving pointer arguments (Rob Landley)
- 455: Optimize case labels with no code in between (Zdenek Pavlas)
- 450: Implement alloca for x86 (grischka)
- 415: Parse unicode escape sequences (Axel Liljencrantz)
- 407: Add a simple va_copy() in stdarg.h (Hasso Tepper)
- 400: Allow typedef names as symbols (Dave Dodge)
-
-- Import some changesets from Rob Landley's fork (part 1):
- 462: Use LGPL with bcheck.c and il-gen.c
- 458: Fix global compound literals (in unary: case '&':) (Andrew Johnson)
- 456: Use return code from tcc_output_file in main() (Michael Somos)
- 442: Fix indirections with function pointers (***fn)() (grischka)
- 441: Fix LL left shift in libtcc1.c:__shldi3 (grischka)
- 440: Pass structures and function ptrs through ?: (grischka)
- 439: Keep rvalue in bit assignment (bit2 = bit1 = x) (grischka)
- 438: Degrade nonportable pointer assignment to warning (grischka)
- 437: Call 'saveregs()' before jumping with logical and/or/not (grischka)
- 435: Put local static variables into global memory (grischka)
- 432/434: Cast double and ptr to bool (grischka)
- 420: Zero pad x87 tenbyte long doubles (Felix Nawothnig)
- 417: Make 'sizeof' unsigned (Rob Landley)
- 397: Fix save_reg for longlongs (Daniel Glöckner)
- 396: Fix "invalid relocation entry" problem on ubuntu - (Bernhard Fischer)
-
-- ignore AS_NEEDED ld command
-- mark executable sections as executable when running in memory
-- added support for win32 wchar_t (Filip Navara)
-- segment override prefix support (Filip Navara)
-- normalized slashes in paths (Filip Navara)
-- windows style fastcall (Filip Navara)
-- support for empty input register section in asm (Filip Navara)
-- anonymous union/struct support (Filip Navara)
-- fixed parsing of function parameters
-- workaround for function pointers in conditional expressions (Dave Dodge)
-- initial '-E' option support to use the C preprocessor alone
-- discard type qualifiers when comparing function parameters (Dave Dodge)
-- Bug fix: A long long value used as a test expression ignores the
- upper 32 bits at runtime (Dave Dodge)
-- fixed multiple concatenation of PPNUM tokens (initial patch by Dave Dodge)
-- fixed multiple typedef specifiers handling
-- fixed sign extension in some type conversions (Dave Dodge)
-
-version 0.9.23:
-
-- initial PE executable format for windows version (grischka)
-- '#pragma pack' support (grischka)
-- '#include_next' support (Bernhard Fischer)
-- ignore '-pipe' option
-- added -f[no-]leading-underscore
-- preprocessor function macro parsing fix (grischka)
-
-version 0.9.22:
-
-- simple memory optimisations: kernel compilation is 30% faster
-- linker symbol definitions fixes
-- gcc 3.4 fixes
-- fixed value stack full error
-- 'packed' attribute support for variables and structure fields
-- ignore 'const' and 'volatile' in function prototypes
-- allow '_Bool' in bit fields
-
-version 0.9.21:
-
-- ARM target support (Daniel Glöckner)
-- added '-funsigned-char, '-fsigned-char' and
- '-Wimplicit-function-declaration'
-- fixed assignment of const struct in struct
-- line comment fix (reported by Bertram Felgenhauer)
-- initial TMS320C67xx target support (TK)
-- win32 configure
-- regparm() attribute
-- many built-in assembler fixes
-- added '.org', '.fill' and '.previous' assembler directives
-- '-fno-common' option
-- '-Ttext' linker option
-- section alignment fixes
-- bit fields fixes
-- do not generate code for unused inline functions
-- '-oformat' linker option.
-- added 'binary' output format.
-
-version 0.9.20:
-
-- added '-w' option
-- added '.gnu.linkonce' ELF sections support
-- fixed libc linking when running in memory (avoid 'stat' function
- errors).
-- extended '-run' option to be able to give several arguments to a C
- script.
-
-version 0.9.19:
-
-- "alacarte" linking (Dave Long)
-- simpler function call
-- more strict type checks
-- added 'const' and 'volatile' support and associated warnings
-- added -Werror, -Wunsupported, -Wwrite-strings, -Wall.
-- added __builtin_types_compatible_p() and __builtin_constant_p()
-- chars support in assembler (Dave Long)
-- .string, .globl, .section, .text, .data and .bss asm directive
- support (Dave Long)
-- man page generated from tcc-doc.texi
-- fixed macro argument substitution
-- fixed zero argument macro parsing
-- changed license to LGPL
-- added -rdynamic option support
-
-version 0.9.18:
-
-- header fix (time.h)
-- fixed inline asm without operand case
-- fixed 'default:' or 'case x:' with '}' after (incorrect C construct accepted
- by gcc)
-- added 'A' inline asm constraint.
-
-version 0.9.17:
-
-- PLT generation fix
-- tcc doc fixes (Peter Lund)
-- struct parse fix (signaled by Pedro A. Aranda Gutierrez)
-- better _Bool lvalue support (signaled by Alex Measday)
-- function parameters must be converted to pointers (signaled by Neil Brown)
-- sanitized string and character constant parsing
-- fixed comment parse (signaled by Damian M Gryski)
-- fixed macro function bug (signaled by Philippe Ribet)
-- added configure (initial patch by Mitchell N Charity)
-- added '-run' and '-v' options (initial patch by vlindos)
-- added real date report in __DATE__ and __TIME__ macros
-
-version 0.9.16:
-
-- added assembler language support
-- added GCC inline asm() support
-- fixed multiple variable definitions : uninitialized variables are
- created as COMMON symbols.
-- optimized macro processing
-- added GCC statement expressions support
-- added GCC local labels support
-- fixed array declaration in old style function parameters
-- support casts in static structure initializations
-- added various __xxx[__] keywords for GCC compatibility
-- ignore __extension__ GCC in an expression or in a type (still not perfect)
-- added '? :' GCC extension support
-
-version 0.9.15:
-
-- compilation fixes for glibc 2.2, gcc 2.95.3 and gcc 3.2.
-- FreeBSD compile fixes. Makefile patches still missing (Carl Drougge).
-- fixed file type guessing if '.' is in the path.
-- fixed tcc_compile_string()
-- add a dummy page in ELF files to fix RX/RW accesses (pageexec at
- freemail dot hu).
-
-version 0.9.14:
-
-- added #warning. error message if invalid preprocessing directive.
-- added CType structure to ease typing (faster parse).
-- suppressed secondary hash tables (faster parse).
-- rewrote parser by optimizing common cases (faster parse).
-- fixed signed long long comparisons.
-- fixed 'int a(), b();' declaration case.
-- fixed structure init without '{}'.
-- correct alignment support in structures.
-- empty structures support.
-- gcc testsuite now supported.
-- output only warning if implicit integer/pointer conversions.
-- added static bitfield init.
-
-version 0.9.13:
-
-- correct preprocessing token pasting (## operator) in all cases (added
- preprocessing number token).
-- fixed long long register spill.
-- fixed signed long long '>>'.
-- removed memory leaks.
-- better error handling : processing can continue on link errors. A
- custom callback can be added to display error messages. Most
- errors do not call exit() now.
-- ignore -O, -W, -m and -f options
-- added old style function declarations
-- added GCC __alignof__ support.
-- added GCC typeof support.
-- added GCC computed gotos support.
-- added stack backtrace in runtime error message. Improved runtime
- error position display.
-
-version 0.9.12:
-
-- more fixes for || and && handling.
-- improved '? :' type handling.
-- fixed bound checking generation with structures
-- force '#endif' to be in same file as matching '#if'
-- #include file optimization with '#ifndef #endif' construct detection
-- macro handling optimization
-- added tcc_relocate() and tcc_get_symbol() in libtcc.
-
-version 0.9.11:
-
-- stdarg.h fix for double type (thanks to Philippe Ribet).
-- correct white space characters and added MSDOS newline support.
-- fixed invalid implicit function call type declaration.
-- special macros such as __LINE__ are defined if tested with defined().
-- fixed '!' operator with relocated address.
-- added symbol + offset relocation (fixes some static variable initializers)
-- '-l' option can be specified anywhere. '-c' option yields default
- output name. added '-r' option for relocatable output.
-- fixed '\nnn' octal parsing.
-- fixed local extern variables declarations.
-
-version 0.9.10:
-
-- fixed lvalue type when saved in local stack.
-- fixed '#include' syntax when using macros.
-- fixed '#line' bug.
-- removed size limit on strings. Unified string constants handling
- with variable declarations.
-- added correct support for '\xX' in wchar_t strings.
-- added support for bound checking in generated executables
-- fixed -I include order.
-- fixed incorrect function displayed in runtime error.
-
-version 0.9.9:
-
-- fixed preprocessor expression parsing for #if/#elif.
-- relocated debug info (.stab section).
-- relocated bounds info (.bounds section).
-- fixed cast to char of char constants ('\377' is -1 instead of 255)
-- fixed implicit cast for unary plus.
-- strings and '__func__' have now 'char[]' type instead of 'char *'
- (fixes sizeof() return value).
-- added __start_xxx and __stop_xxx symbols in linker.
-- better DLL creation support (option -shared begins to work).
-- ELF sections and hash tables are resized dynamically.
-- executables and DLLs are stripped by default.
-
-version 0.9.8:
-
-- First version of full ELF linking support (generate objects, static
- executable, dynamic executable, dynamic libraries). Dynamic library
- support is not finished (need PIC support in compiler and some
- patches in symbol exporting).
-- First version of ELF loader for object (.o) and archive (.a) files.
-- Support of simple GNU ld scripts (GROUP and FILE commands)
-- Separated runtime library and bound check code from TCC (smaller
- compiler core).
-- fixed register reload in float compare.
-- fixed implicit char/short to int casting.
-- allow array type for address of ('&') operator.
-- fixed unused || or && result.
-- added GCC style variadic macro support.
-- optimized bound checking code for array access.
-- tcc includes are now in $(prefix)/lib/tcc/include.
-- more command line options - more consistent handling of multiple
- input files.
-- added tcc man page (thanks to Cyril Bouthors).
-- uClibc Makefile update
-- converted documentation to texinfo format.
-- added developper's guide in documentation.
-
-version 0.9.7:
-
-- added library API for easy dynamic compilation (see libtcc.h - first
- draft).
-- fixed long long register spill bug.
-- fixed '? :' register spill bug.
-
-version 0.9.6:
-
-- added floating point constant propagation (fixes negative floating
- point constants bug).
-
-version 0.9.5:
-
- - uClibc patches (submitted by Alfonso Martone).
- - error reporting fix
- - added CONFIG_TCC_BCHECK to get smaller code if needed.
-
-version 0.9.4:
-
- - windows port (currently cannot use -g, -b and dll functions).
- - faster and simpler I/O handling.
- - '-D' option works in all cases.
- - preprocessor fixes (#elif and empty macro args)
- - floating point fixes
- - first code for CIL generation (does not work yet)
-
-version 0.9.3:
-
- - better and smaller code generator.
- - full ISOC99 64 bit 'long long' support.
- - full 32 bit 'float', 64 bit 'double' and 96 bit 'long double' support.
- - added '-U' option.
- - added assembly sections support.
- - even faster startup time by mmaping sections instead of mallocing them.
- - added GNUC __attribute__ keyword support (currently supports
- 'section' and 'aligned' attributes).
- - added ELF file output (only usable for debugging now)
- - added debug symbol generation (STAB format).
- - added integrated runtime error analysis ('-g' option: print clear
- run time error messages instead of "Segmentation fault").
- - added first version of tiny memory and bound checker ('-b' option).
-
-version 0.9.2:
-
- - even faster parsing.
- - various syntax parsing fixes.
- - fixed external relocation handling for variables or functions pointers.
- - better function pointers type handling.
- - can compile multiple files (-i option).
- - ANSI C bit fields are supported.
- - beginning of float/double/long double support.
- - beginning of long long support.
-
-version 0.9.1:
-
- - full ISOC99 initializers handling.
- - compound literals.
- - structures handle in assignments and as function param or return value.
- - wide chars and strings.
- - macro bug fix
-
-version 0.9:
- - initial version.
diff --git a/tinycc/CodingStyle b/tinycc/CodingStyle
deleted file mode 100644
index 93d1324..0000000
--- a/tinycc/CodingStyle
+++ /dev/null
@@ -1,71 +0,0 @@
-
-In general, use the same coding style as the surrounding code.
-
-However, do not make any unnecessary changes as that complicates
-the VCS (git) history and makes it harder to merge patches. So
-do not modify code just to make it conform to a coding style.
-
- Indentation
-
-Turn on a "fill tabs with spaces" option in your editor.
-
-Remove tabs and trailing spaces from any lines that are modified.
-
-Note that some files are indented with 2 spaces (when they
-have large indentation) while most are indented with 4 spaces.
-
- Language
-
-TCC is mostly implemented in C90. Do not use any non-C90 features
-that are not already in use.
-
-Non-C90 features currently in use, as revealed by
-./configure --extra-cflags="-std=c90 -Wpedantic":
-
-- long long (including "LL" constants)
-- inline
-- very long string constants
-- assignment between function pointer and 'void *'
-- "//" comments
-- empty macro arguments (DEF_ASMTEST in i386-tok.h)
-- unnamed struct and union fields (in struct Sym), a C11 feature
-
- Testing
-
-A simple "make test" is sufficient for some simple changes. However,
-before committing a change consider performing some of the following
-additional tests:
-
-- Build and run "make test" on several architectures.
-
-- Build with ./configure --enable-cross.
-
-- If the generation of relocations has been changed, try compiling
- with TCC and linking with GCC/Clang. If the linker has been
- modified, try compiling with GCC/Clang and linking with TCC.
-
-- Test with ASan/UBSan to detect memory corruption and undefined behaviour:
-
-make clean
-./configure
-make
-make test
-cp libtcc.a libtcc.a.hide
-
-make clean
-./configure --extra-cflags="-fsanitize=address,undefined -g"
-make
-cp libtcc.a.hide libtcc.a
-make test
-
-- Test with Valgrind to detect some uses of uninitialised values:
-
-make clean
-./configure
-make
-# On Intel, because Valgrind does floating-point arithmetic differently:
-( cd tests && gcc -I.. tcctest.c && valgrind -q ./a.out > test.ref )
-make test TCC="valgrind -q --leak-check=full `pwd`/tcc -B`pwd` -I`pwd`"
-
- (Because of how VLAs are implemented, invalid reads are expected
- with 79_vla_continue.)
diff --git a/tinycc/README b/tinycc/README
deleted file mode 100644
index 809dd8d..0000000
--- a/tinycc/README
+++ /dev/null
@@ -1,96 +0,0 @@
-Tiny C Compiler - C Scripting Everywhere - The Smallest ANSI C compiler
------------------------------------------------------------------------
-
-Features:
---------
-
-- SMALL! You can compile and execute C code everywhere, for example on
- rescue disks.
-
-- FAST! tcc generates optimized x86 code. No byte code
- overhead. Compile, assemble and link about 7 times faster than 'gcc
- -O0'.
-
-- UNLIMITED! Any C dynamic library can be used directly. TCC is
- heading toward full ISOC99 compliance. TCC can of course compile
- itself.
-
-- SAFE! tcc includes an optional memory and bound checker. Bound
- checked code can be mixed freely with standard code.
-
-- Compile and execute C source directly. No linking or assembly
- necessary. Full C preprocessor included.
-
-- C script supported : just add '#!/usr/local/bin/tcc -run' at the first
- line of your C source, and execute it directly from the command
- line.
-
-Documentation:
--------------
-
-1) Installation on a i386/x86_64/arm/aarch64/riscv64
- Linux/macOS/FreeBSD/NetBSD/OpenBSD hosts.
-
- ./configure
- make
- make test
- make install
-
- Notes: For FreeBSD, NetBSD and OpenBSD, gmake should be used instead of make.
- For Windows read tcc-win32.txt.
-
-makeinfo must be installed to compile the doc. By default, tcc is
-installed in /usr/local/bin. ./configure --help shows configuration
-options.
-
-
-2) Introduction
-
-We assume here that you know ANSI C. Look at the example ex1.c to know
-what the programs look like.
-
-The include file <tcclib.h> can be used if you want a small basic libc
-include support (especially useful for floppy disks). Of course, you
-can also use standard headers, although they are slower to compile.
-
-You can begin your C script with '#!/usr/local/bin/tcc -run' on the first
-line and set its execute bits (chmod a+x your_script). Then, you can
-launch the C code as a shell or perl script :-) The command line
-arguments are put in 'argc' and 'argv' of the main functions, as in
-ANSI C.
-
-3) Examples
-
-ex1.c: simplest example (hello world). Can also be launched directly
-as a script: './ex1.c'.
-
-ex2.c: more complicated example: find a number with the four
-operations given a list of numbers (benchmark).
-
-ex3.c: compute fibonacci numbers (benchmark).
-
-ex4.c: more complicated: X11 program. Very complicated test in fact
-because standard headers are being used ! As for ex1.c, can also be launched
-directly as a script: './ex4.c'.
-
-ex5.c: 'hello world' with standard glibc headers.
-
-tcc.c: TCC can of course compile itself. Used to check the code
-generator.
-
-tcctest.c: auto test for TCC which tests many subtle possible bugs. Used
-when doing 'make test'.
-
-4) Full Documentation
-
-Please read tcc-doc.html to have all the features of TCC.
-
-Additional information is available for the Windows port in tcc-win32.txt.
-
-License:
--------
-
-TCC is distributed under the GNU Lesser General Public License (see
-COPYING file).
-
-Fabrice Bellard.
diff --git a/tinycc/RELICENSING b/tinycc/RELICENSING
deleted file mode 100644
index 6c69612..0000000
--- a/tinycc/RELICENSING
+++ /dev/null
@@ -1,63 +0,0 @@
-
- Relicensing TinyCC
- ------------------
-
- The authors listed below hereby confirm their agreement to relicense TinyCC
- including their past contributions under the following terms:
-
-
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
-
-
- Author (name) I agree (YES/NO) Files/Features (optional)
- ------------------------------------------------------------------------------
- Adam Sampson YES makefiles
- Daniel Glöckner NO arm-gen.c
- Daniel Glöckner YES not arm-gen.c
- Danny Milosavljevic YES arm-asm.c riscv64-asm.c
- Edmund Grimley Evans YES arm64
- Fabrice Bellard YES original author
- Frédéric Féret YES x86 64/16 bit asm
- grischka YES tccpe.c
- Henry Kroll YES
- Herman ten Brugge YES
- Joe Soroka YES
- Kirill Smelkov YES
- mingodad YES
- Pip Cet YES
- Shinichiro Hamaji YES x86_64-gen.c
- Vincent Lefèvre YES
- Thomas Preud'homme YES arm-gen.c
- Timo VJ Lähde (Timppa) ? tiny_libmaker.c
- TK ? tcccoff.c c67-gen.c
- Tyge Løvset YES tgmath.h, Windows tcc_libm.h math.h
- Urs Janssen YES
- waddlesplash YES
- Christian Jullien YES Windows Cygwin build and tests
-
-
- ------------------------------------------------------------------------------
-
- Please add yourself to the list above (rsp. replace the question mark)
- and (after fetching the latest version) commit to the "mob" branch with
- commit message:
-
- Relicensing TinyCC
-
- Thanks.
diff --git a/tinycc/TODO b/tinycc/TODO
deleted file mode 100644
index 9a38b6b..0000000
--- a/tinycc/TODO
+++ /dev/null
@@ -1,106 +0,0 @@
-TODO list:
-
-Releases:
-- release tcc on a regular basis (which interval? 3 months?)
-
-Bugs:
-
-- i386 fastcall is mostly wrong
-- FPU st(0) is left unclean (kwisatz haderach). Incompatible with
- optimized gcc/msc code
-- see transparent union pb in /urs/include/sys/socket.h
-- precise behaviour of typeof with arrays ? (__put_user macro)
- but should suffice for most cases)
-- handle '? x, y : z' in unsized variable initialization (',' is
- considered incorrectly as separator in preparser)
-- transform functions to function pointers in function parameters
- (net/ipv4/ip_output.c)
-- fix function pointer type display
-- check section alignment in C
-- fix invalid cast in comparison 'if (v == (int8_t)v)'
-- finish varargs.h support (gcc 3.2 testsuite issue)
-- fix static functions declared inside block
-- fix multiple unions init
-- make libtcc fully reentrant (except for the compilation stage itself).
-- struct/union/enum definitions in nested scopes (see also Debian bug #770657)
-- __STDC_IEC_559__: float f(void) { static float x = 0.0 / 0.0; return x; }
-- memory may be leaked after errors (longjmp).
-
-Portability:
-
-- it is assumed that int is 32-bit and sizeof(int) == 4
-- int is used when host or target size_t would make more sense
-- TCC handles target floating-point (fp) values using the host's fp
- arithmetic, which is simple and fast but may lead to exceptions
- and inaccuracy and wrong representations when cross-compiling
-
-Linking:
-
-- static linking (-static) does sort of work
- works with musl libc
- glibc requires libc.so even when statically linked (very bad, but not
- up to tcc)
-
-Bound checking:
-
-- fix bound exit on RedHat 7.3
-- setjmp is not supported properly in bound checking.
-- fix bound check code with '&' on local variables (currently done
- only for local arrays).
-- bound checking and float/long long/struct copy code. bound
- checking and symbol + offset optimization
-
-Missing features:
-
-- disable-asm and disable-bcheck options
-- __builtin_expect()
-- atexit (Nigel Horne)
-- C99: add complex types (gcc 3.2 testsuite issue)
-- postfix compound literals (see 20010124-1.c)
-- interactive mode / integrated debugger
-
-Optimizations:
-
-- suppress specific anonymous symbol handling
-- more parse optimizations (=even faster compilation)
-- memory alloc optimizations (=even faster compilation)
-- optimize VT_LOCAL + const
-- better local variables handling (needed for other targets)
-
-Not critical:
-
-- C99: fix multiple compound literals inits in blocks (ISOC99
- normative example - only relevant when using gotos! -> must add
- boolean variable to tell if compound literal was already
- initialized).
-- add PowerPC generator and improve codegen for RISC (need
- to suppress VT_LOCAL and use a base register instead).
-- fix preprocessor symbol redefinition
-- add portable byte code generator and interpreter for other
- unsupported architectures.
-- C++: variable declaration in for, minimal 'class' support.
-- win32: __intxx. use resolve for bchecked malloc et al.
- check exception code (exception filter func).
-- handle void (__attribute__() *ptr)()
-- VLAs are implemented in a way that is not compatible with signals:
- http://lists.gnu.org/archive/html/tinycc-devel/2015-11/msg00018.html
-
-Fixed (probably):
-
-- bug with defines:
- #define spin_lock(lock) do { } while (0)
- #define wq_spin_lock spin_lock
- #define TEST() wq_spin_lock(a)
-- typedefs can be structure fields
-- see bugfixes.diff + improvement.diff from Daniel Glockner
-- long long constant evaluation
-- add alloca()
-- gcc '-E' option.
-- #include_next support for /usr/include/limits ?
-- function pointers/lvalues in ? : (linux kernel net/core/dev.c)
-- win32: add __stdcall, check GetModuleHandle for dlls.
-- macro substitution with nested definitions (ShangHongzhang)
-- with "-run" and libtcc, a PLT is now built.
-- '-E' option was improved
-- packed attribute is now supported
-- ARM and ARM64 code generators have been added.
diff --git a/tinycc/USES b/tinycc/USES
deleted file mode 100644
index 6d7a2d1..0000000
--- a/tinycc/USES
+++ /dev/null
@@ -1,20 +0,0 @@
-The following software are known to use or support tcc builds.
-Feel free to complete this list (*).
-
-Name Short Description
----- -----------------
-bigz An infinite precision Z & Q library.
-gawk GNU awk.
-gmp Library for arbitrary precision arithmetic.
-gnumake GNU makefile.
-mpfr Multiple-precision floating-point library.
-mpc Complex floating-point library with exact rounding.
-mpv A free, open source, and cross-platform media player.
-openlisp ISLISP ISO/IEC 13816 Lisp interpreter and compiler.
-s-nail BSD Mail/POSIX mailx: send and receive Internet mail.
-sqlite Embbedable SQL engine.
-st Simple Terminal.
-tcc Tiny CC which compiles itself.
-zlib Lossless data-compression library.
-
-(*) This list is ordered by name.
diff --git a/tinycc/VERSION b/tinycc/VERSION
deleted file mode 100644
index 9a54223..0000000
--- a/tinycc/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-0.9.27
diff --git a/tinycc/coff.h b/tinycc/coff.h
deleted file mode 100644
index e8e6185..0000000
--- a/tinycc/coff.h
+++ /dev/null
@@ -1,446 +0,0 @@
-/**************************************************************************/
-/* COFF.H */
-/* COFF data structures and related definitions used by the linker */
-/**************************************************************************/
-
-/*------------------------------------------------------------------------*/
-/* COFF FILE HEADER */
-/*------------------------------------------------------------------------*/
-struct filehdr {
- unsigned short f_magic; /* magic number */
- unsigned short f_nscns; /* number of sections */
- long f_timdat; /* time & date stamp */
- long f_symptr; /* file pointer to symtab */
- long f_nsyms; /* number of symtab entries */
- unsigned short f_opthdr; /* sizeof(optional hdr) */
- unsigned short f_flags; /* flags */
- unsigned short f_TargetID; /* for C6x = 0x0099 */
- };
-
-/*------------------------------------------------------------------------*/
-/* File header flags */
-/*------------------------------------------------------------------------*/
-#define F_RELFLG 0x01 /* relocation info stripped from file */
-#define F_EXEC 0x02 /* file is executable (no unresolved refs) */
-#define F_LNNO 0x04 /* line numbers stripped from file */
-#define F_LSYMS 0x08 /* local symbols stripped from file */
-#define F_GSP10 0x10 /* 34010 version */
-#define F_GSP20 0x20 /* 34020 version */
-#define F_SWABD 0x40 /* bytes swabbed (in names) */
-#define F_AR16WR 0x80 /* byte ordering of an AR16WR (PDP-11) */
-#define F_LITTLE 0x100 /* byte ordering of an AR32WR (vax) */
-#define F_BIG 0x200 /* byte ordering of an AR32W (3B, maxi) */
-#define F_PATCH 0x400 /* contains "patch" list in optional header */
-#define F_NODF 0x400
-
-#define F_VERSION (F_GSP10 | F_GSP20)
-#define F_BYTE_ORDER (F_LITTLE | F_BIG)
-#define FILHDR struct filehdr
-
-/* #define FILHSZ sizeof(FILHDR) */
-#define FILHSZ 22 /* above rounds to align on 4 bytes which causes problems */
-
-#define COFF_C67_MAGIC 0x00c2
-
-/*------------------------------------------------------------------------*/
-/* Macros to recognize magic numbers */
-/*------------------------------------------------------------------------*/
-#define ISMAGIC(x) (((unsigned short)(x))==(unsigned short)magic)
-#define ISARCHIVE(x) ((((unsigned short)(x))==(unsigned short)ARTYPE))
-#define BADMAGIC(x) (((unsigned short)(x) & 0x8080) && !ISMAGIC(x))
-
-
-/*------------------------------------------------------------------------*/
-/* OPTIONAL FILE HEADER */
-/*------------------------------------------------------------------------*/
-typedef struct aouthdr {
- short magic; /* see magic.h */
- short vstamp; /* version stamp */
- long tsize; /* text size in bytes, padded to FW bdry*/
- long dsize; /* initialized data " " */
- long bsize; /* uninitialized data " " */
- long entrypt; /* entry pt. */
- long text_start; /* base of text used for this file */
- long data_start; /* base of data used for this file */
-} AOUTHDR;
-
-#define AOUTSZ sizeof(AOUTHDR)
-
-/*----------------------------------------------------------------------*/
-/* When a UNIX aout header is to be built in the optional header, */
-/* the following magic numbers can appear in that header: */
-/* */
-/* AOUT1MAGIC : default : readonly sharable text segment */
-/* AOUT2MAGIC: : writable text segment */
-/* PAGEMAGIC : : configured for paging */
-/*----------------------------------------------------------------------*/
-#define AOUT1MAGIC 0410
-#define AOUT2MAGIC 0407
-#define PAGEMAGIC 0413
-
-
-/*------------------------------------------------------------------------*/
-/* COMMON ARCHIVE FILE STRUCTURES */
-/* */
-/* ARCHIVE File Organization: */
-/* _______________________________________________ */
-/* |__________ARCHIVE_MAGIC_STRING_______________| */
-/* |__________ARCHIVE_FILE_MEMBER_1______________| */
-/* | | */
-/* | Archive File Header "ar_hdr" | */
-/* |.............................................| */
-/* | Member Contents | */
-/* | 1. External symbol directory | */
-/* | 2. Text file | */
-/* |_____________________________________________| */
-/* |________ARCHIVE_FILE_MEMBER_2________________| */
-/* | "ar_hdr" | */
-/* |.............................................| */
-/* | Member Contents (.o or text file) | */
-/* |_____________________________________________| */
-/* | . . . | */
-/* | . . . | */
-/* | . . . | */
-/* |_____________________________________________| */
-/* |________ARCHIVE_FILE_MEMBER_n________________| */
-/* | "ar_hdr" | */
-/* |.............................................| */
-/* | Member Contents | */
-/* |_____________________________________________| */
-/* */
-/*------------------------------------------------------------------------*/
-
-#define COFF_ARMAG "!<arch>\n"
-#define SARMAG 8
-#define ARFMAG "`\n"
-
-struct ar_hdr /* archive file member header - printable ascii */
-{
- char ar_name[16]; /* file member name - `/' terminated */
- char ar_date[12]; /* file member date - decimal */
- char ar_uid[6]; /* file member user id - decimal */
- char ar_gid[6]; /* file member group id - decimal */
- char ar_mode[8]; /* file member mode - octal */
- char ar_size[10]; /* file member size - decimal */
- char ar_fmag[2]; /* ARFMAG - string to end header */
-};
-
-
-/*------------------------------------------------------------------------*/
-/* SECTION HEADER */
-/*------------------------------------------------------------------------*/
-struct scnhdr {
- char s_name[8]; /* section name */
- long s_paddr; /* physical address */
- long s_vaddr; /* virtual address */
- long s_size; /* section size */
- long s_scnptr; /* file ptr to raw data for section */
- long s_relptr; /* file ptr to relocation */
- long s_lnnoptr; /* file ptr to line numbers */
- unsigned int s_nreloc; /* number of relocation entries */
- unsigned int s_nlnno; /* number of line number entries */
- unsigned int s_flags; /* flags */
- unsigned short s_reserved; /* reserved byte */
- unsigned short s_page; /* memory page id */
- };
-
-#define SCNHDR struct scnhdr
-#define SCNHSZ sizeof(SCNHDR)
-
-/*------------------------------------------------------------------------*/
-/* Define constants for names of "special" sections */
-/*------------------------------------------------------------------------*/
-/* #define _TEXT ".text" */
-#define _DATA ".data"
-#define _BSS ".bss"
-#define _CINIT ".cinit"
-#define _TV ".tv"
-
-/*------------------------------------------------------------------------*/
-/* The low 4 bits of s_flags is used as a section "type" */
-/*------------------------------------------------------------------------*/
-#define STYP_REG 0x00 /* "regular" : allocated, relocated, loaded */
-#define STYP_DSECT 0x01 /* "dummy" : not allocated, relocated, not loaded */
-#define STYP_NOLOAD 0x02 /* "noload" : allocated, relocated, not loaded */
-#define STYP_GROUP 0x04 /* "grouped" : formed of input sections */
-#define STYP_PAD 0x08 /* "padding" : not allocated, not relocated, loaded */
-#define STYP_COPY 0x10 /* "copy" : used for C init tables -
- not allocated, relocated,
- loaded; reloc & lineno
- entries processed normally */
-#define STYP_TEXT 0x20 /* section contains text only */
-#define STYP_DATA 0x40 /* section contains data only */
-#define STYP_BSS 0x80 /* section contains bss only */
-
-#define STYP_ALIGN 0x100 /* align flag passed by old version assemblers */
-#define ALIGN_MASK 0x0F00 /* part of s_flags that is used for align vals */
-#define ALIGNSIZE(x) (1 << ((x & ALIGN_MASK) >> 8))
-
-
-/*------------------------------------------------------------------------*/
-/* RELOCATION ENTRIES */
-/*------------------------------------------------------------------------*/
-struct reloc
-{
- long r_vaddr; /* (virtual) address of reference */
- short r_symndx; /* index into symbol table */
- unsigned short r_disp; /* additional bits for address calculation */
- unsigned short r_type; /* relocation type */
-};
-
-#define RELOC struct reloc
-#define RELSZ 10 /* sizeof(RELOC) */
-
-/*--------------------------------------------------------------------------*/
-/* define all relocation types */
-/*--------------------------------------------------------------------------*/
-
-#define R_ABS 0 /* absolute address - no relocation */
-#define R_DIR16 01 /* UNUSED */
-#define R_REL16 02 /* UNUSED */
-#define R_DIR24 04 /* UNUSED */
-#define R_REL24 05 /* 24 bits, direct */
-#define R_DIR32 06 /* UNUSED */
-#define R_RELBYTE 017 /* 8 bits, direct */
-#define R_RELWORD 020 /* 16 bits, direct */
-#define R_RELLONG 021 /* 32 bits, direct */
-#define R_PCRBYTE 022 /* 8 bits, PC-relative */
-#define R_PCRWORD 023 /* 16 bits, PC-relative */
-#define R_PCRLONG 024 /* 32 bits, PC-relative */
-#define R_OCRLONG 030 /* GSP: 32 bits, one's complement direct */
-#define R_GSPPCR16 031 /* GSP: 16 bits, PC relative (in words) */
-#define R_GSPOPR32 032 /* GSP: 32 bits, direct big-endian */
-#define R_PARTLS16 040 /* Brahma: 16 bit offset of 24 bit address*/
-#define R_PARTMS8 041 /* Brahma: 8 bit page of 24 bit address */
-#define R_PARTLS7 050 /* DSP: 7 bit offset of 16 bit address */
-#define R_PARTMS9 051 /* DSP: 9 bit page of 16 bit address */
-#define R_REL13 052 /* DSP: 13 bits, direct */
-
-
-/*------------------------------------------------------------------------*/
-/* LINE NUMBER ENTRIES */
-/*------------------------------------------------------------------------*/
-struct lineno
-{
- union
- {
- long l_symndx ; /* sym. table index of function name
- iff l_lnno == 0 */
- long l_paddr ; /* (physical) address of line number */
- } l_addr ;
- unsigned short l_lnno ; /* line number */
-};
-
-#define LINENO struct lineno
-#define LINESZ 6 /* sizeof(LINENO) */
-
-
-/*------------------------------------------------------------------------*/
-/* STORAGE CLASSES */
-/*------------------------------------------------------------------------*/
-#define C_EFCN -1 /* physical end of function */
-#define C_NULL 0
-#define C_AUTO 1 /* automatic variable */
-#define C_EXT 2 /* external symbol */
-#define C_STAT 3 /* static */
-#define C_REG 4 /* register variable */
-#define C_EXTDEF 5 /* external definition */
-#define C_LABEL 6 /* label */
-#define C_ULABEL 7 /* undefined label */
-#define C_MOS 8 /* member of structure */
-#define C_ARG 9 /* function argument */
-#define C_STRTAG 10 /* structure tag */
-#define C_MOU 11 /* member of union */
-#define C_UNTAG 12 /* union tag */
-#define C_TPDEF 13 /* type definition */
-#define C_USTATIC 14 /* undefined static */
-#define C_ENTAG 15 /* enumeration tag */
-#define C_MOE 16 /* member of enumeration */
-#define C_REGPARM 17 /* register parameter */
-#define C_FIELD 18 /* bit field */
-
-#define C_BLOCK 100 /* ".bb" or ".eb" */
-#define C_FCN 101 /* ".bf" or ".ef" */
-#define C_EOS 102 /* end of structure */
-#define C_FILE 103 /* file name */
-#define C_LINE 104 /* dummy sclass for line number entry */
-#define C_ALIAS 105 /* duplicate tag */
-#define C_HIDDEN 106 /* special storage class for external */
- /* symbols in dmert public libraries */
-
-/*------------------------------------------------------------------------*/
-/* SYMBOL TABLE ENTRIES */
-/*------------------------------------------------------------------------*/
-
-#define SYMNMLEN 8 /* Number of characters in a symbol name */
-#define FILNMLEN 14 /* Number of characters in a file name */
-#define DIMNUM 4 /* Number of array dimensions in auxiliary entry */
-
-
-struct syment
-{
- union
- {
- char _n_name[SYMNMLEN]; /* old COFF version */
- struct
- {
- long _n_zeroes; /* new == 0 */
- long _n_offset; /* offset into string table */
- } _n_n;
- char *_n_nptr[2]; /* allows for overlaying */
- } _n;
- long n_value; /* value of symbol */
- short n_scnum; /* section number */
- unsigned short n_type; /* type and derived type */
- char n_sclass; /* storage class */
- char n_numaux; /* number of aux. entries */
-};
-
-#define n_name _n._n_name
-#define n_nptr _n._n_nptr[1]
-#define n_zeroes _n._n_n._n_zeroes
-#define n_offset _n._n_n._n_offset
-
-/*------------------------------------------------------------------------*/
-/* Relocatable symbols have a section number of the */
-/* section in which they are defined. Otherwise, section */
-/* numbers have the following meanings: */
-/*------------------------------------------------------------------------*/
-#define N_UNDEF 0 /* undefined symbol */
-#define N_ABS -1 /* value of symbol is absolute */
-#define N_DEBUG -2 /* special debugging symbol */
-#define N_TV (unsigned short)-3 /* needs transfer vector (preload) */
-#define P_TV (unsigned short)-4 /* needs transfer vector (postload) */
-
-
-/*------------------------------------------------------------------------*/
-/* The fundamental type of a symbol packed into the low */
-/* 4 bits of the word. */
-/*------------------------------------------------------------------------*/
-#define _EF ".ef"
-
-#define T_NULL 0 /* no type info */
-#define T_ARG 1 /* function argument (only used by compiler) */
-#define T_CHAR 2 /* character */
-#define T_SHORT 3 /* short integer */
-#define T_INT 4 /* integer */
-#define T_LONG 5 /* long integer */
-#define T_FLOAT 6 /* floating point */
-#define T_DOUBLE 7 /* double word */
-#define T_STRUCT 8 /* structure */
-#define T_UNION 9 /* union */
-#define T_ENUM 10 /* enumeration */
-#define T_MOE 11 /* member of enumeration */
-#define T_UCHAR 12 /* unsigned character */
-#define T_USHORT 13 /* unsigned short */
-#define T_UINT 14 /* unsigned integer */
-#define T_ULONG 15 /* unsigned long */
-
-/*------------------------------------------------------------------------*/
-/* derived types are: */
-/*------------------------------------------------------------------------*/
-#define DT_NON 0 /* no derived type */
-#define DT_PTR 1 /* pointer */
-#define DT_FCN 2 /* function */
-#define DT_ARY 3 /* array */
-
-#define MKTYPE(basic, d1,d2,d3,d4,d5,d6) \
- ((basic) | ((d1) << 4) | ((d2) << 6) | ((d3) << 8) |\
- ((d4) << 10) | ((d5) << 12) | ((d6) << 14))
-
-/*------------------------------------------------------------------------*/
-/* type packing constants and macros */
-/*------------------------------------------------------------------------*/
-#define N_BTMASK_COFF 017
-#define N_TMASK_COFF 060
-#define N_TMASK1_COFF 0300
-#define N_TMASK2_COFF 0360
-#define N_BTSHFT_COFF 4
-#define N_TSHIFT_COFF 2
-
-#define BTYPE_COFF(x) ((x) & N_BTMASK_COFF)
-#define ISINT(x) (((x) >= T_CHAR && (x) <= T_LONG) || \
- ((x) >= T_UCHAR && (x) <= T_ULONG) || (x) == T_ENUM)
-#define ISFLT_COFF(x) ((x) == T_DOUBLE || (x) == T_FLOAT)
-#define ISPTR_COFF(x) (((x) & N_TMASK_COFF) == (DT_PTR << N_BTSHFT_COFF))
-#define ISFCN_COFF(x) (((x) & N_TMASK_COFF) == (DT_FCN << N_BTSHFT_COFF))
-#define ISARY_COFF(x) (((x) & N_TMASK_COFF) == (DT_ARY << N_BTSHFT_COFF))
-#define ISTAG_COFF(x) ((x)==C_STRTAG || (x)==C_UNTAG || (x)==C_ENTAG)
-
-#define INCREF_COFF(x) ((((x)&~N_BTMASK_COFF)<<N_TSHIFT_COFF)|(DT_PTR<<N_BTSHFT_COFF)|(x&N_BTMASK_COFF))
-#define DECREF_COFF(x) ((((x)>>N_TSHIFT_COFF)&~N_BTMASK_COFF)|((x)&N_BTMASK_COFF))
-
-
-/*------------------------------------------------------------------------*/
-/* AUXILIARY SYMBOL ENTRY */
-/*------------------------------------------------------------------------*/
-union auxent
-{
- struct
- {
- long x_tagndx; /* str, un, or enum tag indx */
- union
- {
- struct
- {
- unsigned short x_lnno; /* declaration line number */
- unsigned short x_size; /* str, union, array size */
- } x_lnsz;
- long x_fsize; /* size of function */
- } x_misc;
- union
- {
- struct /* if ISFCN, tag, or .bb */
- {
- long x_lnnoptr; /* ptr to fcn line # */
- long x_endndx; /* entry ndx past block end */
- } x_fcn;
- struct /* if ISARY, up to 4 dimen. */
- {
- unsigned short x_dimen[DIMNUM];
- } x_ary;
- } x_fcnary;
- unsigned short x_regcount; /* number of registers used by func */
- } x_sym;
- struct
- {
- char x_fname[FILNMLEN];
- } x_file;
- struct
- {
- long x_scnlen; /* section length */
- unsigned short x_nreloc; /* number of relocation entries */
- unsigned short x_nlinno; /* number of line numbers */
- } x_scn;
-};
-
-#define SYMENT struct syment
-#define SYMESZ 18 /* sizeof(SYMENT) */
-
-#define AUXENT union auxent
-#define AUXESZ 18 /* sizeof(AUXENT) */
-
-/*------------------------------------------------------------------------*/
-/* NAMES OF "SPECIAL" SYMBOLS */
-/*------------------------------------------------------------------------*/
-#define _STEXT ".text"
-#define _ETEXT "etext"
-#define _SDATA ".data"
-#define _EDATA "edata"
-#define _SBSS ".bss"
-#define _END "end"
-#define _CINITPTR "cinit"
-
-/*--------------------------------------------------------------------------*/
-/* ENTRY POINT SYMBOLS */
-/*--------------------------------------------------------------------------*/
-#define _START "_start"
-#define _MAIN "_main"
- /* _CSTART "_c_int00" (defined in params.h) */
-
-
-#define _TVORIG "_tvorig"
-#define _TORIGIN "_torigin"
-#define _DORIGIN "_dorigin"
-
-#define _SORIGIN "_sorigin"
diff --git a/tinycc/configure b/tinycc/configure
deleted file mode 100644
index 6ec98f3..0000000
--- a/tinycc/configure
+++ /dev/null
@@ -1,602 +0,0 @@
-#!/bin/sh
-#
-# tcc configure script (c) 2003 Fabrice Bellard
-
-# set temporary file name
-# if test ! -z "$TMPDIR" ; then
-# TMPDIR1="${TMPDIR}"
-# elif test ! -z "$TEMPDIR" ; then
-# TMPDIR1="${TEMPDIR}"
-# else
-# TMPDIR1="/tmp"
-# fi
-#
-# bashism: TMPN="${TMPDIR1}/tcc-conf-${RANDOM}-$$-${RANDOM}.c"
-
-TMPN="./conftest-$$"
-TMPH=$TMPN.h
-
-# default parameters
-prefix=""
-execprefix=""
-bindir=""
-libdir=""
-tccdir=""
-includedir=""
-mandir=""
-infodir=""
-sysroot=""
-cross_prefix=""
-cc="gcc"
-ar="ar"
-bigendian="no"
-mingw32="no"
-LIBSUF=".a"
-EXESUF=""
-DLLSUF=".so"
-tcc_usrinclude=""
-tcc_sysincludepaths=""
-tcc_libpaths=""
-tcc_crtprefix=""
-tcc_elfinterp=""
-triplet=
-tcc_lddir=
-confvars=
-suggest="yes"
-gcc_major=0
-gcc_minor=0
-cc_name="gcc"
-ar_set=
-darwin=
-cpuver=
-dwarf=
-
-# use CC from environment when set
-test -n "$CC" && cc="$CC"
-
-# OS specific
-cpu=`uname -m`
-cpu_sys="$cpu"
-targetos=`uname`
-if test "$targetos" = "Linux" ; then
- test "$(uname -o)" = "Android" && targetos=Android
-fi
-
-case $targetos in
- Darwin)
- darwin=yes
- dwarf=4
- confvars="$confvars OSX"
- cc=`command -v cc`
- cc=`readlink $cc || echo clang`
- tcc_usrinclude="`xcrun --show-sdk-path`/usr/include"
- DLLSUF=".dylib"
- case $* in *--config-new_macho*) ;; *)
- # if new_macho was not specified and (known) ver <= 10, use old (=no)
- osxver=$(sw_vers -productVersion 2>/dev/null) # X.Y.Z
- osxver=${osxver%%.*} # major version (or empty on sw_vers error)
- [ "${osxver:-11}" -ge 11 ] || confvars="$confvars new_macho=no"
- esac
- ;;
- Windows_NT|MINGW*|MSYS*|CYGWIN*)
- mingw32=yes
- targetos=WIN32
- ;;
- DragonFly|OpenBSD|FreeBSD|NetBSD)
- confvars="$confvars BSD ldl=no"
- ;;
- Android)
- confvars="$confvars Android pie new-dtags"
- if test -n "$TERMUX_VERSION"; then
- prefix="$PREFIX" # "/data/data/com.termux/files/usr"
- sysroot="$PREFIX"
- test "$cpu" = "aarch64" -o "$cpu" = "x86_64" && S="64" || S=""
- tcc_sysincludepaths="{B}/include:{R}/include/\\\"CONFIG_TRIPLET\\\":{R}/include"
- tcc_libpaths="{B}:{R}/lib:/system/lib${S}"
- tcc_crtprefix="{R}/lib"
- tcc_elfinterp="/system/bin/linker${S}"
- use_triplet="yes"
- tcc_switches="-Wl,-rpath=$sysroot/lib,-section-alignment=0x1000"
- fi
- ;;
- *)
- ;;
-esac
-
-# find source path
-source_path=${0%configure}
-source_path=${source_path%/}
-source_path_used="yes"
-if test -z "$source_path" -o "$source_path" = "." ; then
- source_path=`pwd`
- source_path_used="no"
-fi
-
-for opt do
- eval opt=\"$opt\"
- case "$opt" in
- --prefix=*) prefix=`echo $opt | cut -d '=' -f 2-`
- ;;
- --exec-prefix=*) execprefix=`echo $opt | cut -d '=' -f 2-`
- ;;
- --tccdir=*) tccdir=`echo $opt | cut -d '=' -f 2-`
- ;;
- --bindir=*) bindir=`echo $opt | cut -d '=' -f 2-`
- ;;
- --libdir=*) libdir=`echo $opt | cut -d '=' -f 2-`
- ;;
- --includedir=*) includedir=`echo $opt | cut -d '=' -f 2-`
- ;;
- --sharedir=*) sharedir=`echo $opt | cut -d '=' -f 2-`
- ;;
- --mandir=*) mandir=`echo $opt | cut -d '=' -f 2-`
- ;;
- --infodir=*) infodir=`echo $opt | cut -d '=' -f 2-`
- ;;
- --docdir=*) docdir=`echo $opt | cut -d '=' -f 2-`
- ;;
- --sysroot=*) sysroot=`echo $opt | cut -d '=' -f 2-`
- ;;
- --source-path=*) source_path=`echo $opt | cut -d '=' -f 2-`
- ;;
- --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2-`
- ;;
- --cc=*) cc=`echo $opt | cut -d '=' -f 2-`
- ;;
- --ar=*) ar=`echo $opt | cut -d '=' -f 2-` ; ar_set="yes"
- ;;
- --extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
- ;;
- --extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
- ;;
- --extra-libs=*) extralibs="${opt#--extra-libs=}"
- ;;
- --sysincludepaths=*) tcc_sysincludepaths=`echo $opt | cut -d '=' -f 2-`
- ;;
- --libpaths=*) tcc_libpaths=`echo $opt | cut -d '=' -f 2-`
- ;;
- --crtprefix=*) tcc_crtprefix=`echo $opt | cut -d '=' -f 2-`
- ;;
- --elfinterp=*) tcc_elfinterp=`echo $opt | cut -d '=' -f 2-`
- ;;
- --triplet=*) triplet=`echo $opt | cut -d '=' -f 2-`
- ;;
- --cpu=*) cpu=`echo $opt | cut -d '=' -f 2-`
- ;;
- --dwarf=*) dwarf=`echo $opt | cut -d '=' -f 2-`
- ;;
- --enable-cross) confvars="$confvars cross"
- ;;
- --disable-static) confvars="$confvars static=no"
- ;;
- --enable-static) confvars="$confvars static"
- ;;
- --disable-rpath) confvars="$confvars rpath=no"
- ;;
- --debug) confvars="$confvars debug"
- ;;
- --with-libgcc) confvars="$confvars libgcc"
- ;;
- --with-selinux) confvars="$confvars selinux"
- ;;
- --tcc-switches=*) tcc_switches=`echo $opt | cut -d '=' -f 2-`
- ;;
- --config-mingw32*) mingw32=$(echo "$opt=yes" | cut -d '=' -f 2)
- ;;
- --config-*) confvars="$confvars ${opt#--config-}"; suggest="no"
- ;;
- --help|-h) show_help="yes"
- ;;
- *) echo "configure: WARNING: unrecognized option $opt"
- ;;
- esac
-done
-
-cc="${cross_prefix}${cc}"
-ar="${cross_prefix}${ar}"
-
-# Checking for CFLAGS
-test -z "$CFLAGS" && CFLAGS="-Wall -O2"
-
-# on OSX M1 with --cpu=x86_64, build a tcc to run under rosetta entirely
-if test "$darwin" = "yes" -a "$cpu" = "x86_64" -a "$cpu_sys" = "arm64"; then
- CFLAGS="$CFLAGS -arch $cpu"
- LDFLAGS="$LDFLAGS -arch $cpu"
-fi
-
-case "$cpu" in
- x86|i386|i486|i586|i686|i86pc|BePC|i686-AT386)
- cpu="i386"
- ;;
- x86_64|amd64|x86-64)
- cpu="x86_64"
- ;;
- evbarm)
- case "`uname -p`" in
- aarch64|arm64)
- cpu="arm64"
- ;;
- earmv*)
- cpu="arm"
- ;;
- esac
- ;;
- aarch64|arm64|evbarm)
- cpu="arm64"
- ;;
- arm*)
- case "$cpu" in
- arm|armv4l)
- cpuver=4
- ;;
- armv5tel|armv5tejl)
- cpuver=5
- ;;
- armv6j|armv6l)
- cpuver=6
- ;;
- armv7|armv7a|armv7l)
- cpuver=7
- ;;
- esac
- cpu="arm"
- ;;
- alpha)
- cpu="alpha"
- ;;
- "Power Macintosh"|ppc|ppc64)
- cpu="ppc"
- ;;
- mips)
- cpu="mips"
- ;;
- s390)
- cpu="s390"
- ;;
- riscv64)
- cpu="riscv64"
- ;;
- *)
- echo "Unsupported CPU"
- exit 1
- ;;
-esac
-
-if test "$mingw32" = "yes" ; then
- if test "$source_path_used" = "no"; then
- source_path="."
- fi
- test -z "$prefix" && prefix="C:/Program Files/tcc"
- test -z "$tccdir" && tccdir="${prefix}" && tccdir_auto="yes"
- test -z "$bindir" && bindir="${tccdir}"
- test -z "$docdir" && docdir="${tccdir}/doc"
- test -z "$libdir" && libdir="${tccdir}/libtcc"
- confvars="$confvars WIN32"
- LIBSUF=".lib"
- EXESUF=".exe"
- DLLSUF=".dll"
-else
- if test -z "$prefix" ; then
- prefix="/usr/local"
- fi
- if test -z "$sharedir" ; then
- sharedir="${prefix}/share"
- fi
- if test x"$execprefix" = x""; then
- execprefix="${prefix}"
- fi
- if test x"$libdir" = x""; then
- libdir="${execprefix}/lib"
- fi
- if test x"$bindir" = x""; then
- bindir="${execprefix}/bin"
- fi
- if test x"$docdir" = x""; then
- docdir="${sharedir}/doc"
- fi
- if test x"$mandir" = x""; then
- mandir="${sharedir}/man"
- fi
- if test x"$infodir" = x""; then
- infodir="${sharedir}/info"
- fi
- if test x"$tccdir" = x""; then
- tccdir="${libdir}/tcc"
- fi
- if test x"$includedir" = x""; then
- includedir="${prefix}/include"
- fi
-fi # mingw32
-
-if test x"$show_help" = "xyes" ; then
-cat << EOF
-Usage: configure [options]
-Options: [defaults in brackets after descriptions]
-
-Standard options:
- --help print this message
- --prefix=PREFIX install in PREFIX [$prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [same as prefix]
- --bindir=DIR user executables in DIR [EPREFIX/bin]
- --libdir=DIR object code libraries in DIR [EPREFIX/lib]
- --tccdir=DIR installation directory [EPREFIX/lib/tcc]
- --includedir=DIR C header files in DIR [PREFIX/include]
- --sharedir=DIR documentation root DIR [PREFIX/share]
- --docdir=DIR documentation in DIR [SHAREDIR/doc/tcc]
- --mandir=DIR man documentation in DIR [SHAREDIR/man]
- --infodir=DIR info documentation in DIR [SHAREDIR/info]
-
-Advanced options (experts only):
- --source-path=PATH path of source code [$source_path]
- --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
- --sysroot=PREFIX prepend PREFIX to library/include paths [$sysroot]
- --cc=CC use C compiler CC [$cc]
- --ar=AR create archives using AR [$ar]
- --extra-cflags= specify compiler flags [$CFLAGS]
- --extra-ldflags= specify linker options [$LDFLAGS]
- --cpu=CPU CPU [$cpu]
-
- --debug include debug info with resulting binaries
- --disable-static make libtcc.so instead of libtcc.a
- --enable-static make libtcc.a instead of libtcc.dll (win32)
- --disable-rpath disable use of -rpath with libtcc.so
- --with-libgcc use libgcc_s.so.1 instead of libtcc1.a
- --with-selinux use mmap for executable memory (tcc -run)
- --enable-cross build cross compilers (see also 'make help')
-
- --sysincludepaths=... specify system include paths, colon separated
- --libpaths=... specify system library paths, colon separated
- --crtprefix=... specify locations of crt?.o, colon separated
- --elfinterp=... specify elf interpreter
- --triplet=... specify system library/include directory triplet
- --tcc-switches=... specify implicit switches passed to tcc
-
- --config-uClibc,-musl enable system specific configurations
- --config-mingw32 build on windows using msys, busybox, etc.
- --config-backtrace=no disable stack backtraces (with -run or -bt)
- --config-bcheck=no disable bounds checker (-b)
- --config-predefs=no do not compile tccdefs.h, instead just include
- --config-new_macho=no|yes Force apple object format (autodetect osx <= 10)
- --config-codesign Use codesign on apple to sign executables
- --dwarf=x Use dwarf debug info instead of stabs (x=2..5)
-EOF
-exit 1
-fi
-
-if test -z "$cross_prefix" ; then
- CONFTEST=./conftest$EXESUF
- if ! $cc -o $CONFTEST $source_path/conftest.c ; then
- echo "configure: error: '$cc' failed to compile conftest.c."
- else
- cc_name="$($CONFTEST compiler)"
- gcc_major="$($CONFTEST version)"
- gcc_minor="$($CONFTEST minor)"
- bigendian="$($CONFTEST bigendian)"
- _triplet="$($CONFTEST triplet)"
- fi
- if test "$mingw32" = "no" ; then
-
- if test -z "$triplet" -a -n "$_triplet"; then
- if test -f "/usr/lib/$_triplet/crti.o" -o -n "$use_triplet" ; then
- triplet="$_triplet"
- fi
- fi
-
- if test -z "$triplet"; then
- if test $cpu = "x86_64" -o $cpu = "arm64" -o $cpu = "riscv64" ; then
- if test -f "/usr/lib64/crti.o" ; then
- tcc_lddir="lib64"
- fi
- fi
- fi
-
- if test "$cpu" = "arm" ; then
- if test "${triplet%eabihf}" != "$triplet" ; then
- confvars="$confvars arm_eabihf arm_vfp"
- elif test "${triplet%eabi}" != "$triplet" ; then
- confvars="$confvars arm_eabi arm_vfp"
- elif test "${_triplet%eabihf}" != "$_triplet" ; then
- confvars="$confvars arm_eabihf arm_vfp"
- elif test "${_triplet%eabi}" != "$_triplet" ; then
- confvars="$confvars arm_eabi arm_vfp"
- elif grep -s -q "^Features.* \(vfp\|iwmmxt\) " /proc/cpuinfo ; then
- confvars="$confvars arm_vfp"
- fi
- fi
-
- if test "$suggest" = "yes"; then
- if test -f "/lib/ld-uClibc.so.0" ; then
- echo "Perhaps you want ./configure --config-uClibc"
- fi
- if test -f "/lib/ld-musl-$cpu.so.1"; then
- echo "Perhaps you want ./configure --config-musl"
- fi
- fi
- else # mingw32 = yes
- if test "$cc_name" = "gcc"; then
- # avoid mingw dependencies such as 'libgcc_s_dw2-1.dll'
- test -z "$LDFLAGS" && LDFLAGS="-static"
- fi
- fi
-else
- # if cross compiling, cannot launch a program, so make a static guess
- case $cpu in
- ppc|mips|s390) bigendian=yes;;
- esac
-fi
-
-if test "$bigendian" = "yes" ; then
- confvars="$confvars BIGENDIAN"
-fi
-
-# a final configuration tuning
-if test "$cc_name" != "tcc"; then
- OPT1="-Wdeclaration-after-statement -fno-strict-aliasing"
- # we want -Wno- but gcc does not always reject unknown -Wno- options
- OPT2="-Wpointer-sign -Wsign-compare -Wunused-result -Wformat-truncation"
- OPT2="$OPT2 -Wstringop-truncation"
- if test "$cc_name" = "clang"; then
- OPT1="$OPT1 -fheinous-gnu-extensions"
- OPT2="$OPT2 -Wstring-plus-int"
- fi
- $cc $OPT1 $OPT2 -o a.out -c -xc - < /dev/null > cc_msg.txt 2>&1
- for o in $OPT1; do # enable these options
- if ! grep -q -- $o cc_msg.txt; then CFLAGS="$CFLAGS $o"; fi
- done
- for o in $OPT2; do # disable these options
- if ! grep -q -- $o cc_msg.txt; then CFLAGS="$CFLAGS -Wno-${o#-W*}"; fi
- done
- # cat cc_msg.txt
- # echo $CFLAGS
- rm -f cc_msg.txt a.out
-else # cc is tcc
- test "$ar_set" || ar="$cc -ar"
-fi
-
-fcho() { if test -n "$2"; then echo "$1$2"; fi }
-
-fcho "Binary directory " "$bindir"
-fcho "TinyCC directory " "$tccdir"
-fcho "Library directory " "$libdir"
-fcho "Include directory " "$includedir"
-fcho "Manual directory " "$mandir"
-fcho "Info directory " "$infodir"
-fcho "Doc directory " "$docdir"
-fcho "Target root prefix " "$sysroot"
-fcho "/usr/include dir " "$tcc_usrinclude"
-echo "Source path $source_path"
-echo "C compiler $cc ($gcc_major.$gcc_minor)"
-echo "Target OS $targetos"
-echo "CPU $cpu"
-fcho "Triplet " "$triplet"
-fcho "Config " "${confvars# }"
-echo "Creating config.mak and config.h"
-
-cat >config.mak <<EOF
-# Automatically generated by configure - do not modify
-prefix=$prefix
-bindir=\$(DESTDIR)$bindir
-tccdir=\$(DESTDIR)$tccdir
-libdir=\$(DESTDIR)$libdir
-includedir=\$(DESTDIR)$includedir
-mandir=\$(DESTDIR)$mandir
-infodir=\$(DESTDIR)$infodir
-docdir=\$(DESTDIR)$docdir
-CC=$cc
-CC_NAME=$cc_name
-GCC_MAJOR=$gcc_major
-GCC_MINOR=$gcc_minor
-AR=$ar
-CFLAGS=$CFLAGS
-LDFLAGS=$LDFLAGS
-LIBSUF=$LIBSUF
-EXESUF=$EXESUF
-DLLSUF=$DLLSUF
-EOF
-
-print_inc() {
- local v="$2"
- if test -n "$v"; then
- test "$3" = "num" || v="\"$v\""
- echo "#ifndef $1" >> $TMPH
- echo "# define $1 $v" >> $TMPH
- echo "#endif" >> $TMPH
- fi
-}
-
-print_mak() {
- local v="$2"
- if test -n "$v"; then
- test "$3" = "num" || v="\"\\\"$v\\\"\""
- echo "NATIVE_DEFINES+=-D$1=$v" >> config.mak
- fi
-}
-
-echo "/* Automatically generated by configure - do not modify */" > $TMPH
-
-print_inc CONFIG_SYSROOT "$sysroot"
-test "$tccdir_auto" = "yes" || print_inc CONFIG_TCCDIR "$tccdir"
-print_inc DWARF_VERSION "$dwarf" num
-print_mak CONFIG_USR_INCLUDE "$tcc_usrinclude"
-print_mak CONFIG_TCC_SYSINCLUDEPATHS "$tcc_sysincludepaths"
-print_mak CONFIG_TCC_LIBPATHS "$tcc_libpaths"
-print_mak CONFIG_TCC_CRTPREFIX "$tcc_crtprefix"
-print_mak CONFIG_TCC_ELFINTERP "$tcc_elfinterp"
-print_mak CONFIG_TCC_SWITCHES "$tcc_switches"
-print_mak CONFIG_LDDIR "$tcc_lddir"
-print_mak CONFIG_TRIPLET "$triplet"
-print_mak TCC_CPU_VERSION "$cpuver" num
-
-echo "ARCH=$cpu" >> config.mak
-echo "TARGETOS=$targetos" >> config.mak
-
-predefs="1"
-for v in $confvars ; do
- test "$v" = "predefs=no" && predefs=""
- if test "${v%=*}" = "$v"; then
- echo "CONFIG_$v=yes" >> config.mak
- else
- echo "CONFIG_$v" >> config.mak
- fi
-done
-print_inc CONFIG_TCC_PREDEFS "$predefs" num
-
-version=`head $source_path/VERSION`
-echo "VERSION = $version" >> config.mak
-echo "#define TCC_VERSION \"$version\"" >> $TMPH
-echo "@set VERSION $version" > config.texi
-
-if test "$source_path_used" = "yes" ; then
- case $source_path in
- /*) echo "TOPSRC=$source_path";;
- *) echo "TOPSRC=\$(TOP)/$source_path";;
- esac >>config.mak
-else
- echo 'TOPSRC=$(TOP)' >>config.mak
-fi
-cat >>$TMPH <<EOF
-#define GCC_MAJOR $gcc_major
-#define GCC_MINOR $gcc_minor
-#define CC_NAME CC_${cc_name}
-EOF
-
-diff $TMPH config.h >/dev/null 2>&1
-if test $? -ne 0 ; then
- mv -f $TMPH config.h
-else
- echo "config.h is unchanged"
-fi
-
-rm -f $TMPN* $CONFTEST
-
-# ---------------------------------------------------------------------------
-# build tree in object directory if source path is different from current one
-
-fn_makelink()
-{
- tgt=$1/$2
- case $2 in
- */*) dn=${2%/*}
- test -d $dn || mkdir -p $dn
- case $1 in
- /*) ;;
- *) while test $dn ; do
- tgt=../$tgt; dn=${dn#${dn%%/*}}; dn=${dn#/}
- done
- ;;
- esac
- ;;
- esac
-
- ln -sfn $tgt $2 || ( echo "ln failed. Using cp instead."; cp -f $1/$2 $2 )
-}
-
-if test "$source_path_used" = "yes" ; then
- FILES="Makefile lib/Makefile tests/Makefile tests/tests2/Makefile tests/pp/Makefile"
- for f in $FILES ; do
- fn_makelink $source_path $f
- done
-fi
-
-# ---------------------------------------------------------------------------
diff --git a/tinycc/dwarf.h b/tinycc/dwarf.h
deleted file mode 100644
index c961bc3..0000000
--- a/tinycc/dwarf.h
+++ /dev/null
@@ -1,1046 +0,0 @@
-/* This file defines standard DWARF types, structures, and macros.
- Copyright (C) 2000-2011, 2014, 2016, 2017, 2018 Red Hat, Inc.
- This file is part of elfutils.
-
- This file is free software; you can redistribute it and/or modify
- it under the terms of either
-
- * the GNU Lesser General Public License as published by the Free
- Software Foundation; either version 3 of the License, or (at
- your option) any later version
-
- or
-
- * the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at
- your option) any later version
-
- or both in parallel, as here.
-
- elfutils is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received copies of the GNU General Public License and
- the GNU Lesser General Public License along with this program. If
- not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef _DWARF_H
-#define _DWARF_H 1
-
-/* DWARF Unit Header Types. */
-enum
- {
- DW_UT_compile = 0x01,
- DW_UT_type = 0x02,
- DW_UT_partial = 0x03,
- DW_UT_skeleton = 0x04,
- DW_UT_split_compile = 0x05,
- DW_UT_split_type = 0x06,
-
- DW_UT_lo_user = 0x80,
- DW_UT_hi_user = 0xff
- };
-
-/* DWARF tags. */
-enum
- {
- DW_TAG_array_type = 0x01,
- DW_TAG_class_type = 0x02,
- DW_TAG_entry_point = 0x03,
- DW_TAG_enumeration_type = 0x04,
- DW_TAG_formal_parameter = 0x05,
- /* 0x06 reserved. */
- /* 0x07 reserved. */
- DW_TAG_imported_declaration = 0x08,
- /* 0x09 reserved. */
- DW_TAG_label = 0x0a,
- DW_TAG_lexical_block = 0x0b,
- /* 0x0c reserved. */
- DW_TAG_member = 0x0d,
- /* 0x0e reserved. */
- DW_TAG_pointer_type = 0x0f,
- DW_TAG_reference_type = 0x10,
- DW_TAG_compile_unit = 0x11,
- DW_TAG_string_type = 0x12,
- DW_TAG_structure_type = 0x13,
- /* 0x14 reserved. */
- DW_TAG_subroutine_type = 0x15,
- DW_TAG_typedef = 0x16,
- DW_TAG_union_type = 0x17,
- DW_TAG_unspecified_parameters = 0x18,
- DW_TAG_variant = 0x19,
- DW_TAG_common_block = 0x1a,
- DW_TAG_common_inclusion = 0x1b,
- DW_TAG_inheritance = 0x1c,
- DW_TAG_inlined_subroutine = 0x1d,
- DW_TAG_module = 0x1e,
- DW_TAG_ptr_to_member_type = 0x1f,
- DW_TAG_set_type = 0x20,
- DW_TAG_subrange_type = 0x21,
- DW_TAG_with_stmt = 0x22,
- DW_TAG_access_declaration = 0x23,
- DW_TAG_base_type = 0x24,
- DW_TAG_catch_block = 0x25,
- DW_TAG_const_type = 0x26,
- DW_TAG_constant = 0x27,
- DW_TAG_enumerator = 0x28,
- DW_TAG_file_type = 0x29,
- DW_TAG_friend = 0x2a,
- DW_TAG_namelist = 0x2b,
- DW_TAG_namelist_item = 0x2c,
- DW_TAG_packed_type = 0x2d,
- DW_TAG_subprogram = 0x2e,
- DW_TAG_template_type_parameter = 0x2f,
- DW_TAG_template_value_parameter = 0x30,
- DW_TAG_thrown_type = 0x31,
- DW_TAG_try_block = 0x32,
- DW_TAG_variant_part = 0x33,
- DW_TAG_variable = 0x34,
- DW_TAG_volatile_type = 0x35,
- DW_TAG_dwarf_procedure = 0x36,
- DW_TAG_restrict_type = 0x37,
- DW_TAG_interface_type = 0x38,
- DW_TAG_namespace = 0x39,
- DW_TAG_imported_module = 0x3a,
- DW_TAG_unspecified_type = 0x3b,
- DW_TAG_partial_unit = 0x3c,
- DW_TAG_imported_unit = 0x3d,
- /* 0x3e reserved. Was DW_TAG_mutable_type. */
- DW_TAG_condition = 0x3f,
- DW_TAG_shared_type = 0x40,
- DW_TAG_type_unit = 0x41,
- DW_TAG_rvalue_reference_type = 0x42,
- DW_TAG_template_alias = 0x43,
- DW_TAG_coarray_type = 0x44,
- DW_TAG_generic_subrange = 0x45,
- DW_TAG_dynamic_type = 0x46,
- DW_TAG_atomic_type = 0x47,
- DW_TAG_call_site = 0x48,
- DW_TAG_call_site_parameter = 0x49,
- DW_TAG_skeleton_unit = 0x4a,
- DW_TAG_immutable_type = 0x4b,
-
- DW_TAG_lo_user = 0x4080,
-
- DW_TAG_MIPS_loop = 0x4081,
- DW_TAG_format_label = 0x4101,
- DW_TAG_function_template = 0x4102,
- DW_TAG_class_template = 0x4103,
-
- DW_TAG_GNU_BINCL = 0x4104,
- DW_TAG_GNU_EINCL = 0x4105,
-
- DW_TAG_GNU_template_template_param = 0x4106,
- DW_TAG_GNU_template_parameter_pack = 0x4107,
- DW_TAG_GNU_formal_parameter_pack = 0x4108,
- DW_TAG_GNU_call_site = 0x4109,
- DW_TAG_GNU_call_site_parameter = 0x410a,
-
- DW_TAG_hi_user = 0xffff
- };
-
-
-/* Children determination encodings. */
-enum
- {
- DW_CHILDREN_no = 0,
- DW_CHILDREN_yes = 1
- };
-
-
-/* DWARF attributes encodings. */
-enum
- {
- DW_AT_sibling = 0x01,
- DW_AT_location = 0x02,
- DW_AT_name = 0x03,
- /* 0x04 reserved. */
- /* 0x05 reserved. */
- /* 0x06 reserved. */
- /* 0x07 reserved. */
- /* 0x08 reserved. */
- DW_AT_ordering = 0x09,
- /* 0x0a reserved. */
- DW_AT_byte_size = 0x0b,
- DW_AT_bit_offset = 0x0c, /* Deprecated in DWARF4. */
- DW_AT_bit_size = 0x0d,
- /* 0x0e reserved. */
- /* 0x0f reserved. */
- DW_AT_stmt_list = 0x10,
- DW_AT_low_pc = 0x11,
- DW_AT_high_pc = 0x12,
- DW_AT_language = 0x13,
- /* 0x14 reserved. */
- DW_AT_discr = 0x15,
- DW_AT_discr_value = 0x16,
- DW_AT_visibility = 0x17,
- DW_AT_import = 0x18,
- DW_AT_string_length = 0x19,
- DW_AT_common_reference = 0x1a,
- DW_AT_comp_dir = 0x1b,
- DW_AT_const_value = 0x1c,
- DW_AT_containing_type = 0x1d,
- DW_AT_default_value = 0x1e,
- /* 0x1f reserved. */
- DW_AT_inline = 0x20,
- DW_AT_is_optional = 0x21,
- DW_AT_lower_bound = 0x22,
- /* 0x23 reserved. */
- /* 0x24 reserved. */
- DW_AT_producer = 0x25,
- /* 0x26 reserved. */
- DW_AT_prototyped = 0x27,
- /* 0x28 reserved. */
- /* 0x29 reserved. */
- DW_AT_return_addr = 0x2a,
- /* 0x2b reserved. */
- DW_AT_start_scope = 0x2c,
- /* 0x2d reserved. */
- DW_AT_bit_stride = 0x2e,
- DW_AT_upper_bound = 0x2f,
- /* 0x30 reserved. */
- DW_AT_abstract_origin = 0x31,
- DW_AT_accessibility = 0x32,
- DW_AT_address_class = 0x33,
- DW_AT_artificial = 0x34,
- DW_AT_base_types = 0x35,
- DW_AT_calling_convention = 0x36,
- DW_AT_count = 0x37,
- DW_AT_data_member_location = 0x38,
- DW_AT_decl_column = 0x39,
- DW_AT_decl_file = 0x3a,
- DW_AT_decl_line = 0x3b,
- DW_AT_declaration = 0x3c,
- DW_AT_discr_list = 0x3d,
- DW_AT_encoding = 0x3e,
- DW_AT_external = 0x3f,
- DW_AT_frame_base = 0x40,
- DW_AT_friend = 0x41,
- DW_AT_identifier_case = 0x42,
- DW_AT_macro_info = 0x43, /* Deprecated in DWARF5. */
- DW_AT_namelist_item = 0x44,
- DW_AT_priority = 0x45,
- DW_AT_segment = 0x46,
- DW_AT_specification = 0x47,
- DW_AT_static_link = 0x48,
- DW_AT_type = 0x49,
- DW_AT_use_location = 0x4a,
- DW_AT_variable_parameter = 0x4b,
- DW_AT_virtuality = 0x4c,
- DW_AT_vtable_elem_location = 0x4d,
- DW_AT_allocated = 0x4e,
- DW_AT_associated = 0x4f,
- DW_AT_data_location = 0x50,
- DW_AT_byte_stride = 0x51,
- DW_AT_entry_pc = 0x52,
- DW_AT_use_UTF8 = 0x53,
- DW_AT_extension = 0x54,
- DW_AT_ranges = 0x55,
- DW_AT_trampoline = 0x56,
- DW_AT_call_column = 0x57,
- DW_AT_call_file = 0x58,
- DW_AT_call_line = 0x59,
- DW_AT_description = 0x5a,
- DW_AT_binary_scale = 0x5b,
- DW_AT_decimal_scale = 0x5c,
- DW_AT_small = 0x5d,
- DW_AT_decimal_sign = 0x5e,
- DW_AT_digit_count = 0x5f,
- DW_AT_picture_string = 0x60,
- DW_AT_mutable = 0x61,
- DW_AT_threads_scaled = 0x62,
- DW_AT_explicit = 0x63,
- DW_AT_object_pointer = 0x64,
- DW_AT_endianity = 0x65,
- DW_AT_elemental = 0x66,
- DW_AT_pure = 0x67,
- DW_AT_recursive = 0x68,
- DW_AT_signature = 0x69,
- DW_AT_main_subprogram = 0x6a,
- DW_AT_data_bit_offset = 0x6b,
- DW_AT_const_expr = 0x6c,
- DW_AT_enum_class = 0x6d,
- DW_AT_linkage_name = 0x6e,
- DW_AT_string_length_bit_size = 0x6f,
- DW_AT_string_length_byte_size = 0x70,
- DW_AT_rank = 0x71,
- DW_AT_str_offsets_base = 0x72,
- DW_AT_addr_base = 0x73,
- DW_AT_rnglists_base = 0x74,
- /* 0x75 reserved. */
- DW_AT_dwo_name = 0x76,
- DW_AT_reference = 0x77,
- DW_AT_rvalue_reference = 0x78,
- DW_AT_macros = 0x79,
- DW_AT_call_all_calls = 0x7a,
- DW_AT_call_all_source_calls = 0x7b,
- DW_AT_call_all_tail_calls = 0x7c,
- DW_AT_call_return_pc = 0x7d,
- DW_AT_call_value = 0x7e,
- DW_AT_call_origin = 0x7f,
- DW_AT_call_parameter = 0x80,
- DW_AT_call_pc = 0x81,
- DW_AT_call_tail_call = 0x82,
- DW_AT_call_target = 0x83,
- DW_AT_call_target_clobbered = 0x84,
- DW_AT_call_data_location = 0x85,
- DW_AT_call_data_value = 0x86,
- DW_AT_noreturn = 0x87,
- DW_AT_alignment = 0x88,
- DW_AT_export_symbols = 0x89,
- DW_AT_deleted = 0x8a,
- DW_AT_defaulted = 0x8b,
- DW_AT_loclists_base = 0x8c,
-
- DW_AT_lo_user = 0x2000,
-
- DW_AT_MIPS_fde = 0x2001,
- DW_AT_MIPS_loop_begin = 0x2002,
- DW_AT_MIPS_tail_loop_begin = 0x2003,
- DW_AT_MIPS_epilog_begin = 0x2004,
- DW_AT_MIPS_loop_unroll_factor = 0x2005,
- DW_AT_MIPS_software_pipeline_depth = 0x2006,
- DW_AT_MIPS_linkage_name = 0x2007,
- DW_AT_MIPS_stride = 0x2008,
- DW_AT_MIPS_abstract_name = 0x2009,
- DW_AT_MIPS_clone_origin = 0x200a,
- DW_AT_MIPS_has_inlines = 0x200b,
- DW_AT_MIPS_stride_byte = 0x200c,
- DW_AT_MIPS_stride_elem = 0x200d,
- DW_AT_MIPS_ptr_dopetype = 0x200e,
- DW_AT_MIPS_allocatable_dopetype = 0x200f,
- DW_AT_MIPS_assumed_shape_dopetype = 0x2010,
- DW_AT_MIPS_assumed_size = 0x2011,
-
- /* GNU extensions. */
- DW_AT_sf_names = 0x2101,
- DW_AT_src_info = 0x2102,
- DW_AT_mac_info = 0x2103,
- DW_AT_src_coords = 0x2104,
- DW_AT_body_begin = 0x2105,
- DW_AT_body_end = 0x2106,
- DW_AT_GNU_vector = 0x2107,
- DW_AT_GNU_guarded_by = 0x2108,
- DW_AT_GNU_pt_guarded_by = 0x2109,
- DW_AT_GNU_guarded = 0x210a,
- DW_AT_GNU_pt_guarded = 0x210b,
- DW_AT_GNU_locks_excluded = 0x210c,
- DW_AT_GNU_exclusive_locks_required = 0x210d,
- DW_AT_GNU_shared_locks_required = 0x210e,
- DW_AT_GNU_odr_signature = 0x210f,
- DW_AT_GNU_template_name = 0x2110,
- DW_AT_GNU_call_site_value = 0x2111,
- DW_AT_GNU_call_site_data_value = 0x2112,
- DW_AT_GNU_call_site_target = 0x2113,
- DW_AT_GNU_call_site_target_clobbered = 0x2114,
- DW_AT_GNU_tail_call = 0x2115,
- DW_AT_GNU_all_tail_call_sites = 0x2116,
- DW_AT_GNU_all_call_sites = 0x2117,
- DW_AT_GNU_all_source_call_sites = 0x2118,
- DW_AT_GNU_locviews = 0x2137,
- DW_AT_GNU_entry_view = 0x2138,
- DW_AT_GNU_macros = 0x2119,
- DW_AT_GNU_deleted = 0x211a,
- /* GNU Debug Fission extensions. */
- DW_AT_GNU_dwo_name = 0x2130,
- DW_AT_GNU_dwo_id = 0x2131,
- DW_AT_GNU_ranges_base = 0x2132,
- DW_AT_GNU_addr_base = 0x2133,
- DW_AT_GNU_pubnames = 0x2134,
- DW_AT_GNU_pubtypes = 0x2135,
-
- /* https://gcc.gnu.org/wiki/DW_AT_GNU_numerator_denominator */
- DW_AT_GNU_numerator = 0x2303,
- DW_AT_GNU_denominator = 0x2304,
- /* https://gcc.gnu.org/wiki/DW_AT_GNU_bias */
- DW_AT_GNU_bias = 0x2305,
-
- DW_AT_hi_user = 0x3fff
- };
-
-/* Old unofficially attribute names. Should not be used.
- Will not appear in known-dwarf.h */
-
-/* DWARF1 array subscripts and element data types. */
-#define DW_AT_subscr_data 0x0a
-/* DWARF1 enumeration literals. */
-#define DW_AT_element_list 0x0f
-/* DWARF1 reference for variable to member structure, class or union. */
-#define DW_AT_member 0x14
-
-/* DWARF form encodings. */
-enum
- {
- DW_FORM_addr = 0x01,
- DW_FORM_block2 = 0x03,
- DW_FORM_block4 = 0x04,
- DW_FORM_data2 = 0x05,
- DW_FORM_data4 = 0x06,
- DW_FORM_data8 = 0x07,
- DW_FORM_string = 0x08,
- DW_FORM_block = 0x09,
- DW_FORM_block1 = 0x0a,
- DW_FORM_data1 = 0x0b,
- DW_FORM_flag = 0x0c,
- DW_FORM_sdata = 0x0d,
- DW_FORM_strp = 0x0e,
- DW_FORM_udata = 0x0f,
- DW_FORM_ref_addr = 0x10,
- DW_FORM_ref1 = 0x11,
- DW_FORM_ref2 = 0x12,
- DW_FORM_ref4 = 0x13,
- DW_FORM_ref8 = 0x14,
- DW_FORM_ref_udata = 0x15,
- DW_FORM_indirect = 0x16,
- DW_FORM_sec_offset = 0x17,
- DW_FORM_exprloc = 0x18,
- DW_FORM_flag_present = 0x19,
- DW_FORM_strx = 0x1a,
- DW_FORM_addrx = 0x1b,
- DW_FORM_ref_sup4 = 0x1c,
- DW_FORM_strp_sup = 0x1d,
- DW_FORM_data16 = 0x1e,
- DW_FORM_line_strp = 0x1f,
- DW_FORM_ref_sig8 = 0x20,
- DW_FORM_implicit_const = 0x21,
- DW_FORM_loclistx = 0x22,
- DW_FORM_rnglistx = 0x23,
- DW_FORM_ref_sup8 = 0x24,
- DW_FORM_strx1 = 0x25,
- DW_FORM_strx2 = 0x26,
- DW_FORM_strx3 = 0x27,
- DW_FORM_strx4 = 0x28,
- DW_FORM_addrx1 = 0x29,
- DW_FORM_addrx2 = 0x2a,
- DW_FORM_addrx3 = 0x2b,
- DW_FORM_addrx4 = 0x2c,
-
- /* GNU Debug Fission extensions. */
- DW_FORM_GNU_addr_index = 0x1f01,
- DW_FORM_GNU_str_index = 0x1f02,
-
- DW_FORM_GNU_ref_alt = 0x1f20, /* offset in alternate .debuginfo. */
- DW_FORM_GNU_strp_alt = 0x1f21 /* offset in alternate .debug_str. */
- };
-
-
-/* DWARF location operation encodings. */
-enum
- {
- DW_OP_addr = 0x03, /* Constant address. */
- DW_OP_deref = 0x06,
- DW_OP_const1u = 0x08, /* Unsigned 1-byte constant. */
- DW_OP_const1s = 0x09, /* Signed 1-byte constant. */
- DW_OP_const2u = 0x0a, /* Unsigned 2-byte constant. */
- DW_OP_const2s = 0x0b, /* Signed 2-byte constant. */
- DW_OP_const4u = 0x0c, /* Unsigned 4-byte constant. */
- DW_OP_const4s = 0x0d, /* Signed 4-byte constant. */
- DW_OP_const8u = 0x0e, /* Unsigned 8-byte constant. */
- DW_OP_const8s = 0x0f, /* Signed 8-byte constant. */
- DW_OP_constu = 0x10, /* Unsigned LEB128 constant. */
- DW_OP_consts = 0x11, /* Signed LEB128 constant. */
- DW_OP_dup = 0x12,
- DW_OP_drop = 0x13,
- DW_OP_over = 0x14,
- DW_OP_pick = 0x15, /* 1-byte stack index. */
- DW_OP_swap = 0x16,
- DW_OP_rot = 0x17,
- DW_OP_xderef = 0x18,
- DW_OP_abs = 0x19,
- DW_OP_and = 0x1a,
- DW_OP_div = 0x1b,
- DW_OP_minus = 0x1c,
- DW_OP_mod = 0x1d,
- DW_OP_mul = 0x1e,
- DW_OP_neg = 0x1f,
- DW_OP_not = 0x20,
- DW_OP_or = 0x21,
- DW_OP_plus = 0x22,
- DW_OP_plus_uconst = 0x23, /* Unsigned LEB128 addend. */
- DW_OP_shl = 0x24,
- DW_OP_shr = 0x25,
- DW_OP_shra = 0x26,
- DW_OP_xor = 0x27,
- DW_OP_bra = 0x28, /* Signed 2-byte constant. */
- DW_OP_eq = 0x29,
- DW_OP_ge = 0x2a,
- DW_OP_gt = 0x2b,
- DW_OP_le = 0x2c,
- DW_OP_lt = 0x2d,
- DW_OP_ne = 0x2e,
- DW_OP_skip = 0x2f, /* Signed 2-byte constant. */
- DW_OP_lit0 = 0x30, /* Literal 0. */
- DW_OP_lit1 = 0x31, /* Literal 1. */
- DW_OP_lit2 = 0x32, /* Literal 2. */
- DW_OP_lit3 = 0x33, /* Literal 3. */
- DW_OP_lit4 = 0x34, /* Literal 4. */
- DW_OP_lit5 = 0x35, /* Literal 5. */
- DW_OP_lit6 = 0x36, /* Literal 6. */
- DW_OP_lit7 = 0x37, /* Literal 7. */
- DW_OP_lit8 = 0x38, /* Literal 8. */
- DW_OP_lit9 = 0x39, /* Literal 9. */
- DW_OP_lit10 = 0x3a, /* Literal 10. */
- DW_OP_lit11 = 0x3b, /* Literal 11. */
- DW_OP_lit12 = 0x3c, /* Literal 12. */
- DW_OP_lit13 = 0x3d, /* Literal 13. */
- DW_OP_lit14 = 0x3e, /* Literal 14. */
- DW_OP_lit15 = 0x3f, /* Literal 15. */
- DW_OP_lit16 = 0x40, /* Literal 16. */
- DW_OP_lit17 = 0x41, /* Literal 17. */
- DW_OP_lit18 = 0x42, /* Literal 18. */
- DW_OP_lit19 = 0x43, /* Literal 19. */
- DW_OP_lit20 = 0x44, /* Literal 20. */
- DW_OP_lit21 = 0x45, /* Literal 21. */
- DW_OP_lit22 = 0x46, /* Literal 22. */
- DW_OP_lit23 = 0x47, /* Literal 23. */
- DW_OP_lit24 = 0x48, /* Literal 24. */
- DW_OP_lit25 = 0x49, /* Literal 25. */
- DW_OP_lit26 = 0x4a, /* Literal 26. */
- DW_OP_lit27 = 0x4b, /* Literal 27. */
- DW_OP_lit28 = 0x4c, /* Literal 28. */
- DW_OP_lit29 = 0x4d, /* Literal 29. */
- DW_OP_lit30 = 0x4e, /* Literal 30. */
- DW_OP_lit31 = 0x4f, /* Literal 31. */
- DW_OP_reg0 = 0x50, /* Register 0. */
- DW_OP_reg1 = 0x51, /* Register 1. */
- DW_OP_reg2 = 0x52, /* Register 2. */
- DW_OP_reg3 = 0x53, /* Register 3. */
- DW_OP_reg4 = 0x54, /* Register 4. */
- DW_OP_reg5 = 0x55, /* Register 5. */
- DW_OP_reg6 = 0x56, /* Register 6. */
- DW_OP_reg7 = 0x57, /* Register 7. */
- DW_OP_reg8 = 0x58, /* Register 8. */
- DW_OP_reg9 = 0x59, /* Register 9. */
- DW_OP_reg10 = 0x5a, /* Register 10. */
- DW_OP_reg11 = 0x5b, /* Register 11. */
- DW_OP_reg12 = 0x5c, /* Register 12. */
- DW_OP_reg13 = 0x5d, /* Register 13. */
- DW_OP_reg14 = 0x5e, /* Register 14. */
- DW_OP_reg15 = 0x5f, /* Register 15. */
- DW_OP_reg16 = 0x60, /* Register 16. */
- DW_OP_reg17 = 0x61, /* Register 17. */
- DW_OP_reg18 = 0x62, /* Register 18. */
- DW_OP_reg19 = 0x63, /* Register 19. */
- DW_OP_reg20 = 0x64, /* Register 20. */
- DW_OP_reg21 = 0x65, /* Register 21. */
- DW_OP_reg22 = 0x66, /* Register 22. */
- DW_OP_reg23 = 0x67, /* Register 24. */
- DW_OP_reg24 = 0x68, /* Register 24. */
- DW_OP_reg25 = 0x69, /* Register 25. */
- DW_OP_reg26 = 0x6a, /* Register 26. */
- DW_OP_reg27 = 0x6b, /* Register 27. */
- DW_OP_reg28 = 0x6c, /* Register 28. */
- DW_OP_reg29 = 0x6d, /* Register 29. */
- DW_OP_reg30 = 0x6e, /* Register 30. */
- DW_OP_reg31 = 0x6f, /* Register 31. */
- DW_OP_breg0 = 0x70, /* Base register 0. */
- DW_OP_breg1 = 0x71, /* Base register 1. */
- DW_OP_breg2 = 0x72, /* Base register 2. */
- DW_OP_breg3 = 0x73, /* Base register 3. */
- DW_OP_breg4 = 0x74, /* Base register 4. */
- DW_OP_breg5 = 0x75, /* Base register 5. */
- DW_OP_breg6 = 0x76, /* Base register 6. */
- DW_OP_breg7 = 0x77, /* Base register 7. */
- DW_OP_breg8 = 0x78, /* Base register 8. */
- DW_OP_breg9 = 0x79, /* Base register 9. */
- DW_OP_breg10 = 0x7a, /* Base register 10. */
- DW_OP_breg11 = 0x7b, /* Base register 11. */
- DW_OP_breg12 = 0x7c, /* Base register 12. */
- DW_OP_breg13 = 0x7d, /* Base register 13. */
- DW_OP_breg14 = 0x7e, /* Base register 14. */
- DW_OP_breg15 = 0x7f, /* Base register 15. */
- DW_OP_breg16 = 0x80, /* Base register 16. */
- DW_OP_breg17 = 0x81, /* Base register 17. */
- DW_OP_breg18 = 0x82, /* Base register 18. */
- DW_OP_breg19 = 0x83, /* Base register 19. */
- DW_OP_breg20 = 0x84, /* Base register 20. */
- DW_OP_breg21 = 0x85, /* Base register 21. */
- DW_OP_breg22 = 0x86, /* Base register 22. */
- DW_OP_breg23 = 0x87, /* Base register 23. */
- DW_OP_breg24 = 0x88, /* Base register 24. */
- DW_OP_breg25 = 0x89, /* Base register 25. */
- DW_OP_breg26 = 0x8a, /* Base register 26. */
- DW_OP_breg27 = 0x8b, /* Base register 27. */
- DW_OP_breg28 = 0x8c, /* Base register 28. */
- DW_OP_breg29 = 0x8d, /* Base register 29. */
- DW_OP_breg30 = 0x8e, /* Base register 30. */
- DW_OP_breg31 = 0x8f, /* Base register 31. */
- DW_OP_regx = 0x90, /* Unsigned LEB128 register. */
- DW_OP_fbreg = 0x91, /* Signed LEB128 offset. */
- DW_OP_bregx = 0x92, /* ULEB128 register followed by SLEB128 off. */
- DW_OP_piece = 0x93, /* ULEB128 size of piece addressed. */
- DW_OP_deref_size = 0x94, /* 1-byte size of data retrieved. */
- DW_OP_xderef_size = 0x95, /* 1-byte size of data retrieved. */
- DW_OP_nop = 0x96,
- DW_OP_push_object_address = 0x97,
- DW_OP_call2 = 0x98,
- DW_OP_call4 = 0x99,
- DW_OP_call_ref = 0x9a,
- DW_OP_form_tls_address = 0x9b,/* TLS offset to address in current thread */
- DW_OP_call_frame_cfa = 0x9c,/* CFA as determined by CFI. */
- DW_OP_bit_piece = 0x9d, /* ULEB128 size and ULEB128 offset in bits. */
- DW_OP_implicit_value = 0x9e, /* DW_FORM_block follows opcode. */
- DW_OP_stack_value = 0x9f, /* No operands, special like DW_OP_piece. */
-
- DW_OP_implicit_pointer = 0xa0,
- DW_OP_addrx = 0xa1,
- DW_OP_constx = 0xa2,
- DW_OP_entry_value = 0xa3,
- DW_OP_const_type = 0xa4,
- DW_OP_regval_type = 0xa5,
- DW_OP_deref_type = 0xa6,
- DW_OP_xderef_type = 0xa7,
- DW_OP_convert = 0xa8,
- DW_OP_reinterpret = 0xa9,
-
- /* GNU extensions. */
- DW_OP_GNU_push_tls_address = 0xe0,
- DW_OP_GNU_uninit = 0xf0,
- DW_OP_GNU_encoded_addr = 0xf1,
- DW_OP_GNU_implicit_pointer = 0xf2,
- DW_OP_GNU_entry_value = 0xf3,
- DW_OP_GNU_const_type = 0xf4,
- DW_OP_GNU_regval_type = 0xf5,
- DW_OP_GNU_deref_type = 0xf6,
- DW_OP_GNU_convert = 0xf7,
- DW_OP_GNU_reinterpret = 0xf9,
- DW_OP_GNU_parameter_ref = 0xfa,
-
- /* GNU Debug Fission extensions. */
- DW_OP_GNU_addr_index = 0xfb,
- DW_OP_GNU_const_index = 0xfc,
-
- DW_OP_GNU_variable_value = 0xfd,
-
- DW_OP_lo_user = 0xe0, /* Implementation-defined range start. */
- DW_OP_hi_user = 0xff /* Implementation-defined range end. */
- };
-
-
-/* DWARF base type encodings. */
-enum
- {
- DW_ATE_void = 0x0,
- DW_ATE_address = 0x1,
- DW_ATE_boolean = 0x2,
- DW_ATE_complex_float = 0x3,
- DW_ATE_float = 0x4,
- DW_ATE_signed = 0x5,
- DW_ATE_signed_char = 0x6,
- DW_ATE_unsigned = 0x7,
- DW_ATE_unsigned_char = 0x8,
- DW_ATE_imaginary_float = 0x9,
- DW_ATE_packed_decimal = 0xa,
- DW_ATE_numeric_string = 0xb,
- DW_ATE_edited = 0xc,
- DW_ATE_signed_fixed = 0xd,
- DW_ATE_unsigned_fixed = 0xe,
- DW_ATE_decimal_float = 0xf,
- DW_ATE_UTF = 0x10,
- DW_ATE_UCS = 0x11,
- DW_ATE_ASCII = 0x12,
-
- DW_ATE_lo_user = 0x80,
- DW_ATE_hi_user = 0xff
- };
-
-
-/* DWARF decimal sign encodings. */
-enum
- {
- DW_DS_unsigned = 1,
- DW_DS_leading_overpunch = 2,
- DW_DS_trailing_overpunch = 3,
- DW_DS_leading_separate = 4,
- DW_DS_trailing_separate = 5,
- };
-
-
-/* DWARF endianity encodings. */
-enum
- {
- DW_END_default = 0,
- DW_END_big = 1,
- DW_END_little = 2,
-
- DW_END_lo_user = 0x40,
- DW_END_hi_user = 0xff
- };
-
-
-/* DWARF accessibility encodings. */
-enum
- {
- DW_ACCESS_public = 1,
- DW_ACCESS_protected = 2,
- DW_ACCESS_private = 3
- };
-
-
-/* DWARF visibility encodings. */
-enum
- {
- DW_VIS_local = 1,
- DW_VIS_exported = 2,
- DW_VIS_qualified = 3
- };
-
-
-/* DWARF virtuality encodings. */
-enum
- {
- DW_VIRTUALITY_none = 0,
- DW_VIRTUALITY_virtual = 1,
- DW_VIRTUALITY_pure_virtual = 2
- };
-
-
-/* DWARF language encodings. */
-enum
- {
- DW_LANG_C89 = 0x0001, /* ISO C:1989 */
- DW_LANG_C = 0x0002, /* C */
- DW_LANG_Ada83 = 0x0003, /* ISO Ada:1983 */
- DW_LANG_C_plus_plus = 0x0004, /* ISO C++:1998 */
- DW_LANG_Cobol74 = 0x0005, /* ISO Cobol:1974 */
- DW_LANG_Cobol85 = 0x0006, /* ISO Cobol:1985 */
- DW_LANG_Fortran77 = 0x0007, /* ISO FORTRAN 77 */
- DW_LANG_Fortran90 = 0x0008, /* ISO Fortran 90 */
- DW_LANG_Pascal83 = 0x0009, /* ISO Pascal:1983 */
- DW_LANG_Modula2 = 0x000a, /* ISO Modula-2:1996 */
- DW_LANG_Java = 0x000b, /* Java */
- DW_LANG_C99 = 0x000c, /* ISO C:1999 */
- DW_LANG_Ada95 = 0x000d, /* ISO Ada:1995 */
- DW_LANG_Fortran95 = 0x000e, /* ISO Fortran 95 */
- DW_LANG_PLI = 0x000f, /* ISO PL/1:1976 */
- DW_LANG_ObjC = 0x0010, /* Objective-C */
- DW_LANG_ObjC_plus_plus = 0x0011, /* Objective-C++ */
- DW_LANG_UPC = 0x0012, /* Unified Parallel C */
- DW_LANG_D = 0x0013, /* D */
- DW_LANG_Python = 0x0014, /* Python */
- DW_LANG_OpenCL = 0x0015, /* OpenCL */
- DW_LANG_Go = 0x0016, /* Go */
- DW_LANG_Modula3 = 0x0017, /* Modula-3 */
- DW_LANG_Haskell = 0x0018, /* Haskell */
- DW_LANG_C_plus_plus_03 = 0x0019, /* ISO C++:2003 */
- DW_LANG_C_plus_plus_11 = 0x001a, /* ISO C++:2011 */
- DW_LANG_OCaml = 0x001b, /* OCaml */
- DW_LANG_Rust = 0x001c, /* Rust */
- DW_LANG_C11 = 0x001d, /* ISO C:2011 */
- DW_LANG_Swift = 0x001e, /* Swift */
- DW_LANG_Julia = 0x001f, /* Julia */
- DW_LANG_Dylan = 0x0020, /* Dylan */
- DW_LANG_C_plus_plus_14 = 0x0021, /* ISO C++:2014 */
- DW_LANG_Fortran03 = 0x0022, /* ISO/IEC 1539-1:2004 */
- DW_LANG_Fortran08 = 0x0023, /* ISO/IEC 1539-1:2010 */
- DW_LANG_RenderScript = 0x0024, /* RenderScript Kernal Language */
- DW_LANG_BLISS = 0x0025, /* BLISS */
-
- DW_LANG_lo_user = 0x8000,
- DW_LANG_Mips_Assembler = 0x8001, /* Assembler */
- DW_LANG_hi_user = 0xffff
- };
-
-/* Old (typo) '1' != 'I'. */
-#define DW_LANG_PL1 DW_LANG_PLI
-
-/* DWARF identifier case encodings. */
-enum
- {
- DW_ID_case_sensitive = 0,
- DW_ID_up_case = 1,
- DW_ID_down_case = 2,
- DW_ID_case_insensitive = 3
- };
-
-
-/* DWARF calling conventions encodings.
- Used as values of DW_AT_calling_convention for subroutines
- (normal, program or nocall) or structures, unions and class types
- (normal, reference or value). */
-enum
- {
- DW_CC_normal = 0x1,
- DW_CC_program = 0x2,
- DW_CC_nocall = 0x3,
- DW_CC_pass_by_reference = 0x4,
- DW_CC_pass_by_value = 0x5,
- DW_CC_lo_user = 0x40,
- DW_CC_hi_user = 0xff
- };
-
-
-/* DWARF inline encodings. */
-enum
- {
- DW_INL_not_inlined = 0,
- DW_INL_inlined = 1,
- DW_INL_declared_not_inlined = 2,
- DW_INL_declared_inlined = 3
- };
-
-
-/* DWARF ordering encodings. */
-enum
- {
- DW_ORD_row_major = 0,
- DW_ORD_col_major = 1
- };
-
-
-/* DWARF discriminant descriptor encodings. */
-enum
- {
- DW_DSC_label = 0,
- DW_DSC_range = 1
- };
-
-/* DWARF defaulted member function encodings. */
-enum
- {
- DW_DEFAULTED_no = 0,
- DW_DEFAULTED_in_class = 1,
- DW_DEFAULTED_out_of_class = 2
- };
-
-/* DWARF line content descriptions. */
-enum
- {
- DW_LNCT_path = 0x1,
- DW_LNCT_directory_index = 0x2,
- DW_LNCT_timestamp = 0x3,
- DW_LNCT_size = 0x4,
- DW_LNCT_MD5 = 0x5,
- DW_LNCT_lo_user = 0x2000,
- DW_LNCT_hi_user = 0x3fff
- };
-
-/* DWARF standard opcode encodings. */
-enum
- {
- DW_LNS_copy = 1,
- DW_LNS_advance_pc = 2,
- DW_LNS_advance_line = 3,
- DW_LNS_set_file = 4,
- DW_LNS_set_column = 5,
- DW_LNS_negate_stmt = 6,
- DW_LNS_set_basic_block = 7,
- DW_LNS_const_add_pc = 8,
- DW_LNS_fixed_advance_pc = 9,
- DW_LNS_set_prologue_end = 10,
- DW_LNS_set_epilogue_begin = 11,
- DW_LNS_set_isa = 12
- };
-
-
-/* DWARF extended opcode encodings. */
-enum
- {
- DW_LNE_end_sequence = 1,
- DW_LNE_set_address = 2,
- DW_LNE_define_file = 3,
- DW_LNE_set_discriminator = 4,
-
- DW_LNE_lo_user = 128,
-
- DW_LNE_NVIDIA_inlined_call = 144,
- DW_LNE_NVIDIA_set_function_name = 145,
-
- DW_LNE_hi_user = 255
- };
-
-
-/* DWARF macinfo type encodings. */
-enum
- {
- DW_MACINFO_define = 1,
- DW_MACINFO_undef = 2,
- DW_MACINFO_start_file = 3,
- DW_MACINFO_end_file = 4,
- DW_MACINFO_vendor_ext = 255
- };
-
-
-/* DWARF debug_macro type encodings. */
-enum
- {
- DW_MACRO_define = 0x01,
- DW_MACRO_undef = 0x02,
- DW_MACRO_start_file = 0x03,
- DW_MACRO_end_file = 0x04,
- DW_MACRO_define_strp = 0x05,
- DW_MACRO_undef_strp = 0x06,
- DW_MACRO_import = 0x07,
- DW_MACRO_define_sup = 0x08,
- DW_MACRO_undef_sup = 0x09,
- DW_MACRO_import_sup = 0x0a,
- DW_MACRO_define_strx = 0x0b,
- DW_MACRO_undef_strx = 0x0c,
- DW_MACRO_lo_user = 0xe0,
- DW_MACRO_hi_user = 0xff
- };
-
-/* Old GNU extension names for DWARF5 debug_macro type encodings.
- There are no equivalents for the supplementary object file (sup)
- and indirect string references (strx). */
-#define DW_MACRO_GNU_define DW_MACRO_define
-#define DW_MACRO_GNU_undef DW_MACRO_undef
-#define DW_MACRO_GNU_start_file DW_MACRO_start_file
-#define DW_MACRO_GNU_end_file DW_MACRO_end_file
-#define DW_MACRO_GNU_define_indirect DW_MACRO_define_strp
-#define DW_MACRO_GNU_undef_indirect DW_MACRO_undef_strp
-#define DW_MACRO_GNU_transparent_include DW_MACRO_import
-#define DW_MACRO_GNU_lo_user DW_MACRO_lo_user
-#define DW_MACRO_GNU_hi_user DW_MACRO_hi_user
-
-
-/* Range list entry encoding. */
-enum
- {
- DW_RLE_end_of_list = 0x0,
- DW_RLE_base_addressx = 0x1,
- DW_RLE_startx_endx = 0x2,
- DW_RLE_startx_length = 0x3,
- DW_RLE_offset_pair = 0x4,
- DW_RLE_base_address = 0x5,
- DW_RLE_start_end = 0x6,
- DW_RLE_start_length = 0x7
- };
-
-
-/* Location list entry encoding. */
-enum
- {
- DW_LLE_end_of_list = 0x0,
- DW_LLE_base_addressx = 0x1,
- DW_LLE_startx_endx = 0x2,
- DW_LLE_startx_length = 0x3,
- DW_LLE_offset_pair = 0x4,
- DW_LLE_default_location = 0x5,
- DW_LLE_base_address = 0x6,
- DW_LLE_start_end = 0x7,
- DW_LLE_start_length = 0x8
- };
-
-
-/* GNU DebugFission list entry encodings (.debug_loc.dwo). */
-enum
- {
- DW_LLE_GNU_end_of_list_entry = 0x0,
- DW_LLE_GNU_base_address_selection_entry = 0x1,
- DW_LLE_GNU_start_end_entry = 0x2,
- DW_LLE_GNU_start_length_entry = 0x3
- };
-
-/* DWARF5 package file section identifiers. */
-enum
- {
- DW_SECT_INFO = 1,
- /* Reserved = 2, */
- DW_SECT_ABBREV = 3,
- DW_SECT_LINE = 4,
- DW_SECT_LOCLISTS = 5,
- DW_SECT_STR_OFFSETS = 6,
- DW_SECT_MACRO = 7,
- DW_SECT_RNGLISTS = 8,
- };
-
-
-/* DWARF call frame instruction encodings. */
-enum
- {
- DW_CFA_advance_loc = 0x40,
- DW_CFA_offset = 0x80,
- DW_CFA_restore = 0xc0,
- DW_CFA_extended = 0,
-
- DW_CFA_nop = 0x00,
- DW_CFA_set_loc = 0x01,
- DW_CFA_advance_loc1 = 0x02,
- DW_CFA_advance_loc2 = 0x03,
- DW_CFA_advance_loc4 = 0x04,
- DW_CFA_offset_extended = 0x05,
- DW_CFA_restore_extended = 0x06,
- DW_CFA_undefined = 0x07,
- DW_CFA_same_value = 0x08,
- DW_CFA_register = 0x09,
- DW_CFA_remember_state = 0x0a,
- DW_CFA_restore_state = 0x0b,
- DW_CFA_def_cfa = 0x0c,
- DW_CFA_def_cfa_register = 0x0d,
- DW_CFA_def_cfa_offset = 0x0e,
- DW_CFA_def_cfa_expression = 0x0f,
- DW_CFA_expression = 0x10,
- DW_CFA_offset_extended_sf = 0x11,
- DW_CFA_def_cfa_sf = 0x12,
- DW_CFA_def_cfa_offset_sf = 0x13,
- DW_CFA_val_offset = 0x14,
- DW_CFA_val_offset_sf = 0x15,
- DW_CFA_val_expression = 0x16,
-
- DW_CFA_low_user = 0x1c,
- DW_CFA_MIPS_advance_loc8 = 0x1d,
- DW_CFA_GNU_window_save = 0x2d,
- DW_CFA_AARCH64_negate_ra_state = 0x2d,
- DW_CFA_GNU_args_size = 0x2e,
- DW_CFA_GNU_negative_offset_extended = 0x2f,
- DW_CFA_high_user = 0x3f
- };
-
-/* ID indicating CIE as opposed to FDE in .debug_frame. */
-enum
- {
- DW_CIE_ID_32 = 0xffffffffU, /* In 32-bit format CIE header. */
- DW_CIE_ID_64 = 0xffffffffffffffffULL /* In 64-bit format CIE header. */
- };
-
-
-/* Information for GNU unwind information. */
-enum
- {
- DW_EH_PE_absptr = 0x00,
- DW_EH_PE_omit = 0xff,
-
- /* FDE data encoding. */
- DW_EH_PE_uleb128 = 0x01,
- DW_EH_PE_udata2 = 0x02,
- DW_EH_PE_udata4 = 0x03,
- DW_EH_PE_udata8 = 0x04,
- DW_EH_PE_sleb128 = 0x09,
- DW_EH_PE_sdata2 = 0x0a,
- DW_EH_PE_sdata4 = 0x0b,
- DW_EH_PE_sdata8 = 0x0c,
- DW_EH_PE_signed = 0x08,
-
- /* FDE flags. */
- DW_EH_PE_pcrel = 0x10,
- DW_EH_PE_textrel = 0x20,
- DW_EH_PE_datarel = 0x30,
- DW_EH_PE_funcrel = 0x40,
- DW_EH_PE_aligned = 0x50,
-
- DW_EH_PE_indirect = 0x80
- };
-
-
-/* DWARF XXX. */
-#define DW_ADDR_none 0
-
-/* Section 7.2.2 of the DWARF3 specification defines a range of escape
- codes that can appear in the length field of certain DWARF structures.
-
- These defines enumerate the minimum and maximum values of this range.
- Currently only the maximum value is used (to indicate that 64-bit
- values are going to be used in the dwarf data that accompanies the
- structure). The other values are reserved.
-
- Note: There is a typo in DWARF3 spec (published Dec 20, 2005). In
- sections 7.4, 7.5.1, 7.19, 7.20 the minimum escape code is referred to
- as 0xffffff00 whereas in fact it should be 0xfffffff0. */
-#define DWARF3_LENGTH_MIN_ESCAPE_CODE 0xfffffff0u
-#define DWARF3_LENGTH_MAX_ESCAPE_CODE 0xffffffffu
-#define DWARF3_LENGTH_64_BIT DWARF3_LENGTH_MAX_ESCAPE_CODE
-
-#endif /* dwarf.h */
diff --git a/tinycc/elf.h b/tinycc/elf.h
deleted file mode 100644
index 14cfdcf..0000000
--- a/tinycc/elf.h
+++ /dev/null
@@ -1,3320 +0,0 @@
-/* This file defines standard ELF types, structures, and macros.
- Copyright (C) 1995-2012 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
-
-#ifndef _ELF_H
-#define _ELF_H 1
-
-#ifndef _WIN32
-#include <inttypes.h>
-#else
-#ifndef __int8_t_defined
-#define __int8_t_defined
-typedef signed char int8_t;
-typedef short int int16_t;
-typedef int int32_t;
-typedef long long int int64_t;
-typedef unsigned char uint8_t;
-typedef unsigned short int uint16_t;
-typedef unsigned int uint32_t;
-typedef unsigned long long int uint64_t;
-#endif
-#endif
-
-/* Standard ELF types. */
-
-/* Type for a 16-bit quantity. */
-typedef uint16_t Elf32_Half;
-typedef uint16_t Elf64_Half;
-
-/* Types for signed and unsigned 32-bit quantities. */
-typedef uint32_t Elf32_Word;
-typedef int32_t Elf32_Sword;
-typedef uint32_t Elf64_Word;
-typedef int32_t Elf64_Sword;
-
-/* Types for signed and unsigned 64-bit quantities. */
-typedef uint64_t Elf32_Xword;
-typedef int64_t Elf32_Sxword;
-typedef uint64_t Elf64_Xword;
-typedef int64_t Elf64_Sxword;
-
-/* Type of addresses. */
-typedef uint32_t Elf32_Addr;
-typedef uint64_t Elf64_Addr;
-
-/* Type of file offsets. */
-typedef uint32_t Elf32_Off;
-typedef uint64_t Elf64_Off;
-
-/* Type for section indices, which are 16-bit quantities. */
-typedef uint16_t Elf32_Section;
-typedef uint16_t Elf64_Section;
-
-/* Type for version symbol information. */
-typedef Elf32_Half Elf32_Versym;
-typedef Elf64_Half Elf64_Versym;
-
-
-/* The ELF file header. This appears at the start of every ELF file. */
-
-#define EI_NIDENT (16)
-
-typedef struct
-{
- unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
- Elf32_Half e_type; /* Object file type */
- Elf32_Half e_machine; /* Architecture */
- Elf32_Word e_version; /* Object file version */
- Elf32_Addr e_entry; /* Entry point virtual address */
- Elf32_Off e_phoff; /* Program header table file offset */
- Elf32_Off e_shoff; /* Section header table file offset */
- Elf32_Word e_flags; /* Processor-specific flags */
- Elf32_Half e_ehsize; /* ELF header size in bytes */
- Elf32_Half e_phentsize; /* Program header table entry size */
- Elf32_Half e_phnum; /* Program header table entry count */
- Elf32_Half e_shentsize; /* Section header table entry size */
- Elf32_Half e_shnum; /* Section header table entry count */
- Elf32_Half e_shstrndx; /* Section header string table index */
-} Elf32_Ehdr;
-
-typedef struct
-{
- unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
- Elf64_Half e_type; /* Object file type */
- Elf64_Half e_machine; /* Architecture */
- Elf64_Word e_version; /* Object file version */
- Elf64_Addr e_entry; /* Entry point virtual address */
- Elf64_Off e_phoff; /* Program header table file offset */
- Elf64_Off e_shoff; /* Section header table file offset */
- Elf64_Word e_flags; /* Processor-specific flags */
- Elf64_Half e_ehsize; /* ELF header size in bytes */
- Elf64_Half e_phentsize; /* Program header table entry size */
- Elf64_Half e_phnum; /* Program header table entry count */
- Elf64_Half e_shentsize; /* Section header table entry size */
- Elf64_Half e_shnum; /* Section header table entry count */
- Elf64_Half e_shstrndx; /* Section header string table index */
-} Elf64_Ehdr;
-
-/* Fields in the e_ident array. The EI_* macros are indices into the
- array. The macros under each EI_* macro are the values the byte
- may have. */
-
-#define EI_MAG0 0 /* File identification byte 0 index */
-#define ELFMAG0 0x7f /* Magic number byte 0 */
-
-#define EI_MAG1 1 /* File identification byte 1 index */
-#define ELFMAG1 'E' /* Magic number byte 1 */
-
-#define EI_MAG2 2 /* File identification byte 2 index */
-#define ELFMAG2 'L' /* Magic number byte 2 */
-
-#define EI_MAG3 3 /* File identification byte 3 index */
-#define ELFMAG3 'F' /* Magic number byte 3 */
-
-/* Conglomeration of the identification bytes, for easy testing as a word. */
-#define ELFMAG "\177ELF"
-#define SELFMAG 4
-
-#define EI_CLASS 4 /* File class byte index */
-#define ELFCLASSNONE 0 /* Invalid class */
-#define ELFCLASS32 1 /* 32-bit objects */
-#define ELFCLASS64 2 /* 64-bit objects */
-#define ELFCLASSNUM 3
-
-#define EI_DATA 5 /* Data encoding byte index */
-#define ELFDATANONE 0 /* Invalid data encoding */
-#define ELFDATA2LSB 1 /* 2's complement, little endian */
-#define ELFDATA2MSB 2 /* 2's complement, big endian */
-#define ELFDATANUM 3
-
-#define EI_VERSION 6 /* File version byte index */
- /* Value must be EV_CURRENT */
-
-#define EI_OSABI 7 /* OS ABI identification */
-#define ELFOSABI_NONE 0 /* UNIX System V ABI */
-#define ELFOSABI_SYSV 0 /* Alias. */
-#define ELFOSABI_HPUX 1 /* HP-UX */
-#define ELFOSABI_NETBSD 2 /* NetBSD. */
-#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */
-#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */
-#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */
-#define ELFOSABI_AIX 7 /* IBM AIX. */
-#define ELFOSABI_IRIX 8 /* SGI Irix. */
-#define ELFOSABI_FREEBSD 9 /* FreeBSD. */
-#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */
-#define ELFOSABI_MODESTO 11 /* Novell Modesto. */
-#define ELFOSABI_OPENBSD 12 /* OpenBSD. */
-#define ELFOSABI_OPENVMS 13
-#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel. */
-#define ELFOSABI_AROS 15 /* Amiga Research OS. */
-#define ELFOSABI_FENIXOS 16 /* FenixOS. */
-#define ELFOSABI_ARM_AEABI 64 /* ARM EABI. */
-#define ELFOSABI_C6000_LINUX 65 /* Linux TMS320C6000. */
-#define ELFOSABI_ARM 97 /* ARM */
-#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
-
-#define EI_ABIVERSION 8 /* ABI version */
-
-#define EI_PAD 9 /* Byte index of padding bytes */
-
-/* Legal values for e_type (object file type). */
-
-#define ET_NONE 0 /* No file type */
-#define ET_REL 1 /* Relocatable file */
-#define ET_EXEC 2 /* Executable file */
-#define ET_DYN 3 /* Shared object file */
-#define ET_CORE 4 /* Core file */
-#define ET_NUM 5 /* Number of defined types */
-#define ET_LOOS 0xfe00 /* OS-specific range start */
-#define ET_HIOS 0xfeff /* OS-specific range end */
-#define ET_LOPROC 0xff00 /* Processor-specific range start */
-#define ET_HIPROC 0xffff /* Processor-specific range end */
-
-/* Legal values for e_machine (architecture). */
-
-#define EM_NONE 0 /* No machine */
-#define EM_M32 1 /* AT&T WE 32100 */
-#define EM_SPARC 2 /* SUN SPARC */
-#define EM_386 3 /* Intel 80386 */
-#define EM_68K 4 /* Motorola m68k family */
-#define EM_88K 5 /* Motorola m88k family */
-#define EM_860 7 /* Intel 80860 */
-#define EM_MIPS 8 /* MIPS R3000 big-endian */
-#define EM_S370 9 /* IBM System/370 */
-#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
-
-#define EM_PARISC 15 /* HPPA */
-#define EM_VPP500 17 /* Fujitsu VPP500 */
-#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
-#define EM_960 19 /* Intel 80960 */
-#define EM_PPC 20 /* PowerPC */
-#define EM_PPC64 21 /* PowerPC 64-bit */
-#define EM_S390 22 /* IBM S390 */
-
-#define EM_V800 36 /* NEC V800 series */
-#define EM_FR20 37 /* Fujitsu FR20 */
-#define EM_RH32 38 /* TRW RH-32 */
-#define EM_RCE 39 /* Motorola RCE */
-#define EM_ARM 40 /* ARM */
-#define EM_FAKE_ALPHA 41 /* Digital Alpha */
-#define EM_SH 42 /* Hitachi SH */
-#define EM_SPARCV9 43 /* SPARC v9 64-bit */
-#define EM_TRICORE 44 /* Siemens Tricore */
-#define EM_ARC 45 /* Argonaut RISC Core */
-#define EM_H8_300 46 /* Hitachi H8/300 */
-#define EM_H8_300H 47 /* Hitachi H8/300H */
-#define EM_H8S 48 /* Hitachi H8S */
-#define EM_H8_500 49 /* Hitachi H8/500 */
-#define EM_IA_64 50 /* Intel Merced */
-#define EM_MIPS_X 51 /* Stanford MIPS-X */
-#define EM_COLDFIRE 52 /* Motorola Coldfire */
-#define EM_68HC12 53 /* Motorola M68HC12 */
-#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/
-#define EM_PCP 55 /* Siemens PCP */
-#define EM_NCPU 56 /* Sony nCPU embedded RISC */
-#define EM_NDR1 57 /* Denso NDR1 microprocessor */
-#define EM_STARCORE 58 /* Motorola Start*Core processor */
-#define EM_ME16 59 /* Toyota ME16 processor */
-#define EM_ST100 60 /* STMicroelectronic ST100 processor */
-#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/
-#define EM_X86_64 62 /* AMD x86-64 architecture */
-#define EM_PDSP 63 /* Sony DSP Processor */
-
-#define EM_FX66 66 /* Siemens FX66 microcontroller */
-#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */
-#define EM_ST7 68 /* STMicroelectronics ST7 8 bit mc */
-#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */
-#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */
-#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */
-#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */
-#define EM_SVX 73 /* Silicon Graphics SVx */
-#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */
-#define EM_VAX 75 /* Digital VAX */
-#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */
-#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */
-#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */
-#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */
-#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */
-#define EM_HUANY 81 /* Harvard University machine-independent object files */
-#define EM_PRISM 82 /* SiTera Prism */
-#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */
-#define EM_FR30 84 /* Fujitsu FR30 */
-#define EM_D10V 85 /* Mitsubishi D10V */
-#define EM_D30V 86 /* Mitsubishi D30V */
-#define EM_V850 87 /* NEC v850 */
-#define EM_M32R 88 /* Mitsubishi M32R */
-#define EM_MN10300 89 /* Matsushita MN10300 */
-#define EM_MN10200 90 /* Matsushita MN10200 */
-#define EM_PJ 91 /* picoJava */
-#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
-#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */
-#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */
-#define EM_AARCH64 183 /* ARM AARCH64 */
-#define EM_TILEPRO 188 /* Tilera TILEPro */
-#define EM_TILEGX 191 /* Tilera TILE-Gx */
-#define EM_RISCV 243 /* RISC-V */
-#define EM_NUM 253
-
-/* If it is necessary to assign new unofficial EM_* values, please
- pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
- chances of collision with official or non-GNU unofficial values. */
-
-#define EM_ALPHA 0x9026
-#define EM_C60 0x9c60
-
-/* Legal values for e_version (version). */
-
-#define EV_NONE 0 /* Invalid ELF version */
-#define EV_CURRENT 1 /* Current version */
-#define EV_NUM 2
-
-/* Section header. */
-
-typedef struct
-{
- Elf32_Word sh_name; /* Section name (string tbl index) */
- Elf32_Word sh_type; /* Section type */
- Elf32_Word sh_flags; /* Section flags */
- Elf32_Addr sh_addr; /* Section virtual addr at execution */
- Elf32_Off sh_offset; /* Section file offset */
- Elf32_Word sh_size; /* Section size in bytes */
- Elf32_Word sh_link; /* Link to another section */
- Elf32_Word sh_info; /* Additional section information */
- Elf32_Word sh_addralign; /* Section alignment */
- Elf32_Word sh_entsize; /* Entry size if section holds table */
-} Elf32_Shdr;
-
-typedef struct
-{
- Elf64_Word sh_name; /* Section name (string tbl index) */
- Elf64_Word sh_type; /* Section type */
- Elf64_Xword sh_flags; /* Section flags */
- Elf64_Addr sh_addr; /* Section virtual addr at execution */
- Elf64_Off sh_offset; /* Section file offset */
- Elf64_Xword sh_size; /* Section size in bytes */
- Elf64_Word sh_link; /* Link to another section */
- Elf64_Word sh_info; /* Additional section information */
- Elf64_Xword sh_addralign; /* Section alignment */
- Elf64_Xword sh_entsize; /* Entry size if section holds table */
-} Elf64_Shdr;
-
-/* Special section indices. */
-
-#define SHN_UNDEF 0 /* Undefined section */
-#define SHN_LORESERVE 0xff00 /* Start of reserved indices */
-#define SHN_LOPROC 0xff00 /* Start of processor-specific */
-#define SHN_BEFORE 0xff00 /* Order section before all others
- (Solaris). */
-#define SHN_AFTER 0xff01 /* Order section after all others
- (Solaris). */
-#define SHN_HIPROC 0xff1f /* End of processor-specific */
-#define SHN_LOOS 0xff20 /* Start of OS-specific */
-#define SHN_HIOS 0xff3f /* End of OS-specific */
-#define SHN_ABS 0xfff1 /* Associated symbol is absolute */
-#define SHN_COMMON 0xfff2 /* Associated symbol is common */
-#define SHN_XINDEX 0xffff /* Index is in extra table. */
-#define SHN_HIRESERVE 0xffff /* End of reserved indices */
-
-/* Legal values for sh_type (section type). */
-
-#define SHT_NULL 0 /* Section header table entry unused */
-#define SHT_PROGBITS 1 /* Program data */
-#define SHT_SYMTAB 2 /* Symbol table */
-#define SHT_STRTAB 3 /* String table */
-#define SHT_RELA 4 /* Relocation entries with addends */
-#define SHT_HASH 5 /* Symbol hash table */
-#define SHT_DYNAMIC 6 /* Dynamic linking information */
-#define SHT_NOTE 7 /* Notes */
-#define SHT_NOBITS 8 /* Program space with no data (bss) */
-#define SHT_REL 9 /* Relocation entries, no addends */
-#define SHT_SHLIB 10 /* Reserved */
-#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
-#define SHT_INIT_ARRAY 14 /* Array of constructors */
-#define SHT_FINI_ARRAY 15 /* Array of destructors */
-#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
-#define SHT_GROUP 17 /* Section group */
-#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */
-#define SHT_NUM 19 /* Number of defined types. */
-#define SHT_LOOS 0x60000000 /* Start OS-specific. */
-#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */
-#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
-#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
-#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
-#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */
-#define SHT_SUNW_move 0x6ffffffa
-#define SHT_SUNW_COMDAT 0x6ffffffb
-#define SHT_SUNW_syminfo 0x6ffffffc
-#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */
-#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */
-#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */
-#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */
-#define SHT_HIOS 0x6fffffff /* End OS-specific type */
-#define SHT_LOPROC 0x70000000 /* Start of processor-specific */
-#define SHT_HIPROC 0x7fffffff /* End of processor-specific */
-#define SHT_LOUSER 0x80000000 /* Start of application-specific */
-#define SHT_HIUSER 0x8fffffff /* End of application-specific */
-
-/* Legal values for sh_flags (section flags). */
-
-#define SHF_WRITE (1 << 0) /* Writable */
-#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
-#define SHF_EXECINSTR (1 << 2) /* Executable */
-#define SHF_MERGE (1 << 4) /* Might be merged */
-#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
-#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */
-#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */
-#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling
- required */
-#define SHF_GROUP (1 << 9) /* Section is member of a group. */
-#define SHF_TLS (1 << 10) /* Section hold thread-local data. */
-#define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */
-#define SHF_MASKOS 0x0ff00000 /* OS-specific. */
-#define SHF_MASKPROC 0xf0000000 /* Processor-specific */
-#define SHF_ORDERED (1 << 30) /* Special ordering requirement
- (Solaris). */
-#define SHF_EXCLUDE (1U << 31) /* Section is excluded unless
- referenced or allocated (Solaris).*/
-
-/* Section group handling. */
-#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */
-
-/* Symbol table entry. */
-
-typedef struct
-{
- Elf32_Word st_name; /* Symbol name (string tbl index) */
- Elf32_Addr st_value; /* Symbol value */
- Elf32_Word st_size; /* Symbol size */
- unsigned char st_info; /* Symbol type and binding */
- unsigned char st_other; /* Symbol visibility */
- Elf32_Section st_shndx; /* Section index */
-} Elf32_Sym;
-
-typedef struct
-{
- Elf64_Word st_name; /* Symbol name (string tbl index) */
- unsigned char st_info; /* Symbol type and binding */
- unsigned char st_other; /* Symbol visibility */
- Elf64_Section st_shndx; /* Section index */
- Elf64_Addr st_value; /* Symbol value */
- Elf64_Xword st_size; /* Symbol size */
-} Elf64_Sym;
-
-/* The syminfo section if available contains additional information about
- every dynamic symbol. */
-
-typedef struct
-{
- Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
- Elf32_Half si_flags; /* Per symbol flags */
-} Elf32_Syminfo;
-
-typedef struct
-{
- Elf64_Half si_boundto; /* Direct bindings, symbol bound to */
- Elf64_Half si_flags; /* Per symbol flags */
-} Elf64_Syminfo;
-
-/* Possible values for si_boundto. */
-#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */
-#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */
-#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */
-
-/* Possible bitmasks for si_flags. */
-#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */
-#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */
-#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */
-#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy
- loaded */
-/* Syminfo version values. */
-#define SYMINFO_NONE 0
-#define SYMINFO_CURRENT 1
-#define SYMINFO_NUM 2
-
-
-/* How to extract and insert information held in the st_info field. */
-
-#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4)
-#define ELF32_ST_TYPE(val) ((val) & 0xf)
-#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
-
-/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */
-#define ELF64_ST_BIND(val) ELF32_ST_BIND (val)
-#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val)
-#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type))
-
-/* Legal values for ST_BIND subfield of st_info (symbol binding). */
-
-#define STB_LOCAL 0 /* Local symbol */
-#define STB_GLOBAL 1 /* Global symbol */
-#define STB_WEAK 2 /* Weak symbol */
-#define STB_NUM 3 /* Number of defined types. */
-#define STB_LOOS 10 /* Start of OS-specific */
-#define STB_GNU_UNIQUE 10 /* Unique symbol. */
-#define STB_HIOS 12 /* End of OS-specific */
-#define STB_LOPROC 13 /* Start of processor-specific */
-#define STB_HIPROC 15 /* End of processor-specific */
-
-/* Legal values for ST_TYPE subfield of st_info (symbol type). */
-
-#define STT_NOTYPE 0 /* Symbol type is unspecified */
-#define STT_OBJECT 1 /* Symbol is a data object */
-#define STT_FUNC 2 /* Symbol is a code object */
-#define STT_SECTION 3 /* Symbol associated with a section */
-#define STT_FILE 4 /* Symbol's name is file name */
-#define STT_COMMON 5 /* Symbol is a common data object */
-#define STT_TLS 6 /* Symbol is thread-local data object*/
-#define STT_NUM 7 /* Number of defined types. */
-#define STT_LOOS 10 /* Start of OS-specific */
-#define STT_GNU_IFUNC 10 /* Symbol is indirect code object */
-#define STT_HIOS 12 /* End of OS-specific */
-#define STT_LOPROC 13 /* Start of processor-specific */
-#define STT_HIPROC 15 /* End of processor-specific */
-
-
-/* Symbol table indices are found in the hash buckets and chain table
- of a symbol hash table section. This special index value indicates
- the end of a chain, meaning no further symbols are found in that bucket. */
-
-#define STN_UNDEF 0 /* End of a chain. */
-
-
-/* How to extract and insert information held in the st_other field. */
-
-#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
-
-/* For ELF64 the definitions are the same. */
-#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
-
-/* Symbol visibility specification encoded in the st_other field. */
-#define STV_DEFAULT 0 /* Default symbol visibility rules */
-#define STV_INTERNAL 1 /* Processor specific hidden class */
-#define STV_HIDDEN 2 /* Sym unavailable in other modules */
-#define STV_PROTECTED 3 /* Not preemptible, not exported */
-
-
-/* Relocation table entry without addend (in section of type SHT_REL). */
-
-typedef struct
-{
- Elf32_Addr r_offset; /* Address */
- Elf32_Word r_info; /* Relocation type and symbol index */
-} Elf32_Rel;
-
-/* I have seen two different definitions of the Elf64_Rel and
- Elf64_Rela structures, so we'll leave them out until Novell (or
- whoever) gets their act together. */
-/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
-
-typedef struct
-{
- Elf64_Addr r_offset; /* Address */
- Elf64_Xword r_info; /* Relocation type and symbol index */
-} Elf64_Rel;
-
-/* Relocation table entry with addend (in section of type SHT_RELA). */
-
-typedef struct
-{
- Elf32_Addr r_offset; /* Address */
- Elf32_Word r_info; /* Relocation type and symbol index */
- Elf32_Sword r_addend; /* Addend */
-} Elf32_Rela;
-
-typedef struct
-{
- Elf64_Addr r_offset; /* Address */
- Elf64_Xword r_info; /* Relocation type and symbol index */
- Elf64_Sxword r_addend; /* Addend */
-} Elf64_Rela;
-
-/* How to extract and insert information held in the r_info field. */
-
-#define ELF32_R_SYM(val) ((val) >> 8)
-#define ELF32_R_TYPE(val) ((val) & 0xff)
-#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
-
-#define ELF64_R_SYM(i) ((i) >> 32)
-#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
-#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type))
-
-/* Program segment header. */
-
-typedef struct
-{
- Elf32_Word p_type; /* Segment type */
- Elf32_Off p_offset; /* Segment file offset */
- Elf32_Addr p_vaddr; /* Segment virtual address */
- Elf32_Addr p_paddr; /* Segment physical address */
- Elf32_Word p_filesz; /* Segment size in file */
- Elf32_Word p_memsz; /* Segment size in memory */
- Elf32_Word p_flags; /* Segment flags */
- Elf32_Word p_align; /* Segment alignment */
-} Elf32_Phdr;
-
-typedef struct
-{
- Elf64_Word p_type; /* Segment type */
- Elf64_Word p_flags; /* Segment flags */
- Elf64_Off p_offset; /* Segment file offset */
- Elf64_Addr p_vaddr; /* Segment virtual address */
- Elf64_Addr p_paddr; /* Segment physical address */
- Elf64_Xword p_filesz; /* Segment size in file */
- Elf64_Xword p_memsz; /* Segment size in memory */
- Elf64_Xword p_align; /* Segment alignment */
-} Elf64_Phdr;
-
-/* Special value for e_phnum. This indicates that the real number of
- program headers is too large to fit into e_phnum. Instead the real
- value is in the field sh_info of section 0. */
-
-#define PN_XNUM 0xffff
-
-/* Legal values for p_type (segment type). */
-
-#define PT_NULL 0 /* Program header table entry unused */
-#define PT_LOAD 1 /* Loadable program segment */
-#define PT_DYNAMIC 2 /* Dynamic linking information */
-#define PT_INTERP 3 /* Program interpreter */
-#define PT_NOTE 4 /* Auxiliary information */
-#define PT_SHLIB 5 /* Reserved */
-#define PT_PHDR 6 /* Entry for header table itself */
-#define PT_TLS 7 /* Thread-local storage segment */
-#define PT_NUM 8 /* Number of defined types */
-#define PT_LOOS 0x60000000 /* Start of OS-specific */
-#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
-#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
-#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
-#define PT_LOSUNW 0x6ffffffa
-#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
-#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */
-#define PT_HISUNW 0x6fffffff
-#define PT_HIOS 0x6fffffff /* End of OS-specific */
-#define PT_LOPROC 0x70000000 /* Start of processor-specific */
-#define PT_HIPROC 0x7fffffff /* End of processor-specific */
-
-/* Legal values for p_flags (segment flags). */
-
-#define PF_X (1 << 0) /* Segment is executable */
-#define PF_W (1 << 1) /* Segment is writable */
-#define PF_R (1 << 2) /* Segment is readable */
-#define PF_MASKOS 0x0ff00000 /* OS-specific */
-#define PF_MASKPROC 0xf0000000 /* Processor-specific */
-
-/* Legal values for note segment descriptor types for core files. */
-
-#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */
-#define NT_FPREGSET 2 /* Contains copy of fpregset struct */
-#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
-#define NT_PRXREG 4 /* Contains copy of prxregset struct */
-#define NT_TASKSTRUCT 4 /* Contains copy of task structure */
-#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */
-#define NT_AUXV 6 /* Contains copy of auxv array */
-#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */
-#define NT_ASRS 8 /* Contains copy of asrset struct */
-#define NT_PSTATUS 10 /* Contains copy of pstatus struct */
-#define NT_PSINFO 13 /* Contains copy of psinfo struct */
-#define NT_PRCRED 14 /* Contains copy of prcred struct */
-#define NT_UTSNAME 15 /* Contains copy of utsname struct */
-#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */
-#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */
-#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */
-#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */
-#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
-#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */
-#define NT_PPC_VSX 0x102 /* PowerPC VSX registers */
-#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
-#define NT_386_IOPERM 0x201 /* x86 io permission bitmap (1=deny) */
-#define NT_X86_XSTATE 0x202 /* x86 extended state using xsave */
-#define NT_S390_HIGH_GPRS 0x300 /* s390 upper register halves */
-#define NT_S390_TIMER 0x301 /* s390 timer register */
-#define NT_S390_TODCMP 0x302 /* s390 TOD clock comparator register */
-#define NT_S390_TODPREG 0x303 /* s390 TOD programmable register */
-#define NT_S390_CTRS 0x304 /* s390 control registers */
-#define NT_S390_PREFIX 0x305 /* s390 prefix register */
-#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */
-#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */
-#define NT_ARM_VFP 0x400 /* ARM VFP/NEON registers */
-#define NT_ARM_TLS 0x401 /* ARM TLS register */
-#define NT_ARM_HW_BREAK 0x402 /* ARM hardware breakpoint registers */
-#define NT_ARM_HW_WATCH 0x403 /* ARM hardware watchpoint registers */
-
-/* Legal values for the note segment descriptor types for object files. */
-
-#define NT_VERSION 1 /* Contains a version string. */
-
-
-/* Dynamic section entry. */
-
-typedef struct
-{
- Elf32_Sword d_tag; /* Dynamic entry type */
- union
- {
- Elf32_Word d_val; /* Integer value */
- Elf32_Addr d_ptr; /* Address value */
- } d_un;
-} Elf32_Dyn;
-
-typedef struct
-{
- Elf64_Sxword d_tag; /* Dynamic entry type */
- union
- {
- Elf64_Xword d_val; /* Integer value */
- Elf64_Addr d_ptr; /* Address value */
- } d_un;
-} Elf64_Dyn;
-
-/* Legal values for d_tag (dynamic entry type). */
-
-#define DT_NULL 0 /* Marks end of dynamic section */
-#define DT_NEEDED 1 /* Name of needed library */
-#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
-#define DT_PLTGOT 3 /* Processor defined value */
-#define DT_HASH 4 /* Address of symbol hash table */
-#define DT_STRTAB 5 /* Address of string table */
-#define DT_SYMTAB 6 /* Address of symbol table */
-#define DT_RELA 7 /* Address of Rela relocs */
-#define DT_RELASZ 8 /* Total size of Rela relocs */
-#define DT_RELAENT 9 /* Size of one Rela reloc */
-#define DT_STRSZ 10 /* Size of string table */
-#define DT_SYMENT 11 /* Size of one symbol table entry */
-#define DT_INIT 12 /* Address of init function */
-#define DT_FINI 13 /* Address of termination function */
-#define DT_SONAME 14 /* Name of shared object */
-#define DT_RPATH 15 /* Library search path (deprecated) */
-#define DT_SYMBOLIC 16 /* Start symbol search here */
-#define DT_REL 17 /* Address of Rel relocs */
-#define DT_RELSZ 18 /* Total size of Rel relocs */
-#define DT_RELENT 19 /* Size of one Rel reloc */
-#define DT_PLTREL 20 /* Type of reloc in PLT */
-#define DT_DEBUG 21 /* For debugging; unspecified */
-#define DT_TEXTREL 22 /* Reloc might modify .text */
-#define DT_JMPREL 23 /* Address of PLT relocs */
-#define DT_BIND_NOW 24 /* Process relocations of object */
-#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
-#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
-#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
-#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
-#define DT_RUNPATH 29 /* Library search path */
-#define DT_FLAGS 30 /* Flags for the object being loaded */
-#define DT_ENCODING 32 /* Start of encoded range */
-#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
-#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
-#define DT_NUM 34 /* Number used */
-#define DT_LOOS 0x6000000d /* Start of OS-specific */
-#define DT_HIOS 0x6ffff000 /* End of OS-specific */
-#define DT_LOPROC 0x70000000 /* Start of processor-specific */
-#define DT_HIPROC 0x7fffffff /* End of processor-specific */
-#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */
-
-/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
- Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's
- approach. */
-#define DT_VALRNGLO 0x6ffffd00
-#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */
-#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */
-#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */
-#define DT_CHECKSUM 0x6ffffdf8
-#define DT_PLTPADSZ 0x6ffffdf9
-#define DT_MOVEENT 0x6ffffdfa
-#define DT_MOVESZ 0x6ffffdfb
-#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */
-#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting
- the following DT_* entry. */
-#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
-#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */
-#define DT_VALRNGHI 0x6ffffdff
-#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */
-#define DT_VALNUM 12
-
-/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
- Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
-
- If any adjustment is made to the ELF object after it has been
- built these entries will need to be adjusted. */
-#define DT_ADDRRNGLO 0x6ffffe00
-#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */
-#define DT_TLSDESC_PLT 0x6ffffef6
-#define DT_TLSDESC_GOT 0x6ffffef7
-#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */
-#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */
-#define DT_CONFIG 0x6ffffefa /* Configuration information. */
-#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */
-#define DT_AUDIT 0x6ffffefc /* Object auditing. */
-#define DT_PLTPAD 0x6ffffefd /* PLT padding. */
-#define DT_MOVETAB 0x6ffffefe /* Move table. */
-#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */
-#define DT_ADDRRNGHI 0x6ffffeff
-#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */
-#define DT_ADDRNUM 11
-
-/* The versioning entry types. The next are defined as part of the
- GNU extension. */
-#define DT_VERSYM 0x6ffffff0
-
-#define DT_RELACOUNT 0x6ffffff9
-#define DT_RELCOUNT 0x6ffffffa
-
-/* These were chosen by Sun. */
-#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
-#define DT_VERDEF 0x6ffffffc /* Address of version definition
- table */
-#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
-#define DT_VERNEED 0x6ffffffe /* Address of table with needed
- versions */
-#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
-#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
-#define DT_VERSIONTAGNUM 16
-
-/* Sun added these machine-independent extensions in the "processor-specific"
- range. Be compatible. */
-#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */
-#define DT_FILTER 0x7fffffff /* Shared object to get values from */
-#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
-#define DT_EXTRANUM 3
-
-/* Values of `d_un.d_val' in the DT_FLAGS entry. */
-#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */
-#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */
-#define DF_TEXTREL 0x00000004 /* Object contains text relocations */
-#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */
-#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */
-
-/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
- entry in the dynamic section. */
-#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */
-#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */
-#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */
-#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/
-#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/
-#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/
-#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */
-#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */
-#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */
-#define DF_1_TRANS 0x00000200
-#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */
-#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */
-#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */
-#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/
-#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */
-#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */
-#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */
-#define DF_1_NODIRECT 0x00020000 /* Object has no-direct binding. */
-#define DF_1_IGNMULDEF 0x00040000
-#define DF_1_NOKSYMS 0x00080000
-#define DF_1_NOHDR 0x00100000
-#define DF_1_EDITED 0x00200000 /* Object is modified after built. */
-#define DF_1_NORELOC 0x00400000
-#define DF_1_SYMINTPOSE 0x00800000 /* Object has individual interposers. */
-#define DF_1_GLOBAUDIT 0x01000000 /* Global auditing required. */
-#define DF_1_SINGLETON 0x02000000 /* Singleton symbols are used. */
-#define DF_1_PIE 0x08000000
-
-/* Flags for the feature selection in DT_FEATURE_1. */
-#define DTF_1_PARINIT 0x00000001
-#define DTF_1_CONFEXP 0x00000002
-
-/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */
-#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */
-#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not
- generally available. */
-
-/* Version definition sections. */
-
-typedef struct
-{
- Elf32_Half vd_version; /* Version revision */
- Elf32_Half vd_flags; /* Version information */
- Elf32_Half vd_ndx; /* Version Index */
- Elf32_Half vd_cnt; /* Number of associated aux entries */
- Elf32_Word vd_hash; /* Version name hash value */
- Elf32_Word vd_aux; /* Offset in bytes to verdaux array */
- Elf32_Word vd_next; /* Offset in bytes to next verdef
- entry */
-} Elf32_Verdef;
-
-typedef struct
-{
- Elf64_Half vd_version; /* Version revision */
- Elf64_Half vd_flags; /* Version information */
- Elf64_Half vd_ndx; /* Version Index */
- Elf64_Half vd_cnt; /* Number of associated aux entries */
- Elf64_Word vd_hash; /* Version name hash value */
- Elf64_Word vd_aux; /* Offset in bytes to verdaux array */
- Elf64_Word vd_next; /* Offset in bytes to next verdef
- entry */
-} Elf64_Verdef;
-
-
-/* Legal values for vd_version (version revision). */
-#define VER_DEF_NONE 0 /* No version */
-#define VER_DEF_CURRENT 1 /* Current version */
-#define VER_DEF_NUM 2 /* Given version number */
-
-/* Legal values for vd_flags (version information flags). */
-#define VER_FLG_BASE 0x1 /* Version definition of file itself */
-#define VER_FLG_WEAK 0x2 /* Weak version identifier */
-
-/* Versym symbol index values. */
-#define VER_NDX_LOCAL 0 /* Symbol is local. */
-#define VER_NDX_GLOBAL 1 /* Symbol is global. */
-#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */
-#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */
-
-/* Auxiliary version information. */
-
-typedef struct
-{
- Elf32_Word vda_name; /* Version or dependency names */
- Elf32_Word vda_next; /* Offset in bytes to next verdaux
- entry */
-} Elf32_Verdaux;
-
-typedef struct
-{
- Elf64_Word vda_name; /* Version or dependency names */
- Elf64_Word vda_next; /* Offset in bytes to next verdaux
- entry */
-} Elf64_Verdaux;
-
-
-/* Version dependency section. */
-
-typedef struct
-{
- Elf32_Half vn_version; /* Version of structure */
- Elf32_Half vn_cnt; /* Number of associated aux entries */
- Elf32_Word vn_file; /* Offset of filename for this
- dependency */
- Elf32_Word vn_aux; /* Offset in bytes to vernaux array */
- Elf32_Word vn_next; /* Offset in bytes to next verneed
- entry */
-} Elf32_Verneed;
-
-typedef struct
-{
- Elf64_Half vn_version; /* Version of structure */
- Elf64_Half vn_cnt; /* Number of associated aux entries */
- Elf64_Word vn_file; /* Offset of filename for this
- dependency */
- Elf64_Word vn_aux; /* Offset in bytes to vernaux array */
- Elf64_Word vn_next; /* Offset in bytes to next verneed
- entry */
-} Elf64_Verneed;
-
-
-/* Legal values for vn_version (version revision). */
-#define VER_NEED_NONE 0 /* No version */
-#define VER_NEED_CURRENT 1 /* Current version */
-#define VER_NEED_NUM 2 /* Given version number */
-
-/* Auxiliary needed version information. */
-
-typedef struct
-{
- Elf32_Word vna_hash; /* Hash value of dependency name */
- Elf32_Half vna_flags; /* Dependency specific information */
- Elf32_Half vna_other; /* Unused */
- Elf32_Word vna_name; /* Dependency name string offset */
- Elf32_Word vna_next; /* Offset in bytes to next vernaux
- entry */
-} Elf32_Vernaux;
-
-typedef struct
-{
- Elf64_Word vna_hash; /* Hash value of dependency name */
- Elf64_Half vna_flags; /* Dependency specific information */
- Elf64_Half vna_other; /* Unused */
- Elf64_Word vna_name; /* Dependency name string offset */
- Elf64_Word vna_next; /* Offset in bytes to next vernaux
- entry */
-} Elf64_Vernaux;
-
-
-/* Legal values for vna_flags. */
-#define VER_FLG_WEAK 0x2 /* Weak version identifier */
-
-
-/* Auxiliary vector. */
-
-/* This vector is normally only used by the program interpreter. The
- usual definition in an ABI supplement uses the name auxv_t. The
- vector is not usually defined in a standard <elf.h> file, but it
- can't hurt. We rename it to avoid conflicts. The sizes of these
- types are an arrangement between the exec server and the program
- interpreter, so we don't fully specify them here. */
-
-typedef struct
-{
- uint32_t a_type; /* Entry type */
- union
- {
- uint32_t a_val; /* Integer value */
- /* We use to have pointer elements added here. We cannot do that,
- though, since it does not work when using 32-bit definitions
- on 64-bit platforms and vice versa. */
- } a_un;
-} Elf32_auxv_t;
-
-typedef struct
-{
- uint64_t a_type; /* Entry type */
- union
- {
- uint64_t a_val; /* Integer value */
- /* We use to have pointer elements added here. We cannot do that,
- though, since it does not work when using 32-bit definitions
- on 64-bit platforms and vice versa. */
- } a_un;
-} Elf64_auxv_t;
-
-/* Legal values for a_type (entry type). */
-
-#define AT_NULL 0 /* End of vector */
-#define AT_IGNORE 1 /* Entry should be ignored */
-#define AT_EXECFD 2 /* File descriptor of program */
-#define AT_PHDR 3 /* Program headers for program */
-#define AT_PHENT 4 /* Size of program header entry */
-#define AT_PHNUM 5 /* Number of program headers */
-#define AT_PAGESZ 6 /* System page size */
-#define AT_BASE 7 /* Base address of interpreter */
-#define AT_FLAGS 8 /* Flags */
-#define AT_ENTRY 9 /* Entry point of program */
-#define AT_NOTELF 10 /* Program is not ELF */
-#define AT_UID 11 /* Real uid */
-#define AT_EUID 12 /* Effective uid */
-#define AT_GID 13 /* Real gid */
-#define AT_EGID 14 /* Effective gid */
-#define AT_CLKTCK 17 /* Frequency of times() */
-
-/* Some more special a_type values describing the hardware. */
-#define AT_PLATFORM 15 /* String identifying platform. */
-#define AT_HWCAP 16 /* Machine dependent hints about
- processor capabilities. */
-
-/* This entry gives some information about the FPU initialization
- performed by the kernel. */
-#define AT_FPUCW 18 /* Used FPU control word. */
-
-/* Cache block sizes. */
-#define AT_DCACHEBSIZE 19 /* Data cache block size. */
-#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */
-#define AT_UCACHEBSIZE 21 /* Unified cache block size. */
-
-/* A special ignored value for PPC, used by the kernel to control the
- interpretation of the AUXV. Must be > 16. */
-#define AT_IGNOREPPC 22 /* Entry should be ignored. */
-
-#define AT_SECURE 23 /* Boolean, was exec setuid-like? */
-
-#define AT_BASE_PLATFORM 24 /* String identifying real platforms.*/
-
-#define AT_RANDOM 25 /* Address of 16 random bytes. */
-
-#define AT_EXECFN 31 /* Filename of executable. */
-
-/* Pointer to the global system page used for system calls and other
- nice things. */
-#define AT_SYSINFO 32
-#define AT_SYSINFO_EHDR 33
-
-/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains
- log2 of line size; mask those to get cache size. */
-#define AT_L1I_CACHESHAPE 34
-#define AT_L1D_CACHESHAPE 35
-#define AT_L2_CACHESHAPE 36
-#define AT_L3_CACHESHAPE 37
-
-/* Note section contents. Each entry in the note section begins with
- a header of a fixed form. */
-
-typedef struct
-{
- Elf32_Word n_namesz; /* Length of the note's name. */
- Elf32_Word n_descsz; /* Length of the note's descriptor. */
- Elf32_Word n_type; /* Type of the note. */
-} Elf32_Nhdr;
-
-typedef struct
-{
- Elf64_Word n_namesz; /* Length of the note's name. */
- Elf64_Word n_descsz; /* Length of the note's descriptor. */
- Elf64_Word n_type; /* Type of the note. */
-} Elf64_Nhdr;
-
-/* Known names of notes. */
-
-/* Solaris entries in the note section have this name. */
-#define ELF_NOTE_SOLARIS "SUNW Solaris"
-
-/* Note entries for GNU systems have this name. */
-#define ELF_NOTE_GNU "GNU"
-
-
-/* Defined types of notes for Solaris. */
-
-/* Value of descriptor (one word) is desired pagesize for the binary. */
-#define ELF_NOTE_PAGESIZE_HINT 1
-
-
-/* Defined note types for GNU systems. */
-
-/* ABI information. The descriptor consists of words:
- word 0: OS descriptor
- word 1: major version of the ABI
- word 2: minor version of the ABI
- word 3: subminor version of the ABI
-*/
-#define NT_GNU_ABI_TAG 1
-#define ELF_NOTE_ABI NT_GNU_ABI_TAG /* Old name. */
-
-/* Known OSes. These values can appear in word 0 of an
- NT_GNU_ABI_TAG note section entry. */
-#define ELF_NOTE_OS_LINUX 0
-#define ELF_NOTE_OS_GNU 1
-#define ELF_NOTE_OS_SOLARIS2 2
-#define ELF_NOTE_OS_FREEBSD 3
-
-/* Synthetic hwcap information. The descriptor begins with two words:
- word 0: number of entries
- word 1: bitmask of enabled entries
- Then follow variable-length entries, one byte followed by a
- '\0'-terminated hwcap name string. The byte gives the bit
- number to test if enabled, (1U << bit) & bitmask. */
-#define NT_GNU_HWCAP 2
-
-/* Build ID bits as generated by ld --build-id.
- The descriptor consists of any nonzero number of bytes. */
-#define NT_GNU_BUILD_ID 3
-
-/* Version note generated by GNU gold containing a version string. */
-#define NT_GNU_GOLD_VERSION 4
-
-
-/* Move records. */
-typedef struct
-{
- Elf32_Xword m_value; /* Symbol value. */
- Elf32_Word m_info; /* Size and index. */
- Elf32_Word m_poffset; /* Symbol offset. */
- Elf32_Half m_repeat; /* Repeat count. */
- Elf32_Half m_stride; /* Stride info. */
-} Elf32_Move;
-
-typedef struct
-{
- Elf64_Xword m_value; /* Symbol value. */
- Elf64_Xword m_info; /* Size and index. */
- Elf64_Xword m_poffset; /* Symbol offset. */
- Elf64_Half m_repeat; /* Repeat count. */
- Elf64_Half m_stride; /* Stride info. */
-} Elf64_Move;
-
-/* Macro to construct move records. */
-#define ELF32_M_SYM(info) ((info) >> 8)
-#define ELF32_M_SIZE(info) ((unsigned char) (info))
-#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size))
-
-#define ELF64_M_SYM(info) ELF32_M_SYM (info)
-#define ELF64_M_SIZE(info) ELF32_M_SIZE (info)
-#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size)
-
-
-/* Motorola 68k specific definitions. */
-
-/* Values for Elf32_Ehdr.e_flags. */
-#define EF_CPU32 0x00810000
-
-/* m68k relocs. */
-
-#define R_68K_NONE 0 /* No reloc */
-#define R_68K_32 1 /* Direct 32 bit */
-#define R_68K_16 2 /* Direct 16 bit */
-#define R_68K_8 3 /* Direct 8 bit */
-#define R_68K_PC32 4 /* PC relative 32 bit */
-#define R_68K_PC16 5 /* PC relative 16 bit */
-#define R_68K_PC8 6 /* PC relative 8 bit */
-#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */
-#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */
-#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */
-#define R_68K_GOT32O 10 /* 32 bit GOT offset */
-#define R_68K_GOT16O 11 /* 16 bit GOT offset */
-#define R_68K_GOT8O 12 /* 8 bit GOT offset */
-#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */
-#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */
-#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */
-#define R_68K_PLT32O 16 /* 32 bit PLT offset */
-#define R_68K_PLT16O 17 /* 16 bit PLT offset */
-#define R_68K_PLT8O 18 /* 8 bit PLT offset */
-#define R_68K_COPY 19 /* Copy symbol at runtime */
-#define R_68K_GLOB_DAT 20 /* Create GOT entry */
-#define R_68K_JMP_SLOT 21 /* Create PLT entry */
-#define R_68K_RELATIVE 22 /* Adjust by program base */
-#define R_68K_TLS_GD32 25 /* 32 bit GOT offset for GD */
-#define R_68K_TLS_GD16 26 /* 16 bit GOT offset for GD */
-#define R_68K_TLS_GD8 27 /* 8 bit GOT offset for GD */
-#define R_68K_TLS_LDM32 28 /* 32 bit GOT offset for LDM */
-#define R_68K_TLS_LDM16 29 /* 16 bit GOT offset for LDM */
-#define R_68K_TLS_LDM8 30 /* 8 bit GOT offset for LDM */
-#define R_68K_TLS_LDO32 31 /* 32 bit module-relative offset */
-#define R_68K_TLS_LDO16 32 /* 16 bit module-relative offset */
-#define R_68K_TLS_LDO8 33 /* 8 bit module-relative offset */
-#define R_68K_TLS_IE32 34 /* 32 bit GOT offset for IE */
-#define R_68K_TLS_IE16 35 /* 16 bit GOT offset for IE */
-#define R_68K_TLS_IE8 36 /* 8 bit GOT offset for IE */
-#define R_68K_TLS_LE32 37 /* 32 bit offset relative to
- static TLS block */
-#define R_68K_TLS_LE16 38 /* 16 bit offset relative to
- static TLS block */
-#define R_68K_TLS_LE8 39 /* 8 bit offset relative to
- static TLS block */
-#define R_68K_TLS_DTPMOD32 40 /* 32 bit module number */
-#define R_68K_TLS_DTPREL32 41 /* 32 bit module-relative offset */
-#define R_68K_TLS_TPREL32 42 /* 32 bit TP-relative offset */
-/* Keep this the last entry. */
-#define R_68K_NUM 43
-
-/* Intel 80386 specific definitions. */
-
-/* i386 relocs. */
-
-#define R_386_NONE 0 /* No reloc */
-#define R_386_32 1 /* Direct 32 bit */
-#define R_386_PC32 2 /* PC relative 32 bit */
-#define R_386_GOT32 3 /* 32 bit GOT entry */
-#define R_386_PLT32 4 /* 32 bit PLT address */
-#define R_386_COPY 5 /* Copy symbol at runtime */
-#define R_386_GLOB_DAT 6 /* Create GOT entry */
-#define R_386_JMP_SLOT 7 /* Create PLT entry */
-#define R_386_RELATIVE 8 /* Adjust by program base */
-#define R_386_GOTOFF 9 /* 32 bit offset to GOT */
-#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */
-#define R_386_32PLT 11
-#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */
-#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS
- block offset */
-#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block
- offset */
-#define R_386_TLS_LE 17 /* Offset relative to static TLS
- block */
-#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of
- general dynamic thread local data */
-#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of
- local dynamic thread local data
- in LE code */
-#define R_386_16 20
-#define R_386_PC16 21
-#define R_386_8 22
-#define R_386_PC8 23
-#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic
- thread local data */
-#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */
-#define R_386_TLS_GD_CALL 26 /* Relocation for call to
- __tls_get_addr() */
-#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */
-#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic
- thread local data in LE code */
-#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */
-#define R_386_TLS_LDM_CALL 30 /* Relocation for call to
- __tls_get_addr() in LDM code */
-#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */
-#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */
-#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS
- block offset */
-#define R_386_TLS_LE_32 34 /* Negated offset relative to static
- TLS block */
-#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */
-#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */
-#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */
-/* 38? */
-#define R_386_TLS_GOTDESC 39 /* GOT offset for TLS descriptor. */
-#define R_386_TLS_DESC_CALL 40 /* Marker of call through TLS
- descriptor for
- relaxation. */
-#define R_386_TLS_DESC 41 /* TLS descriptor containing
- pointer to code and to
- argument, returning the TLS
- offset for the symbol. */
-#define R_386_IRELATIVE 42 /* Adjust indirectly by program base */
-#define R_386_GOT32X 43 /* 32 bit GOT entry, relaxable */
-/* Keep this the last entry. */
-#define R_386_NUM 44
-
-/* SUN SPARC specific definitions. */
-
-/* Legal values for ST_TYPE subfield of st_info (symbol type). */
-
-#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */
-
-/* Values for Elf64_Ehdr.e_flags. */
-
-#define EF_SPARCV9_MM 3
-#define EF_SPARCV9_TSO 0
-#define EF_SPARCV9_PSO 1
-#define EF_SPARCV9_RMO 2
-#define EF_SPARC_LEDATA 0x800000 /* little endian data */
-#define EF_SPARC_EXT_MASK 0xFFFF00
-#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */
-#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */
-#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */
-#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */
-
-/* SPARC relocs. */
-
-#define R_SPARC_NONE 0 /* No reloc */
-#define R_SPARC_8 1 /* Direct 8 bit */
-#define R_SPARC_16 2 /* Direct 16 bit */
-#define R_SPARC_32 3 /* Direct 32 bit */
-#define R_SPARC_DISP8 4 /* PC relative 8 bit */
-#define R_SPARC_DISP16 5 /* PC relative 16 bit */
-#define R_SPARC_DISP32 6 /* PC relative 32 bit */
-#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */
-#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */
-#define R_SPARC_HI22 9 /* High 22 bit */
-#define R_SPARC_22 10 /* Direct 22 bit */
-#define R_SPARC_13 11 /* Direct 13 bit */
-#define R_SPARC_LO10 12 /* Truncated 10 bit */
-#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */
-#define R_SPARC_GOT13 14 /* 13 bit GOT entry */
-#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */
-#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */
-#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */
-#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */
-#define R_SPARC_COPY 19 /* Copy symbol at runtime */
-#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */
-#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */
-#define R_SPARC_RELATIVE 22 /* Adjust by program base */
-#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */
-
-/* Additional Sparc64 relocs. */
-
-#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */
-#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */
-#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */
-#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */
-#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */
-#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */
-#define R_SPARC_10 30 /* Direct 10 bit */
-#define R_SPARC_11 31 /* Direct 11 bit */
-#define R_SPARC_64 32 /* Direct 64 bit */
-#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */
-#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */
-#define R_SPARC_HM10 35 /* High middle 10 bits of ... */
-#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */
-#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */
-#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */
-#define R_SPARC_PC_LM22 39 /* Low middle 22 bits of ... */
-#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */
-#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */
-#define R_SPARC_GLOB_JMP 42 /* was part of v9 ABI but was removed */
-#define R_SPARC_7 43 /* Direct 7 bit */
-#define R_SPARC_5 44 /* Direct 5 bit */
-#define R_SPARC_6 45 /* Direct 6 bit */
-#define R_SPARC_DISP64 46 /* PC relative 64 bit */
-#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */
-#define R_SPARC_HIX22 48 /* High 22 bit complemented */
-#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */
-#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */
-#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */
-#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */
-#define R_SPARC_REGISTER 53 /* Global register usage */
-#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */
-#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */
-#define R_SPARC_TLS_GD_HI22 56
-#define R_SPARC_TLS_GD_LO10 57
-#define R_SPARC_TLS_GD_ADD 58
-#define R_SPARC_TLS_GD_CALL 59
-#define R_SPARC_TLS_LDM_HI22 60
-#define R_SPARC_TLS_LDM_LO10 61
-#define R_SPARC_TLS_LDM_ADD 62
-#define R_SPARC_TLS_LDM_CALL 63
-#define R_SPARC_TLS_LDO_HIX22 64
-#define R_SPARC_TLS_LDO_LOX10 65
-#define R_SPARC_TLS_LDO_ADD 66
-#define R_SPARC_TLS_IE_HI22 67
-#define R_SPARC_TLS_IE_LO10 68
-#define R_SPARC_TLS_IE_LD 69
-#define R_SPARC_TLS_IE_LDX 70
-#define R_SPARC_TLS_IE_ADD 71
-#define R_SPARC_TLS_LE_HIX22 72
-#define R_SPARC_TLS_LE_LOX10 73
-#define R_SPARC_TLS_DTPMOD32 74
-#define R_SPARC_TLS_DTPMOD64 75
-#define R_SPARC_TLS_DTPOFF32 76
-#define R_SPARC_TLS_DTPOFF64 77
-#define R_SPARC_TLS_TPOFF32 78
-#define R_SPARC_TLS_TPOFF64 79
-#define R_SPARC_GOTDATA_HIX22 80
-#define R_SPARC_GOTDATA_LOX10 81
-#define R_SPARC_GOTDATA_OP_HIX22 82
-#define R_SPARC_GOTDATA_OP_LOX10 83
-#define R_SPARC_GOTDATA_OP 84
-#define R_SPARC_H34 85
-#define R_SPARC_SIZE32 86
-#define R_SPARC_SIZE64 87
-#define R_SPARC_WDISP10 88
-#define R_SPARC_JMP_IREL 248
-#define R_SPARC_IRELATIVE 249
-#define R_SPARC_GNU_VTINHERIT 250
-#define R_SPARC_GNU_VTENTRY 251
-#define R_SPARC_REV32 252
-/* Keep this the last entry. */
-#define R_SPARC_NUM 253
-
-/* For Sparc64, legal values for d_tag of Elf64_Dyn. */
-
-#define DT_SPARC_REGISTER 0x70000001
-#define DT_SPARC_NUM 2
-
-/* MIPS R3000 specific definitions. */
-
-/* Legal values for e_flags field of Elf32_Ehdr. */
-
-#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */
-#define EF_MIPS_PIC 2 /* Contains PIC code */
-#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */
-#define EF_MIPS_XGOT 8
-#define EF_MIPS_64BIT_WHIRL 16
-#define EF_MIPS_ABI2 32
-#define EF_MIPS_ABI_ON32 64
-#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */
-
-/* Legal values for MIPS architecture level. */
-
-#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
-#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
-#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
-#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
-#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
-#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */
-#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */
-
-/* The following are non-official names and should not be used. */
-
-#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */
-#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */
-#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */
-#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */
-#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */
-#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */
-#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */
-
-/* Special section indices. */
-
-#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */
-#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */
-#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */
-#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */
-#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */
-
-/* Legal values for sh_type field of Elf32_Shdr. */
-
-#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */
-#define SHT_MIPS_MSYM 0x70000001
-#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */
-#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */
-#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */
-#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/
-#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */
-#define SHT_MIPS_PACKAGE 0x70000007
-#define SHT_MIPS_PACKSYM 0x70000008
-#define SHT_MIPS_RELD 0x70000009
-#define SHT_MIPS_IFACE 0x7000000b
-#define SHT_MIPS_CONTENT 0x7000000c
-#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */
-#define SHT_MIPS_SHDR 0x70000010
-#define SHT_MIPS_FDESC 0x70000011
-#define SHT_MIPS_EXTSYM 0x70000012
-#define SHT_MIPS_DENSE 0x70000013
-#define SHT_MIPS_PDESC 0x70000014
-#define SHT_MIPS_LOCSYM 0x70000015
-#define SHT_MIPS_AUXSYM 0x70000016
-#define SHT_MIPS_OPTSYM 0x70000017
-#define SHT_MIPS_LOCSTR 0x70000018
-#define SHT_MIPS_LINE 0x70000019
-#define SHT_MIPS_RFDESC 0x7000001a
-#define SHT_MIPS_DELTASYM 0x7000001b
-#define SHT_MIPS_DELTAINST 0x7000001c
-#define SHT_MIPS_DELTACLASS 0x7000001d
-#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */
-#define SHT_MIPS_DELTADECL 0x7000001f
-#define SHT_MIPS_SYMBOL_LIB 0x70000020
-#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */
-#define SHT_MIPS_TRANSLATE 0x70000022
-#define SHT_MIPS_PIXIE 0x70000023
-#define SHT_MIPS_XLATE 0x70000024
-#define SHT_MIPS_XLATE_DEBUG 0x70000025
-#define SHT_MIPS_WHIRL 0x70000026
-#define SHT_MIPS_EH_REGION 0x70000027
-#define SHT_MIPS_XLATE_OLD 0x70000028
-#define SHT_MIPS_PDR_EXCEPTION 0x70000029
-
-/* Legal values for sh_flags field of Elf32_Shdr. */
-
-#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */
-#define SHF_MIPS_MERGE 0x20000000
-#define SHF_MIPS_ADDR 0x40000000
-#define SHF_MIPS_STRINGS 0x80000000
-#define SHF_MIPS_NOSTRIP 0x08000000
-#define SHF_MIPS_LOCAL 0x04000000
-#define SHF_MIPS_NAMES 0x02000000
-#define SHF_MIPS_NODUPE 0x01000000
-
-
-/* Symbol tables. */
-
-/* MIPS specific values for `st_other'. */
-#define STO_MIPS_DEFAULT 0x0
-#define STO_MIPS_INTERNAL 0x1
-#define STO_MIPS_HIDDEN 0x2
-#define STO_MIPS_PROTECTED 0x3
-#define STO_MIPS_PLT 0x8
-#define STO_MIPS_SC_ALIGN_UNUSED 0xff
-
-/* MIPS specific values for `st_info'. */
-#define STB_MIPS_SPLIT_COMMON 13
-
-/* Entries found in sections of type SHT_MIPS_GPTAB. */
-
-typedef union
-{
- struct
- {
- Elf32_Word gt_current_g_value; /* -G value used for compilation */
- Elf32_Word gt_unused; /* Not used */
- } gt_header; /* First entry in section */
- struct
- {
- Elf32_Word gt_g_value; /* If this value were used for -G */
- Elf32_Word gt_bytes; /* This many bytes would be used */
- } gt_entry; /* Subsequent entries in section */
-} Elf32_gptab;
-
-/* Entry found in sections of type SHT_MIPS_REGINFO. */
-
-typedef struct
-{
- Elf32_Word ri_gprmask; /* General registers used */
- Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */
- Elf32_Sword ri_gp_value; /* $gp register value */
-} Elf32_RegInfo;
-
-/* Entries found in sections of type SHT_MIPS_OPTIONS. */
-
-typedef struct
-{
- unsigned char kind; /* Determines interpretation of the
- variable part of descriptor. */
- unsigned char size; /* Size of descriptor, including header. */
- Elf32_Section section; /* Section header index of section affected,
- 0 for global options. */
- Elf32_Word info; /* Kind-specific information. */
-} Elf_Options;
-
-/* Values for `kind' field in Elf_Options. */
-
-#define ODK_NULL 0 /* Undefined. */
-#define ODK_REGINFO 1 /* Register usage information. */
-#define ODK_EXCEPTIONS 2 /* Exception processing options. */
-#define ODK_PAD 3 /* Section padding options. */
-#define ODK_HWPATCH 4 /* Hardware workarounds performed */
-#define ODK_FILL 5 /* record the fill value used by the linker. */
-#define ODK_TAGS 6 /* reserve space for desktop tools to write. */
-#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */
-#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */
-
-/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */
-
-#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */
-#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */
-#define OEX_PAGE0 0x10000 /* page zero must be mapped. */
-#define OEX_SMM 0x20000 /* Force sequential memory mode? */
-#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */
-#define OEX_PRECISEFP OEX_FPDBUG
-#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */
-
-#define OEX_FPU_INVAL 0x10
-#define OEX_FPU_DIV0 0x08
-#define OEX_FPU_OFLO 0x04
-#define OEX_FPU_UFLO 0x02
-#define OEX_FPU_INEX 0x01
-
-/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */
-
-#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */
-#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */
-#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */
-#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */
-
-#define OPAD_PREFIX 0x1
-#define OPAD_POSTFIX 0x2
-#define OPAD_SYMBOL 0x4
-
-/* Entry found in `.options' section. */
-
-typedef struct
-{
- Elf32_Word hwp_flags1; /* Extra flags. */
- Elf32_Word hwp_flags2; /* Extra flags. */
-} Elf_Options_Hw;
-
-/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */
-
-#define OHWA0_R4KEOP_CHECKED 0x00000001
-#define OHWA1_R4KEOP_CLEAN 0x00000002
-
-/* MIPS relocs. */
-
-#define R_MIPS_NONE 0 /* No reloc */
-#define R_MIPS_16 1 /* Direct 16 bit */
-#define R_MIPS_32 2 /* Direct 32 bit */
-#define R_MIPS_REL32 3 /* PC relative 32 bit */
-#define R_MIPS_26 4 /* Direct 26 bit shifted */
-#define R_MIPS_HI16 5 /* High 16 bit */
-#define R_MIPS_LO16 6 /* Low 16 bit */
-#define R_MIPS_GPREL16 7 /* GP relative 16 bit */
-#define R_MIPS_LITERAL 8 /* 16 bit literal entry */
-#define R_MIPS_GOT16 9 /* 16 bit GOT entry */
-#define R_MIPS_PC16 10 /* PC relative 16 bit */
-#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */
-#define R_MIPS_GPREL32 12 /* GP relative 32 bit */
-
-#define R_MIPS_SHIFT5 16
-#define R_MIPS_SHIFT6 17
-#define R_MIPS_64 18
-#define R_MIPS_GOT_DISP 19
-#define R_MIPS_GOT_PAGE 20
-#define R_MIPS_GOT_OFST 21
-#define R_MIPS_GOT_HI16 22
-#define R_MIPS_GOT_LO16 23
-#define R_MIPS_SUB 24
-#define R_MIPS_INSERT_A 25
-#define R_MIPS_INSERT_B 26
-#define R_MIPS_DELETE 27
-#define R_MIPS_HIGHER 28
-#define R_MIPS_HIGHEST 29
-#define R_MIPS_CALL_HI16 30
-#define R_MIPS_CALL_LO16 31
-#define R_MIPS_SCN_DISP 32
-#define R_MIPS_REL16 33
-#define R_MIPS_ADD_IMMEDIATE 34
-#define R_MIPS_PJUMP 35
-#define R_MIPS_RELGOT 36
-#define R_MIPS_JALR 37
-#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */
-#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */
-#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */
-#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */
-#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */
-#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */
-#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */
-#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */
-#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */
-#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */
-#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */
-#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */
-#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */
-#define R_MIPS_GLOB_DAT 51
-#define R_MIPS_COPY 126
-#define R_MIPS_JUMP_SLOT 127
-/* Keep this the last entry. */
-#define R_MIPS_NUM 128
-
-/* Legal values for p_type field of Elf32_Phdr. */
-
-#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */
-#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */
-#define PT_MIPS_OPTIONS 0x70000002
-
-/* Special program header types. */
-
-#define PF_MIPS_LOCAL 0x10000000
-
-/* Legal values for d_tag field of Elf32_Dyn. */
-
-#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */
-#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */
-#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */
-#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */
-#define DT_MIPS_FLAGS 0x70000005 /* Flags */
-#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */
-#define DT_MIPS_MSYM 0x70000007
-#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */
-#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */
-#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */
-#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */
-#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */
-#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */
-#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */
-#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */
-#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */
-#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */
-#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */
-#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in
- DT_MIPS_DELTA_CLASS. */
-#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */
-#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
- DT_MIPS_DELTA_INSTANCE. */
-#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */
-#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
- DT_MIPS_DELTA_RELOC. */
-#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta
- relocations refer to. */
-#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
- DT_MIPS_DELTA_SYM. */
-#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
- class declaration. */
-#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
- DT_MIPS_DELTA_CLASSSYM. */
-#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */
-#define DT_MIPS_PIXIE_INIT 0x70000023
-#define DT_MIPS_SYMBOL_LIB 0x70000024
-#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
-#define DT_MIPS_LOCAL_GOTIDX 0x70000026
-#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
-#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
-#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */
-#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */
-#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
-#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
-#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
- function stored in GOT. */
-#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added
- by rld on dlopen() calls. */
-#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
-#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */
-#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */
-/* The address of .got.plt in an executable using the new non-PIC ABI. */
-#define DT_MIPS_PLTGOT 0x70000032
-/* The base of the PLT in an executable using the new non-PIC ABI if that
- PLT is writable. For a non-writable PLT, this is omitted or has a zero
- value. */
-#define DT_MIPS_RWPLT 0x70000034
-#define DT_MIPS_NUM 0x35
-
-/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */
-
-#define RHF_NONE 0 /* No flags */
-#define RHF_QUICKSTART (1 << 0) /* Use quickstart */
-#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */
-#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */
-#define RHF_NO_MOVE (1 << 3)
-#define RHF_SGI_ONLY (1 << 4)
-#define RHF_GUARANTEE_INIT (1 << 5)
-#define RHF_DELTA_C_PLUS_PLUS (1 << 6)
-#define RHF_GUARANTEE_START_INIT (1 << 7)
-#define RHF_PIXIE (1 << 8)
-#define RHF_DEFAULT_DELAY_LOAD (1 << 9)
-#define RHF_REQUICKSTART (1 << 10)
-#define RHF_REQUICKSTARTED (1 << 11)
-#define RHF_CORD (1 << 12)
-#define RHF_NO_UNRES_UNDEF (1 << 13)
-#define RHF_RLD_ORDER_SAFE (1 << 14)
-
-/* Entries found in sections of type SHT_MIPS_LIBLIST. */
-
-typedef struct
-{
- Elf32_Word l_name; /* Name (string table index) */
- Elf32_Word l_time_stamp; /* Timestamp */
- Elf32_Word l_checksum; /* Checksum */
- Elf32_Word l_version; /* Interface version */
- Elf32_Word l_flags; /* Flags */
-} Elf32_Lib;
-
-typedef struct
-{
- Elf64_Word l_name; /* Name (string table index) */
- Elf64_Word l_time_stamp; /* Timestamp */
- Elf64_Word l_checksum; /* Checksum */
- Elf64_Word l_version; /* Interface version */
- Elf64_Word l_flags; /* Flags */
-} Elf64_Lib;
-
-
-/* Legal values for l_flags. */
-
-#define LL_NONE 0
-#define LL_EXACT_MATCH (1 << 0) /* Require exact match */
-#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */
-#define LL_REQUIRE_MINOR (1 << 2)
-#define LL_EXPORTS (1 << 3)
-#define LL_DELAY_LOAD (1 << 4)
-#define LL_DELTA (1 << 5)
-
-/* Entries found in sections of type SHT_MIPS_CONFLICT. */
-
-typedef Elf32_Addr Elf32_Conflict;
-
-
-/* HPPA specific definitions. */
-
-/* Legal values for e_flags field of Elf32_Ehdr. */
-
-#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */
-#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */
-#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */
-#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */
-#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch
- prediction. */
-#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */
-#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */
-
-/* Defined values for `e_flags & EF_PARISC_ARCH' are: */
-
-#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */
-#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */
-#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */
-
-/* Additional section indices. */
-
-#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tentatively declared
- symbols in ANSI C. */
-#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */
-
-/* Legal values for sh_type field of Elf32_Shdr. */
-
-#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */
-#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */
-#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */
-
-/* Legal values for sh_flags field of Elf32_Shdr. */
-
-#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */
-#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */
-#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */
-
-/* Legal values for ST_TYPE subfield of st_info (symbol type). */
-
-#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */
-
-#define STT_HP_OPAQUE (STT_LOOS + 0x1)
-#define STT_HP_STUB (STT_LOOS + 0x2)
-
-/* HPPA relocs. */
-
-#define R_PARISC_NONE 0 /* No reloc. */
-#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */
-#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */
-#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */
-#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */
-#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */
-#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */
-#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */
-#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */
-#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */
-#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */
-#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */
-#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */
-#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */
-#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */
-#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */
-#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */
-#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */
-#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */
-#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */
-#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */
-#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */
-#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */
-#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */
-#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */
-#define R_PARISC_FPTR64 64 /* 64 bits function address. */
-#define R_PARISC_PLABEL32 65 /* 32 bits function address. */
-#define R_PARISC_PLABEL21L 66 /* Left 21 bits of fdesc address. */
-#define R_PARISC_PLABEL14R 70 /* Right 14 bits of fdesc address. */
-#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */
-#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */
-#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */
-#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */
-#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */
-#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */
-#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */
-#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */
-#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */
-#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */
-#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */
-#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */
-#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */
-#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */
-#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */
-#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */
-#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */
-#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */
-#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */
-#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */
-#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */
-#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */
-#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */
-#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */
-#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */
-#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */
-#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */
-#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */
-#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */
-#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */
-#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */
-#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */
-#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */
-#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */
-#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */
-#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */
-#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */
-#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */
-#define R_PARISC_LORESERVE 128
-#define R_PARISC_COPY 128 /* Copy relocation. */
-#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */
-#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */
-#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */
-#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */
-#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */
-#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */
-#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/
-#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */
-#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */
-#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */
-#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */
-#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */
-#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */
-#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */
-#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */
-#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/
-#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/
-#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */
-#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */
-#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */
-#define R_PARISC_GNU_VTENTRY 232
-#define R_PARISC_GNU_VTINHERIT 233
-#define R_PARISC_TLS_GD21L 234 /* GD 21-bit left. */
-#define R_PARISC_TLS_GD14R 235 /* GD 14-bit right. */
-#define R_PARISC_TLS_GDCALL 236 /* GD call to __t_g_a. */
-#define R_PARISC_TLS_LDM21L 237 /* LD module 21-bit left. */
-#define R_PARISC_TLS_LDM14R 238 /* LD module 14-bit right. */
-#define R_PARISC_TLS_LDMCALL 239 /* LD module call to __t_g_a. */
-#define R_PARISC_TLS_LDO21L 240 /* LD offset 21-bit left. */
-#define R_PARISC_TLS_LDO14R 241 /* LD offset 14-bit right. */
-#define R_PARISC_TLS_DTPMOD32 242 /* DTP module 32-bit. */
-#define R_PARISC_TLS_DTPMOD64 243 /* DTP module 64-bit. */
-#define R_PARISC_TLS_DTPOFF32 244 /* DTP offset 32-bit. */
-#define R_PARISC_TLS_DTPOFF64 245 /* DTP offset 32-bit. */
-#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L
-#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R
-#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L
-#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R
-#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32
-#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64
-#define R_PARISC_HIRESERVE 255
-
-/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */
-
-#define PT_HP_TLS (PT_LOOS + 0x0)
-#define PT_HP_CORE_NONE (PT_LOOS + 0x1)
-#define PT_HP_CORE_VERSION (PT_LOOS + 0x2)
-#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3)
-#define PT_HP_CORE_COMM (PT_LOOS + 0x4)
-#define PT_HP_CORE_PROC (PT_LOOS + 0x5)
-#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6)
-#define PT_HP_CORE_STACK (PT_LOOS + 0x7)
-#define PT_HP_CORE_SHM (PT_LOOS + 0x8)
-#define PT_HP_CORE_MMF (PT_LOOS + 0x9)
-#define PT_HP_PARALLEL (PT_LOOS + 0x10)
-#define PT_HP_FASTBIND (PT_LOOS + 0x11)
-#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12)
-#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13)
-#define PT_HP_STACK (PT_LOOS + 0x14)
-
-#define PT_PARISC_ARCHEXT 0x70000000
-#define PT_PARISC_UNWIND 0x70000001
-
-/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */
-
-#define PF_PARISC_SBP 0x08000000
-
-#define PF_HP_PAGE_SIZE 0x00100000
-#define PF_HP_FAR_SHARED 0x00200000
-#define PF_HP_NEAR_SHARED 0x00400000
-#define PF_HP_CODE 0x01000000
-#define PF_HP_MODIFY 0x02000000
-#define PF_HP_LAZYSWAP 0x04000000
-#define PF_HP_SBP 0x08000000
-
-
-/* Alpha specific definitions. */
-
-/* Legal values for e_flags field of Elf64_Ehdr. */
-
-#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */
-#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */
-
-/* Legal values for sh_type field of Elf64_Shdr. */
-
-/* These two are primarily concerned with ECOFF debugging info. */
-#define SHT_ALPHA_DEBUG 0x70000001
-#define SHT_ALPHA_REGINFO 0x70000002
-
-/* Legal values for sh_flags field of Elf64_Shdr. */
-
-#define SHF_ALPHA_GPREL 0x10000000
-
-/* Legal values for st_other field of Elf64_Sym. */
-#define STO_ALPHA_NOPV 0x80 /* No PV required. */
-#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */
-
-/* Alpha relocs. */
-
-#define R_ALPHA_NONE 0 /* No reloc */
-#define R_ALPHA_REFLONG 1 /* Direct 32 bit */
-#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */
-#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */
-#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */
-#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */
-#define R_ALPHA_GPDISP 6 /* Add displacement to GP */
-#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */
-#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */
-#define R_ALPHA_SREL16 9 /* PC relative 16 bit */
-#define R_ALPHA_SREL32 10 /* PC relative 32 bit */
-#define R_ALPHA_SREL64 11 /* PC relative 64 bit */
-#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */
-#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */
-#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */
-#define R_ALPHA_COPY 24 /* Copy symbol at runtime */
-#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */
-#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */
-#define R_ALPHA_RELATIVE 27 /* Adjust by program base */
-#define R_ALPHA_TLS_GD_HI 28
-#define R_ALPHA_TLSGD 29
-#define R_ALPHA_TLS_LDM 30
-#define R_ALPHA_DTPMOD64 31
-#define R_ALPHA_GOTDTPREL 32
-#define R_ALPHA_DTPREL64 33
-#define R_ALPHA_DTPRELHI 34
-#define R_ALPHA_DTPRELLO 35
-#define R_ALPHA_DTPREL16 36
-#define R_ALPHA_GOTTPREL 37
-#define R_ALPHA_TPREL64 38
-#define R_ALPHA_TPRELHI 39
-#define R_ALPHA_TPRELLO 40
-#define R_ALPHA_TPREL16 41
-/* Keep this the last entry. */
-#define R_ALPHA_NUM 46
-
-/* Magic values of the LITUSE relocation addend. */
-#define LITUSE_ALPHA_ADDR 0
-#define LITUSE_ALPHA_BASE 1
-#define LITUSE_ALPHA_BYTOFF 2
-#define LITUSE_ALPHA_JSR 3
-#define LITUSE_ALPHA_TLS_GD 4
-#define LITUSE_ALPHA_TLS_LDM 5
-
-/* Legal values for d_tag of Elf64_Dyn. */
-#define DT_ALPHA_PLTRO (DT_LOPROC + 0)
-#define DT_ALPHA_NUM 1
-
-/* PowerPC specific declarations */
-
-/* Values for Elf32/64_Ehdr.e_flags. */
-#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */
-
-/* Cygnus local bits below */
-#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/
-#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib
- flag */
-
-/* PowerPC relocations defined by the ABIs */
-#define R_PPC_NONE 0
-#define R_PPC_ADDR32 1 /* 32bit absolute address */
-#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */
-#define R_PPC_ADDR16 3 /* 16bit absolute address */
-#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */
-#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */
-#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */
-#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */
-#define R_PPC_ADDR14_BRTAKEN 8
-#define R_PPC_ADDR14_BRNTAKEN 9
-#define R_PPC_REL24 10 /* PC relative 26 bit */
-#define R_PPC_REL14 11 /* PC relative 16 bit */
-#define R_PPC_REL14_BRTAKEN 12
-#define R_PPC_REL14_BRNTAKEN 13
-#define R_PPC_GOT16 14
-#define R_PPC_GOT16_LO 15
-#define R_PPC_GOT16_HI 16
-#define R_PPC_GOT16_HA 17
-#define R_PPC_PLTREL24 18
-#define R_PPC_COPY 19
-#define R_PPC_GLOB_DAT 20
-#define R_PPC_JMP_SLOT 21
-#define R_PPC_RELATIVE 22
-#define R_PPC_LOCAL24PC 23
-#define R_PPC_UADDR32 24
-#define R_PPC_UADDR16 25
-#define R_PPC_REL32 26
-#define R_PPC_PLT32 27
-#define R_PPC_PLTREL32 28
-#define R_PPC_PLT16_LO 29
-#define R_PPC_PLT16_HI 30
-#define R_PPC_PLT16_HA 31
-#define R_PPC_SDAREL16 32
-#define R_PPC_SECTOFF 33
-#define R_PPC_SECTOFF_LO 34
-#define R_PPC_SECTOFF_HI 35
-#define R_PPC_SECTOFF_HA 36
-
-/* PowerPC relocations defined for the TLS access ABI. */
-#define R_PPC_TLS 67 /* none (sym+add)@tls */
-#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */
-#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */
-#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
-#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
-#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
-#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */
-#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */
-#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
-#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
-#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
-#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */
-#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
-#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
-#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
-#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
-#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
-#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
-#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
-#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
-#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */
-#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */
-#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
-#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
-#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */
-#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */
-#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */
-#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */
-
-/* The remaining relocs are from the Embedded ELF ABI, and are not
- in the SVR4 ELF ABI. */
-#define R_PPC_EMB_NADDR32 101
-#define R_PPC_EMB_NADDR16 102
-#define R_PPC_EMB_NADDR16_LO 103
-#define R_PPC_EMB_NADDR16_HI 104
-#define R_PPC_EMB_NADDR16_HA 105
-#define R_PPC_EMB_SDAI16 106
-#define R_PPC_EMB_SDA2I16 107
-#define R_PPC_EMB_SDA2REL 108
-#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */
-#define R_PPC_EMB_MRKREF 110
-#define R_PPC_EMB_RELSEC16 111
-#define R_PPC_EMB_RELST_LO 112
-#define R_PPC_EMB_RELST_HI 113
-#define R_PPC_EMB_RELST_HA 114
-#define R_PPC_EMB_BIT_FLD 115
-#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */
-
-/* Diab tool relocations. */
-#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */
-#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */
-#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */
-#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */
-#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */
-#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */
-
-/* GNU extension to support local ifunc. */
-#define R_PPC_IRELATIVE 248
-
-/* GNU relocs used in PIC code sequences. */
-#define R_PPC_REL16 249 /* half16 (sym+add-.) */
-#define R_PPC_REL16_LO 250 /* half16 (sym+add-.)@l */
-#define R_PPC_REL16_HI 251 /* half16 (sym+add-.)@h */
-#define R_PPC_REL16_HA 252 /* half16 (sym+add-.)@ha */
-
-/* This is a phony reloc to handle any old fashioned TOC16 references
- that may still be in object files. */
-#define R_PPC_TOC16 255
-
-/* PowerPC specific values for the Dyn d_tag field. */
-#define DT_PPC_GOT (DT_LOPROC + 0)
-#define DT_PPC_NUM 1
-
-/* PowerPC64 relocations defined by the ABIs */
-#define R_PPC64_NONE R_PPC_NONE
-#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */
-#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */
-#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */
-#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */
-#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */
-#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */
-#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */
-#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
-#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
-#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */
-#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */
-#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
-#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
-#define R_PPC64_GOT16 R_PPC_GOT16
-#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
-#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
-#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
-
-#define R_PPC64_COPY R_PPC_COPY
-#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
-#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
-#define R_PPC64_RELATIVE R_PPC_RELATIVE
-
-#define R_PPC64_UADDR32 R_PPC_UADDR32
-#define R_PPC64_UADDR16 R_PPC_UADDR16
-#define R_PPC64_REL32 R_PPC_REL32
-#define R_PPC64_PLT32 R_PPC_PLT32
-#define R_PPC64_PLTREL32 R_PPC_PLTREL32
-#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
-#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
-#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
-
-#define R_PPC64_SECTOFF R_PPC_SECTOFF
-#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
-#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
-#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
-#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */
-#define R_PPC64_ADDR64 38 /* doubleword64 S + A */
-#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */
-#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */
-#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */
-#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */
-#define R_PPC64_UADDR64 43 /* doubleword64 S + A */
-#define R_PPC64_REL64 44 /* doubleword64 S + A - P */
-#define R_PPC64_PLT64 45 /* doubleword64 L + A */
-#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */
-#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */
-#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */
-#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */
-#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */
-#define R_PPC64_TOC 51 /* doubleword64 .TOC */
-#define R_PPC64_PLTGOT16 52 /* half16* M + A */
-#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */
-#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */
-#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */
-
-#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */
-#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */
-#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */
-#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */
-#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */
-#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */
-#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */
-#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */
-#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */
-#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */
-#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */
-
-/* PowerPC64 relocations defined for the TLS access ABI. */
-#define R_PPC64_TLS 67 /* none (sym+add)@tls */
-#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */
-#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */
-#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */
-#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */
-#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */
-#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */
-#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */
-#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */
-#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */
-#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */
-#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */
-#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */
-#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */
-#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */
-#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */
-#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */
-#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */
-#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */
-#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */
-#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */
-#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
-#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */
-#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */
-#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */
-#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
-#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */
-#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */
-#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */
-#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */
-#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */
-#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */
-#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */
-#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */
-#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */
-#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */
-#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */
-#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */
-#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */
-#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */
-
-/* GNU extension to support local ifunc. */
-#define R_PPC64_JMP_IREL 247
-#define R_PPC64_IRELATIVE 248
-#define R_PPC64_REL16 249 /* half16 (sym+add-.) */
-#define R_PPC64_REL16_LO 250 /* half16 (sym+add-.)@l */
-#define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */
-#define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */
-
-/* PowerPC64 specific values for the Dyn d_tag field. */
-#define DT_PPC64_GLINK (DT_LOPROC + 0)
-#define DT_PPC64_OPD (DT_LOPROC + 1)
-#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
-#define DT_PPC64_NUM 3
-
-
-/* ARM specific declarations */
-
-/* Processor specific flags for the ELF header e_flags field. */
-#define EF_ARM_RELEXEC 0x01
-#define EF_ARM_HASENTRY 0x02
-#define EF_ARM_INTERWORK 0x04
-#define EF_ARM_APCS_26 0x08
-#define EF_ARM_APCS_FLOAT 0x10
-#define EF_ARM_PIC 0x20
-#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */
-#define EF_ARM_NEW_ABI 0x80
-#define EF_ARM_OLD_ABI 0x100
-#define EF_ARM_SOFT_FLOAT 0x200
-#define EF_ARM_VFP_FLOAT 0x400
-#define EF_ARM_MAVERICK_FLOAT 0x800
-
-#define EF_ARM_ABI_FLOAT_SOFT 0x200 /* NB conflicts with EF_ARM_SOFT_FLOAT */
-#define EF_ARM_ABI_FLOAT_HARD 0x400 /* NB conflicts with EF_ARM_VFP_FLOAT */
-
-
-/* Other constants defined in the ARM ELF spec. version B-01. */
-/* NB. These conflict with values defined above. */
-#define EF_ARM_SYMSARESORTED 0x04
-#define EF_ARM_DYNSYMSUSESEGIDX 0x08
-#define EF_ARM_MAPSYMSFIRST 0x10
-#define EF_ARM_EABIMASK 0XFF000000
-
-/* Constants defined in AAELF. */
-#define EF_ARM_BE8 0x00800000
-#define EF_ARM_LE8 0x00400000
-
-#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
-#define EF_ARM_EABI_UNKNOWN 0x00000000
-#define EF_ARM_EABI_VER1 0x01000000
-#define EF_ARM_EABI_VER2 0x02000000
-#define EF_ARM_EABI_VER3 0x03000000
-#define EF_ARM_EABI_VER4 0x04000000
-#define EF_ARM_EABI_VER5 0x05000000
-
-/* Additional symbol types for Thumb. */
-#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */
-#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */
-
-/* ARM-specific values for sh_flags */
-#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */
-#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined
- in the input to a link step. */
-
-/* ARM-specific program header flags */
-#define PF_ARM_SB 0x10000000 /* Segment contains the location
- addressed by the static base. */
-#define PF_ARM_PI 0x20000000 /* Position-independent segment. */
-#define PF_ARM_ABS 0x40000000 /* Absolute segment. */
-
-/* Processor specific values for the Phdr p_type field. */
-#define PT_ARM_EXIDX (PT_LOPROC + 1) /* ARM unwind segment. */
-
-/* Processor specific values for the Shdr sh_type field. */
-#define SHT_ARM_EXIDX (SHT_LOPROC + 1) /* ARM unwind section. */
-#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2) /* Preemption details. */
-#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3) /* ARM attributes section. */
-
-
-/* AArch64 relocs. */
-
-#define R_AARCH64_NONE 0 /* No relocation. */
-#define R_AARCH64_ABS64 257 /* Direct 64 bit. */
-#define R_AARCH64_ABS32 258 /* Direct 32 bit. */
-#define R_AARCH64_ABS16 259 /* Direct 16-bit. */
-#define R_AARCH64_PREL64 260 /* PC-relative 64-bit. */
-#define R_AARCH64_PREL32 261 /* PC-relative 32-bit. */
-#define R_AARCH64_PREL16 262 /* PC-relative 16-bit. */
-#define R_AARCH64_MOVW_UABS_G0 263 /* Dir. MOVZ imm. from bits 15:0. */
-#define R_AARCH64_MOVW_UABS_G0_NC 264 /* Likewise for MOVK; no check. */
-#define R_AARCH64_MOVW_UABS_G1 265 /* Dir. MOVZ imm. from bits 31:16. */
-#define R_AARCH64_MOVW_UABS_G1_NC 266 /* Likewise for MOVK; no check. */
-#define R_AARCH64_MOVW_UABS_G2 267 /* Dir. MOVZ imm. from bits 47:32. */
-#define R_AARCH64_MOVW_UABS_G2_NC 268 /* Likewise for MOVK; no check. */
-#define R_AARCH64_MOVW_UABS_G3 269 /* Dir. MOV{K,Z} imm. from 63:48. */
-#define R_AARCH64_MOVW_SABS_G0 270 /* Dir. MOV{N,Z} imm. from 15:0. */
-#define R_AARCH64_MOVW_SABS_G1 271 /* Dir. MOV{N,Z} imm. from 31:16. */
-#define R_AARCH64_MOVW_SABS_G2 272 /* Dir. MOV{N,Z} imm. from 47:32. */
-#define R_AARCH64_LD_PREL_LO19 273 /* PC-rel. LD imm. from bits 20:2. */
-#define R_AARCH64_ADR_PREL_LO21 274 /* PC-rel. ADR imm. from bits 20:0. */
-#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page-rel. ADRP imm. from 32:12. */
-#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check. */
-#define R_AARCH64_ADD_ABS_LO12_NC 277 /* Dir. ADD imm. from bits 11:0. */
-#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* Likewise for LD/ST; no check. */
-#define R_AARCH64_TSTBR14 279 /* PC-rel. TBZ/TBNZ imm. from 15:2. */
-#define R_AARCH64_CONDBR19 280 /* PC-rel. cond. br. imm. from 20:2. */
-#define R_AARCH64_JUMP26 282 /* PC-rel. B imm. from bits 27:2. */
-#define R_AARCH64_CALL26 283 /* Likewise for CALL. */
-#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1. */
-#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2. */
-#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3. */
-#define R_AARCH64_MOVW_PREL_G0 287 /* PC-rel. MOV{N,Z} imm. from 15:0. */
-#define R_AARCH64_MOVW_PREL_G0_NC 288 /* Likewise for MOVK; no check. */
-#define R_AARCH64_MOVW_PREL_G1 289 /* PC-rel. MOV{N,Z} imm. from 31:16. */
-#define R_AARCH64_MOVW_PREL_G1_NC 290 /* Likewise for MOVK; no check. */
-#define R_AARCH64_MOVW_PREL_G2 291 /* PC-rel. MOV{N,Z} imm. from 47:32. */
-#define R_AARCH64_MOVW_PREL_G2_NC 292 /* Likewise for MOVK; no check. */
-#define R_AARCH64_MOVW_PREL_G3 293 /* PC-rel. MOV{N,Z} imm. from 63:48. */
-#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4. */
-#define R_AARCH64_MOVW_GOTOFF_G0 300 /* GOT-rel. off. MOV{N,Z} imm. 15:0. */
-#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* Likewise for MOVK; no check. */
-#define R_AARCH64_MOVW_GOTOFF_G1 302 /* GOT-rel. o. MOV{N,Z} imm. 31:16. */
-#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* Likewise for MOVK; no check. */
-#define R_AARCH64_MOVW_GOTOFF_G2 304 /* GOT-rel. o. MOV{N,Z} imm. 47:32. */
-#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* Likewise for MOVK; no check. */
-#define R_AARCH64_MOVW_GOTOFF_G3 306 /* GOT-rel. o. MOV{N,Z} imm. 63:48. */
-#define R_AARCH64_GOTREL64 307 /* GOT-relative 64-bit. */
-#define R_AARCH64_GOTREL32 308 /* GOT-relative 32-bit. */
-#define R_AARCH64_GOT_LD_PREL19 309 /* PC-rel. GOT off. load imm. 20:2. */
-#define R_AARCH64_LD64_GOTOFF_LO15 310 /* GOT-rel. off. LD/ST imm. 14:3. */
-#define R_AARCH64_ADR_GOT_PAGE 311 /* P-page-rel. GOT off. ADRP 32:12. */
-#define R_AARCH64_LD64_GOT_LO12_NC 312 /* Dir. GOT off. LD/ST imm. 11:3. */
-#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* GOT-page-rel. GOT off. LD/ST 14:3 */
-#define R_AARCH64_TLSGD_ADR_PREL21 512 /* PC-relative ADR imm. 20:0. */
-#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* page-rel. ADRP imm. 32:12. */
-#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* direct ADD imm. from 11:0. */
-#define R_AARCH64_TLSGD_MOVW_G1 515 /* GOT-rel. MOV{N,Z} 31:16. */
-#define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* GOT-rel. MOVK imm. 15:0. */
-#define R_AARCH64_TLSLD_ADR_PREL21 517 /* Like 512; local dynamic model. */
-#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Like 513; local dynamic model. */
-#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* Like 514; local dynamic model. */
-#define R_AARCH64_TLSLD_MOVW_G1 520 /* Like 515; local dynamic model. */
-#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* Like 516; local dynamic model. */
-#define R_AARCH64_TLSLD_LD_PREL19 522 /* TLS PC-rel. load imm. 20:2. */
-#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32. */
-#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16. */
-#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check. */
-#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0. */
-#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check. */
-#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */
-#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0. */
-#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check. */
-#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0. */
-#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check. */
-#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1. */
-#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check. */
-#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2. */
-#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check. */
-#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3. */
-#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check. */
-#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16. */
-#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0. */
-#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12. */
-#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3. */
-#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2. */
-#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32. */
-#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16. */
-#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check. */
-#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0. */
-#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check. */
-#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12. */
-#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0. */
-#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check. */
-#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0. */
-#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */
-#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1. */
-#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check. */
-#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2. */
-#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check. */
-#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3. */
-#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check. */
-#define R_AARCH64_TLSDESC_LD_PREL19 560 /* PC-rel. load immediate 20:2. */
-#define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0. */
-#define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12. */
-#define R_AARCH64_TLSDESC_LD64_LO12 563 /* Direct LD off. from 11:3. */
-#define R_AARCH64_TLSDESC_ADD_LO12 564 /* Direct ADD imm. from 11:0. */
-#define R_AARCH64_TLSDESC_OFF_G1 565 /* GOT-rel. MOV{N,Z} imm. 31:16. */
-#define R_AARCH64_TLSDESC_OFF_G0_NC 566 /* GOT-rel. MOVK imm. 15:0; no ck. */
-#define R_AARCH64_TLSDESC_LDR 567 /* Relax LDR. */
-#define R_AARCH64_TLSDESC_ADD 568 /* Relax ADD. */
-#define R_AARCH64_TLSDESC_CALL 569 /* Relax BLR. */
-#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4. */
-#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check. */
-#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */
-#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check. */
-#define R_AARCH64_COPY 1024 /* Copy symbol at runtime. */
-#define R_AARCH64_GLOB_DAT 1025 /* Create GOT entry. */
-#define R_AARCH64_JUMP_SLOT 1026 /* Create PLT entry. */
-#define R_AARCH64_RELATIVE 1027 /* Adjust by program base. */
-#define R_AARCH64_TLS_DTPMOD64 1028 /* Module number, 64 bit. */
-#define R_AARCH64_TLS_DTPREL64 1029 /* Module-relative offset, 64 bit. */
-#define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset, 64 bit. */
-#define R_AARCH64_TLSDESC 1031 /* TLS Descriptor. */
-#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */
-/* Keep this the last entry. */
-#define R_AARCH64_NUM 1033
-
-/* ARM relocs. */
-
-#define R_ARM_NONE 0 /* No reloc */
-#define R_ARM_PC24 1 /* PC relative 26 bit branch */
-#define R_ARM_ABS32 2 /* Direct 32 bit */
-#define R_ARM_REL32 3 /* PC relative 32 bit */
-#define R_ARM_PC13 4
-#define R_ARM_ABS16 5 /* Direct 16 bit */
-#define R_ARM_ABS12 6 /* Direct 12 bit */
-#define R_ARM_THM_ABS5 7
-#define R_ARM_ABS8 8 /* Direct 8 bit */
-#define R_ARM_SBREL32 9
-#define R_ARM_THM_PC22 10
-#define R_ARM_THM_PC8 11
-#define R_ARM_AMP_VCALL9 12
-#define R_ARM_SWI24 13 /* Obsolete static relocation. */
-#define R_ARM_TLS_DESC 13 /* Dynamic relocation. */
-#define R_ARM_THM_SWI8 14
-#define R_ARM_XPC25 15
-#define R_ARM_THM_XPC22 16
-#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */
-#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */
-#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */
-#define R_ARM_COPY 20 /* Copy symbol at runtime */
-#define R_ARM_GLOB_DAT 21 /* Create GOT entry */
-#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */
-#define R_ARM_RELATIVE 23 /* Adjust by program base */
-#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */
-#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */
-#define R_ARM_GOT32 26 /* 32 bit GOT entry */
-#define R_ARM_PLT32 27 /* 32 bit PLT address */
-#define R_ARM_CALL 28
-#define R_ARM_JUMP24 29
-#define R_ARM_THM_JUMP24 30
-#define R_ARM_BASE_ABS 31 /* Adjust by program base. */
-#define R_ARM_ALU_PCREL_7_0 32
-#define R_ARM_ALU_PCREL_15_8 33
-#define R_ARM_ALU_PCREL_23_15 34
-#define R_ARM_LDR_SBREL_11_0 35
-#define R_ARM_ALU_SBREL_19_12 36
-#define R_ARM_ALU_SBREL_27_20 37
-#define R_ARM_TARGET1 38
-#define R_ARM_SBREL31 39 /* Program base relative. */
-#define R_ARM_V4BX 40
-#define R_ARM_TARGET2 41
-#define R_ARM_PREL31 42
-#define R_ARM_MOVW_ABS_NC 43
-#define R_ARM_MOVT_ABS 44
-#define R_ARM_MOVW_PREL_NC 45 /* PC relative 16-bit (MOVW). */
-#define R_ARM_MOVT_PREL 46 /* PC relative (MOVT). */
-#define R_ARM_THM_MOVW_ABS_NC 47
-#define R_ARM_THM_MOVT_ABS 48
-/* Values from 49 to 89 are not yet used/handled by tcc. */
-#define R_ARM_TLS_GOTDESC 90
-#define R_ARM_TLS_CALL 91
-#define R_ARM_TLS_DESCSEQ 92
-#define R_ARM_THM_TLS_CALL 93
-#define R_ARM_GOT_PREL 96
-#define R_ARM_GNU_VTENTRY 100
-#define R_ARM_GNU_VTINHERIT 101
-#define R_ARM_THM_PC11 102 /* thumb unconditional branch */
-#define R_ARM_THM_PC9 103 /* thumb conditional branch */
-#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic
- thread local data */
-#define R_ARM_TLS_LDM32 105 /* PC-rel 32 bit for local dynamic
- thread local data */
-#define R_ARM_TLS_LDO32 106 /* 32 bit offset relative to TLS
- block */
-#define R_ARM_TLS_IE32 107 /* PC-rel 32 bit for GOT entry of
- static TLS block offset */
-#define R_ARM_TLS_LE32 108 /* 32 bit offset relative to static
- TLS block */
-#define R_ARM_THM_TLS_DESCSEQ 129
-#define R_ARM_IRELATIVE 160
-#define R_ARM_RXPC25 249
-#define R_ARM_RSBREL32 250
-#define R_ARM_THM_RPC22 251
-#define R_ARM_RREL32 252
-#define R_ARM_RABS22 253
-#define R_ARM_RPC24 254
-#define R_ARM_RBASE 255
-/* Keep this the last entry. */
-#define R_ARM_NUM 256
-
-/* TMS320C67xx specific declarations */
-
-/* XXX: no ELF standard yet*/
-
-/* TMS320C67xx relocs. */
-#define R_C60_32 1
-#define R_C60_GOT32 3 /* 32 bit GOT entry */
-#define R_C60_PLT32 4 /* 32 bit PLT address */
-#define R_C60_COPY 5 /* Copy symbol at runtime */
-#define R_C60_GLOB_DAT 6 /* Create GOT entry */
-#define R_C60_JMP_SLOT 7 /* Create PLT entry */
-#define R_C60_RELATIVE 8 /* Adjust by program base */
-#define R_C60_GOTOFF 9 /* 32 bit offset to GOT */
-#define R_C60_GOTPC 10 /* 32 bit PC relative offset to GOT */
-
-#define R_C60LO16 0x54 /* low 16 bit MVKL embedded */
-#define R_C60HI16 0x55 /* high 16 bit MVKH embedded */
-/* Keep this the last entry. */
-#define R_C60_NUM 0x56
-
-/* IA-64 specific declarations. */
-
-/* Processor specific flags for the Ehdr e_flags field. */
-#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */
-#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */
-#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */
-
-/* Processor specific values for the Phdr p_type field. */
-#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */
-#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */
-#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12)
-#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13)
-#define PT_IA_64_HP_STACK (PT_LOOS + 0x14)
-
-/* Processor specific flags for the Phdr p_flags field. */
-#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */
-
-/* Processor specific values for the Shdr sh_type field. */
-#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */
-#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */
-
-/* Processor specific flags for the Shdr sh_flags field. */
-#define SHF_IA_64_SHORT 0x10000000 /* section near gp */
-#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */
-
-/* Processor specific values for the Dyn d_tag field. */
-#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0)
-#define DT_IA_64_NUM 1
-
-/* IA-64 relocations. */
-#define R_IA64_NONE 0x00 /* none */
-#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */
-#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */
-#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */
-#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */
-#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */
-#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */
-#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */
-#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */
-#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */
-#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */
-#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */
-#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */
-#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */
-#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */
-#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */
-#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */
-#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */
-#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */
-#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */
-#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */
-#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */
-#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */
-#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */
-#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */
-#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */
-#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */
-#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */
-#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */
-#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */
-#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */
-#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */
-#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */
-#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */
-#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */
-#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */
-#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */
-#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */
-#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */
-#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */
-#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */
-#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */
-#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */
-#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */
-#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */
-#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */
-#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */
-#define R_IA64_REL32MSB 0x6c /* data 4 + REL */
-#define R_IA64_REL32LSB 0x6d /* data 4 + REL */
-#define R_IA64_REL64MSB 0x6e /* data 8 + REL */
-#define R_IA64_REL64LSB 0x6f /* data 8 + REL */
-#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */
-#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */
-#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */
-#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */
-#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */
-#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */
-#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */
-#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */
-#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */
-#define R_IA64_COPY 0x84 /* copy relocation */
-#define R_IA64_SUB 0x85 /* Addend and symbol difference */
-#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */
-#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */
-#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */
-#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */
-#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */
-#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */
-#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */
-#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */
-#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */
-#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */
-#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */
-#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */
-#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */
-#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */
-#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */
-#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */
-#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */
-#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */
-#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */
-
-/* SH specific declarations */
-
-/* Processor specific flags for the ELF header e_flags field. */
-#define EF_SH_MACH_MASK 0x1f
-#define EF_SH_UNKNOWN 0x0
-#define EF_SH1 0x1
-#define EF_SH2 0x2
-#define EF_SH3 0x3
-#define EF_SH_DSP 0x4
-#define EF_SH3_DSP 0x5
-#define EF_SH4AL_DSP 0x6
-#define EF_SH3E 0x8
-#define EF_SH4 0x9
-#define EF_SH2E 0xb
-#define EF_SH4A 0xc
-#define EF_SH2A 0xd
-#define EF_SH4_NOFPU 0x10
-#define EF_SH4A_NOFPU 0x11
-#define EF_SH4_NOMMU_NOFPU 0x12
-#define EF_SH2A_NOFPU 0x13
-#define EF_SH3_NOMMU 0x14
-#define EF_SH2A_SH4_NOFPU 0x15
-#define EF_SH2A_SH3_NOFPU 0x16
-#define EF_SH2A_SH4 0x17
-#define EF_SH2A_SH3E 0x18
-
-/* SH relocs. */
-#define R_SH_NONE 0
-#define R_SH_DIR32 1
-#define R_SH_REL32 2
-#define R_SH_DIR8WPN 3
-#define R_SH_IND12W 4
-#define R_SH_DIR8WPL 5
-#define R_SH_DIR8WPZ 6
-#define R_SH_DIR8BP 7
-#define R_SH_DIR8W 8
-#define R_SH_DIR8L 9
-#define R_SH_SWITCH16 25
-#define R_SH_SWITCH32 26
-#define R_SH_USES 27
-#define R_SH_COUNT 28
-#define R_SH_ALIGN 29
-#define R_SH_CODE 30
-#define R_SH_DATA 31
-#define R_SH_LABEL 32
-#define R_SH_SWITCH8 33
-#define R_SH_GNU_VTINHERIT 34
-#define R_SH_GNU_VTENTRY 35
-#define R_SH_TLS_GD_32 144
-#define R_SH_TLS_LD_32 145
-#define R_SH_TLS_LDO_32 146
-#define R_SH_TLS_IE_32 147
-#define R_SH_TLS_LE_32 148
-#define R_SH_TLS_DTPMOD32 149
-#define R_SH_TLS_DTPOFF32 150
-#define R_SH_TLS_TPOFF32 151
-#define R_SH_GOT32 160
-#define R_SH_PLT32 161
-#define R_SH_COPY 162
-#define R_SH_GLOB_DAT 163
-#define R_SH_JMP_SLOT 164
-#define R_SH_RELATIVE 165
-#define R_SH_GOTOFF 166
-#define R_SH_GOTPC 167
-/* Keep this the last entry. */
-#define R_SH_NUM 256
-
-/* S/390 specific definitions. */
-
-/* Valid values for the e_flags field. */
-
-#define EF_S390_HIGH_GPRS 0x00000001 /* High GPRs kernel facility needed. */
-
-/* Additional s390 relocs */
-
-#define R_390_NONE 0 /* No reloc. */
-#define R_390_8 1 /* Direct 8 bit. */
-#define R_390_12 2 /* Direct 12 bit. */
-#define R_390_16 3 /* Direct 16 bit. */
-#define R_390_32 4 /* Direct 32 bit. */
-#define R_390_PC32 5 /* PC relative 32 bit. */
-#define R_390_GOT12 6 /* 12 bit GOT offset. */
-#define R_390_GOT32 7 /* 32 bit GOT offset. */
-#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */
-#define R_390_COPY 9 /* Copy symbol at runtime. */
-#define R_390_GLOB_DAT 10 /* Create GOT entry. */
-#define R_390_JMP_SLOT 11 /* Create PLT entry. */
-#define R_390_RELATIVE 12 /* Adjust by program base. */
-#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */
-#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */
-#define R_390_GOT16 15 /* 16 bit GOT offset. */
-#define R_390_PC16 16 /* PC relative 16 bit. */
-#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */
-#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */
-#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */
-#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */
-#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */
-#define R_390_64 22 /* Direct 64 bit. */
-#define R_390_PC64 23 /* PC relative 64 bit. */
-#define R_390_GOT64 24 /* 64 bit GOT offset. */
-#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */
-#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */
-#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */
-#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */
-#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */
-#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */
-#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */
-#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */
-#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */
-#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */
-#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */
-#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */
-#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */
-#define R_390_TLS_GDCALL 38 /* Tag for function call in general
- dynamic TLS code. */
-#define R_390_TLS_LDCALL 39 /* Tag for function call in local
- dynamic TLS code. */
-#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic
- thread local data. */
-#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic
- thread local data. */
-#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS
- block offset. */
-#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS
- block offset. */
-#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS
- block offset. */
-#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic
- thread local data in LE code. */
-#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic
- thread local data in LE code. */
-#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for
- negated static TLS block offset. */
-#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for
- negated static TLS block offset. */
-#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for
- negated static TLS block offset. */
-#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to
- static TLS block. */
-#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to
- static TLS block. */
-#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS
- block. */
-#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS
- block. */
-#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */
-#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */
-#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS
- block. */
-#define R_390_20 57 /* Direct 20 bit. */
-#define R_390_GOT20 58 /* 20 bit GOT offset. */
-#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */
-#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS
- block offset. */
-#define R_390_IRELATIVE 61 /* STT_GNU_IFUNC relocation. */
-/* Keep this the last entry. */
-#define R_390_NUM 62
-
-
-/* CRIS relocations. */
-#define R_CRIS_NONE 0
-#define R_CRIS_8 1
-#define R_CRIS_16 2
-#define R_CRIS_32 3
-#define R_CRIS_8_PCREL 4
-#define R_CRIS_16_PCREL 5
-#define R_CRIS_32_PCREL 6
-#define R_CRIS_GNU_VTINHERIT 7
-#define R_CRIS_GNU_VTENTRY 8
-#define R_CRIS_COPY 9
-#define R_CRIS_GLOB_DAT 10
-#define R_CRIS_JUMP_SLOT 11
-#define R_CRIS_RELATIVE 12
-#define R_CRIS_16_GOT 13
-#define R_CRIS_32_GOT 14
-#define R_CRIS_16_GOTPLT 15
-#define R_CRIS_32_GOTPLT 16
-#define R_CRIS_32_GOTREL 17
-#define R_CRIS_32_PLT_GOTREL 18
-#define R_CRIS_32_PLT_PCREL 19
-
-#define R_CRIS_NUM 20
-
-
-/* AMD x86-64 relocations. */
-#define R_X86_64_NONE 0 /* No reloc */
-#define R_X86_64_64 1 /* Direct 64 bit */
-#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
-#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
-#define R_X86_64_PLT32 4 /* 32 bit PLT address */
-#define R_X86_64_COPY 5 /* Copy symbol at runtime */
-#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
-#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
-#define R_X86_64_RELATIVE 8 /* Adjust by program base */
-#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative
- offset to GOT */
-#define R_X86_64_32 10 /* Direct 32 bit zero extended */
-#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
-#define R_X86_64_16 12 /* Direct 16 bit zero extended */
-#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
-#define R_X86_64_8 14 /* Direct 8 bit sign extended */
-#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
-#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */
-#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */
-#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */
-#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset
- to two GOT entries for GD symbol */
-#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset
- to two GOT entries for LD symbol */
-#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */
-#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset
- to GOT entry for IE symbol */
-#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */
-#define R_X86_64_PC64 24 /* PC relative 64 bit */
-#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */
-#define R_X86_64_GOTPC32 26 /* 32 bit signed pc relative
- offset to GOT */
-#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */
-#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset
- to GOT entry */
-#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */
-#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */
-#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset
- to PLT entry */
-#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */
-#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */
-#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */
-#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS
- descriptor. */
-#define R_X86_64_TLSDESC 36 /* TLS descriptor. */
-#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */
-#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */
-#define R_X86_64_GOTPCRELX 41 /* like GOTPCREL, but optionally with
- linker optimizations */
-#define R_X86_64_REX_GOTPCRELX 42 /* like GOTPCRELX, but a REX prefix
- is present */
-
-#define R_X86_64_NUM 43
-
-/* x86-64 sh_type values. */
-#define SHT_X86_64_UNWIND 0x70000001 /* Unwind information. */
-
-/* AM33 relocations. */
-#define R_MN10300_NONE 0 /* No reloc. */
-#define R_MN10300_32 1 /* Direct 32 bit. */
-#define R_MN10300_16 2 /* Direct 16 bit. */
-#define R_MN10300_8 3 /* Direct 8 bit. */
-#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */
-#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */
-#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */
-#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */
-#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */
-#define R_MN10300_24 9 /* Direct 24 bit. */
-#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */
-#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */
-#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */
-#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */
-#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */
-#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */
-#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */
-#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */
-#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */
-#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */
-#define R_MN10300_COPY 20 /* Copy symbol at runtime. */
-#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */
-#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */
-#define R_MN10300_RELATIVE 23 /* Adjust by program base. */
-#define R_MN10300_TLS_GD 24 /* 32-bit offset for global dynamic. */
-#define R_MN10300_TLS_LD 25 /* 32-bit offset for local dynamic. */
-#define R_MN10300_TLS_LDO 26 /* Module-relative offset. */
-#define R_MN10300_TLS_GOTIE 27 /* GOT offset for static TLS block
- offset. */
-#define R_MN10300_TLS_IE 28 /* GOT address for static TLS block
- offset. */
-#define R_MN10300_TLS_LE 29 /* Offset relative to static TLS
- block. */
-#define R_MN10300_TLS_DTPMOD 30 /* ID of module containing symbol. */
-#define R_MN10300_TLS_DTPOFF 31 /* Offset in module TLS block. */
-#define R_MN10300_TLS_TPOFF 32 /* Offset in static TLS block. */
-#define R_MN10300_SYM_DIFF 33 /* Adjustment for next reloc as needed
- by linker relaxation. */
-#define R_MN10300_ALIGN 34 /* Alignment requirement for linker
- relaxation. */
-#define R_MN10300_NUM 35
-
-
-/* M32R relocs. */
-#define R_M32R_NONE 0 /* No reloc. */
-#define R_M32R_16 1 /* Direct 16 bit. */
-#define R_M32R_32 2 /* Direct 32 bit. */
-#define R_M32R_24 3 /* Direct 24 bit. */
-#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */
-#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */
-#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */
-#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */
-#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */
-#define R_M32R_LO16 9 /* Low 16 bit. */
-#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */
-#define R_M32R_GNU_VTINHERIT 11
-#define R_M32R_GNU_VTENTRY 12
-/* M32R relocs use SHT_RELA. */
-#define R_M32R_16_RELA 33 /* Direct 16 bit. */
-#define R_M32R_32_RELA 34 /* Direct 32 bit. */
-#define R_M32R_24_RELA 35 /* Direct 24 bit. */
-#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */
-#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */
-#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */
-#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */
-#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */
-#define R_M32R_LO16_RELA 41 /* Low 16 bit */
-#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */
-#define R_M32R_RELA_GNU_VTINHERIT 43
-#define R_M32R_RELA_GNU_VTENTRY 44
-#define R_M32R_REL32 45 /* PC relative 32 bit. */
-
-#define R_M32R_GOT24 48 /* 24 bit GOT entry */
-#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */
-#define R_M32R_COPY 50 /* Copy symbol at runtime */
-#define R_M32R_GLOB_DAT 51 /* Create GOT entry */
-#define R_M32R_JMP_SLOT 52 /* Create PLT entry */
-#define R_M32R_RELATIVE 53 /* Adjust by program base */
-#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */
-#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */
-#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned
- low */
-#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed
- low */
-#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */
-#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to
- GOT with unsigned low */
-#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to
- GOT with signed low */
-#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to
- GOT */
-#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT
- with unsigned low */
-#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT
- with signed low */
-#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */
-#define R_M32R_NUM 256 /* Keep this the last entry. */
-
-
-/* TILEPro relocations. */
-#define R_TILEPRO_NONE 0 /* No reloc */
-#define R_TILEPRO_32 1 /* Direct 32 bit */
-#define R_TILEPRO_16 2 /* Direct 16 bit */
-#define R_TILEPRO_8 3 /* Direct 8 bit */
-#define R_TILEPRO_32_PCREL 4 /* PC relative 32 bit */
-#define R_TILEPRO_16_PCREL 5 /* PC relative 16 bit */
-#define R_TILEPRO_8_PCREL 6 /* PC relative 8 bit */
-#define R_TILEPRO_LO16 7 /* Low 16 bit */
-#define R_TILEPRO_HI16 8 /* High 16 bit */
-#define R_TILEPRO_HA16 9 /* High 16 bit, adjusted */
-#define R_TILEPRO_COPY 10 /* Copy relocation */
-#define R_TILEPRO_GLOB_DAT 11 /* Create GOT entry */
-#define R_TILEPRO_JMP_SLOT 12 /* Create PLT entry */
-#define R_TILEPRO_RELATIVE 13 /* Adjust by program base */
-#define R_TILEPRO_BROFF_X1 14 /* X1 pipe branch offset */
-#define R_TILEPRO_JOFFLONG_X1 15 /* X1 pipe jump offset */
-#define R_TILEPRO_JOFFLONG_X1_PLT 16 /* X1 pipe jump offset to PLT */
-#define R_TILEPRO_IMM8_X0 17 /* X0 pipe 8-bit */
-#define R_TILEPRO_IMM8_Y0 18 /* Y0 pipe 8-bit */
-#define R_TILEPRO_IMM8_X1 19 /* X1 pipe 8-bit */
-#define R_TILEPRO_IMM8_Y1 20 /* Y1 pipe 8-bit */
-#define R_TILEPRO_MT_IMM15_X1 21 /* X1 pipe mtspr */
-#define R_TILEPRO_MF_IMM15_X1 22 /* X1 pipe mfspr */
-#define R_TILEPRO_IMM16_X0 23 /* X0 pipe 16-bit */
-#define R_TILEPRO_IMM16_X1 24 /* X1 pipe 16-bit */
-#define R_TILEPRO_IMM16_X0_LO 25 /* X0 pipe low 16-bit */
-#define R_TILEPRO_IMM16_X1_LO 26 /* X1 pipe low 16-bit */
-#define R_TILEPRO_IMM16_X0_HI 27 /* X0 pipe high 16-bit */
-#define R_TILEPRO_IMM16_X1_HI 28 /* X1 pipe high 16-bit */
-#define R_TILEPRO_IMM16_X0_HA 29 /* X0 pipe high 16-bit, adjusted */
-#define R_TILEPRO_IMM16_X1_HA 30 /* X1 pipe high 16-bit, adjusted */
-#define R_TILEPRO_IMM16_X0_PCREL 31 /* X0 pipe PC relative 16 bit */
-#define R_TILEPRO_IMM16_X1_PCREL 32 /* X1 pipe PC relative 16 bit */
-#define R_TILEPRO_IMM16_X0_LO_PCREL 33 /* X0 pipe PC relative low 16 bit */
-#define R_TILEPRO_IMM16_X1_LO_PCREL 34 /* X1 pipe PC relative low 16 bit */
-#define R_TILEPRO_IMM16_X0_HI_PCREL 35 /* X0 pipe PC relative high 16 bit */
-#define R_TILEPRO_IMM16_X1_HI_PCREL 36 /* X1 pipe PC relative high 16 bit */
-#define R_TILEPRO_IMM16_X0_HA_PCREL 37 /* X0 pipe PC relative ha() 16 bit */
-#define R_TILEPRO_IMM16_X1_HA_PCREL 38 /* X1 pipe PC relative ha() 16 bit */
-#define R_TILEPRO_IMM16_X0_GOT 39 /* X0 pipe 16-bit GOT offset */
-#define R_TILEPRO_IMM16_X1_GOT 40 /* X1 pipe 16-bit GOT offset */
-#define R_TILEPRO_IMM16_X0_GOT_LO 41 /* X0 pipe low 16-bit GOT offset */
-#define R_TILEPRO_IMM16_X1_GOT_LO 42 /* X1 pipe low 16-bit GOT offset */
-#define R_TILEPRO_IMM16_X0_GOT_HI 43 /* X0 pipe high 16-bit GOT offset */
-#define R_TILEPRO_IMM16_X1_GOT_HI 44 /* X1 pipe high 16-bit GOT offset */
-#define R_TILEPRO_IMM16_X0_GOT_HA 45 /* X0 pipe ha() 16-bit GOT offset */
-#define R_TILEPRO_IMM16_X1_GOT_HA 46 /* X1 pipe ha() 16-bit GOT offset */
-#define R_TILEPRO_MMSTART_X0 47 /* X0 pipe mm "start" */
-#define R_TILEPRO_MMEND_X0 48 /* X0 pipe mm "end" */
-#define R_TILEPRO_MMSTART_X1 49 /* X1 pipe mm "start" */
-#define R_TILEPRO_MMEND_X1 50 /* X1 pipe mm "end" */
-#define R_TILEPRO_SHAMT_X0 51 /* X0 pipe shift amount */
-#define R_TILEPRO_SHAMT_X1 52 /* X1 pipe shift amount */
-#define R_TILEPRO_SHAMT_Y0 53 /* Y0 pipe shift amount */
-#define R_TILEPRO_SHAMT_Y1 54 /* Y1 pipe shift amount */
-#define R_TILEPRO_DEST_IMM8_X1 55 /* X1 pipe destination 8-bit */
-/* Relocs 56-59 are currently not defined. */
-#define R_TILEPRO_TLS_GD_CALL 60 /* "jal" for TLS GD */
-#define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61 /* X0 pipe "addi" for TLS GD */
-#define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62 /* X1 pipe "addi" for TLS GD */
-#define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63 /* Y0 pipe "addi" for TLS GD */
-#define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64 /* Y1 pipe "addi" for TLS GD */
-#define R_TILEPRO_TLS_IE_LOAD 65 /* "lw_tls" for TLS IE */
-#define R_TILEPRO_IMM16_X0_TLS_GD 66 /* X0 pipe 16-bit TLS GD offset */
-#define R_TILEPRO_IMM16_X1_TLS_GD 67 /* X1 pipe 16-bit TLS GD offset */
-#define R_TILEPRO_IMM16_X0_TLS_GD_LO 68 /* X0 pipe low 16-bit TLS GD offset */
-#define R_TILEPRO_IMM16_X1_TLS_GD_LO 69 /* X1 pipe low 16-bit TLS GD offset */
-#define R_TILEPRO_IMM16_X0_TLS_GD_HI 70 /* X0 pipe high 16-bit TLS GD offset */
-#define R_TILEPRO_IMM16_X1_TLS_GD_HI 71 /* X1 pipe high 16-bit TLS GD offset */
-#define R_TILEPRO_IMM16_X0_TLS_GD_HA 72 /* X0 pipe ha() 16-bit TLS GD offset */
-#define R_TILEPRO_IMM16_X1_TLS_GD_HA 73 /* X1 pipe ha() 16-bit TLS GD offset */
-#define R_TILEPRO_IMM16_X0_TLS_IE 74 /* X0 pipe 16-bit TLS IE offset */
-#define R_TILEPRO_IMM16_X1_TLS_IE 75 /* X1 pipe 16-bit TLS IE offset */
-#define R_TILEPRO_IMM16_X0_TLS_IE_LO 76 /* X0 pipe low 16-bit TLS IE offset */
-#define R_TILEPRO_IMM16_X1_TLS_IE_LO 77 /* X1 pipe low 16-bit TLS IE offset */
-#define R_TILEPRO_IMM16_X0_TLS_IE_HI 78 /* X0 pipe high 16-bit TLS IE offset */
-#define R_TILEPRO_IMM16_X1_TLS_IE_HI 79 /* X1 pipe high 16-bit TLS IE offset */
-#define R_TILEPRO_IMM16_X0_TLS_IE_HA 80 /* X0 pipe ha() 16-bit TLS IE offset */
-#define R_TILEPRO_IMM16_X1_TLS_IE_HA 81 /* X1 pipe ha() 16-bit TLS IE offset */
-#define R_TILEPRO_TLS_DTPMOD32 82 /* ID of module containing symbol */
-#define R_TILEPRO_TLS_DTPOFF32 83 /* Offset in TLS block */
-#define R_TILEPRO_TLS_TPOFF32 84 /* Offset in static TLS block */
-#define R_TILEPRO_IMM16_X0_TLS_LE 85 /* X0 pipe 16-bit TLS LE offset */
-#define R_TILEPRO_IMM16_X1_TLS_LE 86 /* X1 pipe 16-bit TLS LE offset */
-#define R_TILEPRO_IMM16_X0_TLS_LE_LO 87 /* X0 pipe low 16-bit TLS LE offset */
-#define R_TILEPRO_IMM16_X1_TLS_LE_LO 88 /* X1 pipe low 16-bit TLS LE offset */
-#define R_TILEPRO_IMM16_X0_TLS_LE_HI 89 /* X0 pipe high 16-bit TLS LE offset */
-#define R_TILEPRO_IMM16_X1_TLS_LE_HI 90 /* X1 pipe high 16-bit TLS LE offset */
-#define R_TILEPRO_IMM16_X0_TLS_LE_HA 91 /* X0 pipe ha() 16-bit TLS LE offset */
-#define R_TILEPRO_IMM16_X1_TLS_LE_HA 92 /* X1 pipe ha() 16-bit TLS LE offset */
-
-#define R_TILEPRO_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */
-#define R_TILEPRO_GNU_VTENTRY 129 /* GNU C++ vtable member usage */
-
-#define R_TILEPRO_NUM 130
-
-
-/* TILE-Gx relocations. */
-#define R_TILEGX_NONE 0 /* No reloc */
-#define R_TILEGX_64 1 /* Direct 64 bit */
-#define R_TILEGX_32 2 /* Direct 32 bit */
-#define R_TILEGX_16 3 /* Direct 16 bit */
-#define R_TILEGX_8 4 /* Direct 8 bit */
-#define R_TILEGX_64_PCREL 5 /* PC relative 64 bit */
-#define R_TILEGX_32_PCREL 6 /* PC relative 32 bit */
-#define R_TILEGX_16_PCREL 7 /* PC relative 16 bit */
-#define R_TILEGX_8_PCREL 8 /* PC relative 8 bit */
-#define R_TILEGX_HW0 9 /* hword 0 16-bit */
-#define R_TILEGX_HW1 10 /* hword 1 16-bit */
-#define R_TILEGX_HW2 11 /* hword 2 16-bit */
-#define R_TILEGX_HW3 12 /* hword 3 16-bit */
-#define R_TILEGX_HW0_LAST 13 /* last hword 0 16-bit */
-#define R_TILEGX_HW1_LAST 14 /* last hword 1 16-bit */
-#define R_TILEGX_HW2_LAST 15 /* last hword 2 16-bit */
-#define R_TILEGX_COPY 16 /* Copy relocation */
-#define R_TILEGX_GLOB_DAT 17 /* Create GOT entry */
-#define R_TILEGX_JMP_SLOT 18 /* Create PLT entry */
-#define R_TILEGX_RELATIVE 19 /* Adjust by program base */
-#define R_TILEGX_BROFF_X1 20 /* X1 pipe branch offset */
-#define R_TILEGX_JUMPOFF_X1 21 /* X1 pipe jump offset */
-#define R_TILEGX_JUMPOFF_X1_PLT 22 /* X1 pipe jump offset to PLT */
-#define R_TILEGX_IMM8_X0 23 /* X0 pipe 8-bit */
-#define R_TILEGX_IMM8_Y0 24 /* Y0 pipe 8-bit */
-#define R_TILEGX_IMM8_X1 25 /* X1 pipe 8-bit */
-#define R_TILEGX_IMM8_Y1 26 /* Y1 pipe 8-bit */
-#define R_TILEGX_DEST_IMM8_X1 27 /* X1 pipe destination 8-bit */
-#define R_TILEGX_MT_IMM14_X1 28 /* X1 pipe mtspr */
-#define R_TILEGX_MF_IMM14_X1 29 /* X1 pipe mfspr */
-#define R_TILEGX_MMSTART_X0 30 /* X0 pipe mm "start" */
-#define R_TILEGX_MMEND_X0 31 /* X0 pipe mm "end" */
-#define R_TILEGX_SHAMT_X0 32 /* X0 pipe shift amount */
-#define R_TILEGX_SHAMT_X1 33 /* X1 pipe shift amount */
-#define R_TILEGX_SHAMT_Y0 34 /* Y0 pipe shift amount */
-#define R_TILEGX_SHAMT_Y1 35 /* Y1 pipe shift amount */
-#define R_TILEGX_IMM16_X0_HW0 36 /* X0 pipe hword 0 */
-#define R_TILEGX_IMM16_X1_HW0 37 /* X1 pipe hword 0 */
-#define R_TILEGX_IMM16_X0_HW1 38 /* X0 pipe hword 1 */
-#define R_TILEGX_IMM16_X1_HW1 39 /* X1 pipe hword 1 */
-#define R_TILEGX_IMM16_X0_HW2 40 /* X0 pipe hword 2 */
-#define R_TILEGX_IMM16_X1_HW2 41 /* X1 pipe hword 2 */
-#define R_TILEGX_IMM16_X0_HW3 42 /* X0 pipe hword 3 */
-#define R_TILEGX_IMM16_X1_HW3 43 /* X1 pipe hword 3 */
-#define R_TILEGX_IMM16_X0_HW0_LAST 44 /* X0 pipe last hword 0 */
-#define R_TILEGX_IMM16_X1_HW0_LAST 45 /* X1 pipe last hword 0 */
-#define R_TILEGX_IMM16_X0_HW1_LAST 46 /* X0 pipe last hword 1 */
-#define R_TILEGX_IMM16_X1_HW1_LAST 47 /* X1 pipe last hword 1 */
-#define R_TILEGX_IMM16_X0_HW2_LAST 48 /* X0 pipe last hword 2 */
-#define R_TILEGX_IMM16_X1_HW2_LAST 49 /* X1 pipe last hword 2 */
-#define R_TILEGX_IMM16_X0_HW0_PCREL 50 /* X0 pipe PC relative hword 0 */
-#define R_TILEGX_IMM16_X1_HW0_PCREL 51 /* X1 pipe PC relative hword 0 */
-#define R_TILEGX_IMM16_X0_HW1_PCREL 52 /* X0 pipe PC relative hword 1 */
-#define R_TILEGX_IMM16_X1_HW1_PCREL 53 /* X1 pipe PC relative hword 1 */
-#define R_TILEGX_IMM16_X0_HW2_PCREL 54 /* X0 pipe PC relative hword 2 */
-#define R_TILEGX_IMM16_X1_HW2_PCREL 55 /* X1 pipe PC relative hword 2 */
-#define R_TILEGX_IMM16_X0_HW3_PCREL 56 /* X0 pipe PC relative hword 3 */
-#define R_TILEGX_IMM16_X1_HW3_PCREL 57 /* X1 pipe PC relative hword 3 */
-#define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */
-#define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */
-#define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */
-#define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */
-#define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */
-#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */
-#define R_TILEGX_IMM16_X0_HW0_GOT 64 /* X0 pipe hword 0 GOT offset */
-#define R_TILEGX_IMM16_X1_HW0_GOT 65 /* X1 pipe hword 0 GOT offset */
-#define R_TILEGX_IMM16_X0_HW0_PLT_PCREL 66 /* X0 pipe PC-rel PLT hword 0 */
-#define R_TILEGX_IMM16_X1_HW0_PLT_PCREL 67 /* X1 pipe PC-rel PLT hword 0 */
-#define R_TILEGX_IMM16_X0_HW1_PLT_PCREL 68 /* X0 pipe PC-rel PLT hword 1 */
-#define R_TILEGX_IMM16_X1_HW1_PLT_PCREL 69 /* X1 pipe PC-rel PLT hword 1 */
-#define R_TILEGX_IMM16_X0_HW2_PLT_PCREL 70 /* X0 pipe PC-rel PLT hword 2 */
-#define R_TILEGX_IMM16_X1_HW2_PLT_PCREL 71 /* X1 pipe PC-rel PLT hword 2 */
-#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */
-#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */
-#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */
-#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */
-#define R_TILEGX_IMM16_X0_HW3_PLT_PCREL 76 /* X0 pipe PC-rel PLT hword 3 */
-#define R_TILEGX_IMM16_X1_HW3_PLT_PCREL 77 /* X1 pipe PC-rel PLT hword 3 */
-#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78 /* X0 pipe hword 0 TLS GD offset */
-#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79 /* X1 pipe hword 0 TLS GD offset */
-#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80 /* X0 pipe hword 0 TLS LE offset */
-#define R_TILEGX_IMM16_X1_HW0_TLS_LE 81 /* X1 pipe hword 0 TLS LE offset */
-#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */
-#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */
-#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */
-#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */
-#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */
-#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */
-#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */
-#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */
-/* Relocs 90-91 are currently not defined. */
-#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92 /* X0 pipe hword 0 TLS IE offset */
-#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93 /* X1 pipe hword 0 TLS IE offset */
-#define R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL 94 /* X0 pipe PC-rel PLT last hword 0 */
-#define R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL 95 /* X1 pipe PC-rel PLT last hword 0 */
-#define R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL 96 /* X0 pipe PC-rel PLT last hword 1 */
-#define R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL 97 /* X1 pipe PC-rel PLT last hword 1 */
-#define R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL 98 /* X0 pipe PC-rel PLT last hword 2 */
-#define R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL 99 /* X1 pipe PC-rel PLT last hword 2 */
-#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */
-#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */
-#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */
-#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */
-/* Relocs 104-105 are currently not defined. */
-#define R_TILEGX_TLS_DTPMOD64 106 /* 64-bit ID of symbol's module */
-#define R_TILEGX_TLS_DTPOFF64 107 /* 64-bit offset in TLS block */
-#define R_TILEGX_TLS_TPOFF64 108 /* 64-bit offset in static TLS block */
-#define R_TILEGX_TLS_DTPMOD32 109 /* 32-bit ID of symbol's module */
-#define R_TILEGX_TLS_DTPOFF32 110 /* 32-bit offset in TLS block */
-#define R_TILEGX_TLS_TPOFF32 111 /* 32-bit offset in static TLS block */
-#define R_TILEGX_TLS_GD_CALL 112 /* "jal" for TLS GD */
-#define R_TILEGX_IMM8_X0_TLS_GD_ADD 113 /* X0 pipe "addi" for TLS GD */
-#define R_TILEGX_IMM8_X1_TLS_GD_ADD 114 /* X1 pipe "addi" for TLS GD */
-#define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115 /* Y0 pipe "addi" for TLS GD */
-#define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116 /* Y1 pipe "addi" for TLS GD */
-#define R_TILEGX_TLS_IE_LOAD 117 /* "ld_tls" for TLS IE */
-#define R_TILEGX_IMM8_X0_TLS_ADD 118 /* X0 pipe "addi" for TLS GD/IE */
-#define R_TILEGX_IMM8_X1_TLS_ADD 119 /* X1 pipe "addi" for TLS GD/IE */
-#define R_TILEGX_IMM8_Y0_TLS_ADD 120 /* Y0 pipe "addi" for TLS GD/IE */
-#define R_TILEGX_IMM8_Y1_TLS_ADD 121 /* Y1 pipe "addi" for TLS GD/IE */
-
-#define R_TILEGX_GNU_VTINHERIT 128 /* GNU C++ vtable hierarchy */
-#define R_TILEGX_GNU_VTENTRY 129 /* GNU C++ vtable member usage */
-
-#define R_TILEGX_NUM 130
-
-/* RISC-V ELF Flags */
-#define EF_RISCV_RVC 0x0001
-#define EF_RISCV_FLOAT_ABI 0x0006
-#define EF_RISCV_FLOAT_ABI_SOFT 0x0000
-#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002
-#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004
-#define EF_RISCV_FLOAT_ABI_QUAD 0x0006
-
-/* RISC-V relocations. */
-#define R_RISCV_NONE 0
-#define R_RISCV_32 1
-#define R_RISCV_64 2
-#define R_RISCV_RELATIVE 3
-#define R_RISCV_COPY 4
-#define R_RISCV_JUMP_SLOT 5
-#define R_RISCV_TLS_DTPMOD32 6
-#define R_RISCV_TLS_DTPMOD64 7
-#define R_RISCV_TLS_DTPREL32 8
-#define R_RISCV_TLS_DTPREL64 9
-#define R_RISCV_TLS_TPREL32 10
-#define R_RISCV_TLS_TPREL64 11
-#define R_RISCV_BRANCH 16
-#define R_RISCV_JAL 17
-#define R_RISCV_CALL 18
-#define R_RISCV_CALL_PLT 19
-#define R_RISCV_GOT_HI20 20
-#define R_RISCV_TLS_GOT_HI20 21
-#define R_RISCV_TLS_GD_HI20 22
-#define R_RISCV_PCREL_HI20 23
-#define R_RISCV_PCREL_LO12_I 24
-#define R_RISCV_PCREL_LO12_S 25
-#define R_RISCV_HI20 26
-#define R_RISCV_LO12_I 27
-#define R_RISCV_LO12_S 28
-#define R_RISCV_TPREL_HI20 29
-#define R_RISCV_TPREL_LO12_I 30
-#define R_RISCV_TPREL_LO12_S 31
-#define R_RISCV_TPREL_ADD 32
-#define R_RISCV_ADD8 33
-#define R_RISCV_ADD16 34
-#define R_RISCV_ADD32 35
-#define R_RISCV_ADD64 36
-#define R_RISCV_SUB8 37
-#define R_RISCV_SUB16 38
-#define R_RISCV_SUB32 39
-#define R_RISCV_SUB64 40
-#define R_RISCV_GNU_VTINHERIT 41
-#define R_RISCV_GNU_VTENTRY 42
-#define R_RISCV_ALIGN 43
-#define R_RISCV_RVC_BRANCH 44
-#define R_RISCV_RVC_JUMP 45
-#define R_RISCV_RVC_LUI 46
-#define R_RISCV_GPREL_I 47
-#define R_RISCV_GPREL_S 48
-#define R_RISCV_TPREL_I 49
-#define R_RISCV_TPREL_S 50
-#define R_RISCV_RELAX 51
-#define R_RISCV_SUB6 52
-#define R_RISCV_SET6 53
-#define R_RISCV_SET8 54
-#define R_RISCV_SET16 55
-#define R_RISCV_SET32 56
-#define R_RISCV_32_PCREL 57
-
-#define R_RISCV_NUM 58
-
-
-#endif /* elf.h */
diff --git a/tinycc/i386-asm.c b/tinycc/i386-asm.c
deleted file mode 100644
index 3cc8d18..0000000
--- a/tinycc/i386-asm.c
+++ /dev/null
@@ -1,1744 +0,0 @@
-/*
- * i386 specific functions for TCC assembler
- *
- * Copyright (c) 2001, 2002 Fabrice Bellard
- * Copyright (c) 2009 Frédéric Feret (x86_64 support)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define USING_GLOBALS
-#include "tcc.h"
-
-#define MAX_OPERANDS 3
-
-#define TOK_ASM_first TOK_ASM_clc
-#define TOK_ASM_last TOK_ASM_emms
-#define TOK_ASM_alllast TOK_ASM_subps
-
-#define OPC_B 0x01 /* only used with OPC_WL */
-#define OPC_WL 0x02 /* accepts w, l or no suffix */
-#define OPC_BWL (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */
-#define OPC_REG 0x04 /* register is added to opcode */
-#define OPC_MODRM 0x08 /* modrm encoding */
-
-#define OPCT_MASK 0x70
-#define OPC_FWAIT 0x10 /* add fwait opcode */
-#define OPC_SHIFT 0x20 /* shift opcodes */
-#define OPC_ARITH 0x30 /* arithmetic opcodes */
-#define OPC_FARITH 0x40 /* FPU arithmetic opcodes */
-#define OPC_TEST 0x50 /* test opcodes */
-#define OPC_0F01 0x60 /* 0x0f01XX (group 7, XX is 2nd opcode,
- no operands and unstructured mod/rm) */
-#define OPCT_IS(v,i) (((v) & OPCT_MASK) == (i))
-
-#define OPC_0F 0x100 /* Is secondary map (0x0f prefix) */
-#define OPC_48 0x200 /* Always has REX prefix */
-#ifdef TCC_TARGET_X86_64
-# define OPC_WLQ 0x1000 /* accepts w, l, q or no suffix */
-# define OPC_BWLQ (OPC_B | OPC_WLQ) /* accepts b, w, l, q or no suffix */
-# define OPC_WLX OPC_WLQ
-# define OPC_BWLX OPC_BWLQ
-#else
-# define OPC_WLX OPC_WL
-# define OPC_BWLX OPC_BWL
-#endif
-
-#define OPC_GROUP_SHIFT 13
-
-/* in order to compress the operand type, we use specific operands and
- we or only with EA */
-enum {
- OPT_REG8=0, /* warning: value is hardcoded from TOK_ASM_xxx */
- OPT_REG16, /* warning: value is hardcoded from TOK_ASM_xxx */
- OPT_REG32, /* warning: value is hardcoded from TOK_ASM_xxx */
-#ifdef TCC_TARGET_X86_64
- OPT_REG64, /* warning: value is hardcoded from TOK_ASM_xxx */
-#endif
- OPT_MMX, /* warning: value is hardcoded from TOK_ASM_xxx */
- OPT_SSE, /* warning: value is hardcoded from TOK_ASM_xxx */
- OPT_CR, /* warning: value is hardcoded from TOK_ASM_xxx */
- OPT_TR, /* warning: value is hardcoded from TOK_ASM_xxx */
- OPT_DB, /* warning: value is hardcoded from TOK_ASM_xxx */
- OPT_SEG,
- OPT_ST,
-#ifdef TCC_TARGET_X86_64
- OPT_REG8_LOW, /* %spl,%bpl,%sil,%dil, encoded like ah,ch,dh,bh, but
- with REX prefix, not used in insn templates */
-#endif
- OPT_IM8,
- OPT_IM8S,
- OPT_IM16,
- OPT_IM32,
-#ifdef TCC_TARGET_X86_64
- OPT_IM64,
-#endif
- OPT_EAX, /* %al, %ax, %eax or %rax register */
- OPT_ST0, /* %st(0) register */
- OPT_CL, /* %cl register */
- OPT_DX, /* %dx register */
- OPT_ADDR, /* OP_EA with only offset */
- OPT_INDIR, /* *(expr) */
- /* composite types */
- OPT_COMPOSITE_FIRST,
- OPT_IM, /* IM8 | IM16 | IM32 */
- OPT_REG, /* REG8 | REG16 | REG32 | REG64 */
- OPT_REGW, /* REG16 | REG32 | REG64 */
- OPT_IMW, /* IM16 | IM32 */
- OPT_MMXSSE, /* MMX | SSE */
- OPT_DISP, /* Like OPT_ADDR, but emitted as displacement (for jumps) */
- OPT_DISP8, /* Like OPT_ADDR, but only 8bit (short jumps) */
- /* can be ored with any OPT_xxx */
- OPT_EA = 0x80
-};
-
-#define OP_REG8 (1 << OPT_REG8)
-#define OP_REG16 (1 << OPT_REG16)
-#define OP_REG32 (1 << OPT_REG32)
-#define OP_MMX (1 << OPT_MMX)
-#define OP_SSE (1 << OPT_SSE)
-#define OP_CR (1 << OPT_CR)
-#define OP_TR (1 << OPT_TR)
-#define OP_DB (1 << OPT_DB)
-#define OP_SEG (1 << OPT_SEG)
-#define OP_ST (1 << OPT_ST)
-#define OP_IM8 (1 << OPT_IM8)
-#define OP_IM8S (1 << OPT_IM8S)
-#define OP_IM16 (1 << OPT_IM16)
-#define OP_IM32 (1 << OPT_IM32)
-#define OP_EAX (1 << OPT_EAX)
-#define OP_ST0 (1 << OPT_ST0)
-#define OP_CL (1 << OPT_CL)
-#define OP_DX (1 << OPT_DX)
-#define OP_ADDR (1 << OPT_ADDR)
-#define OP_INDIR (1 << OPT_INDIR)
-#ifdef TCC_TARGET_X86_64
-# define OP_REG64 (1 << OPT_REG64)
-# define OP_REG8_LOW (1 << OPT_REG8_LOW)
-# define OP_IM64 (1 << OPT_IM64)
-# define OP_EA32 (OP_EA << 1)
-#else
-# define OP_REG64 0
-# define OP_REG8_LOW 0
-# define OP_IM64 0
-# define OP_EA32 0
-#endif
-
-#define OP_EA 0x40000000
-#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64)
-
-#ifdef TCC_TARGET_X86_64
-# define TREG_XAX TREG_RAX
-# define TREG_XCX TREG_RCX
-# define TREG_XDX TREG_RDX
-#else
-# define TREG_XAX TREG_EAX
-# define TREG_XCX TREG_ECX
-# define TREG_XDX TREG_EDX
-#endif
-
-typedef struct ASMInstr {
- uint16_t sym;
- uint16_t opcode;
- uint16_t instr_type;
- uint8_t nb_ops;
- uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */
-} ASMInstr;
-
-typedef struct Operand {
- uint32_t type;
- int8_t reg; /* register, -1 if none */
- int8_t reg2; /* second register, -1 if none */
- uint8_t shift;
- ExprValue e;
-} Operand;
-
-static const uint8_t reg_to_size[9] = {
-/*
- [OP_REG8] = 0,
- [OP_REG16] = 1,
- [OP_REG32] = 2,
-#ifdef TCC_TARGET_X86_64
- [OP_REG64] = 3,
-#endif
-*/
- 0, 0, 1, 0, 2, 0, 0, 0, 3
-};
-
-#define NB_TEST_OPCODES 30
-
-static const uint8_t test_bits[NB_TEST_OPCODES] = {
- 0x00, /* o */
- 0x01, /* no */
- 0x02, /* b */
- 0x02, /* c */
- 0x02, /* nae */
- 0x03, /* nb */
- 0x03, /* nc */
- 0x03, /* ae */
- 0x04, /* e */
- 0x04, /* z */
- 0x05, /* ne */
- 0x05, /* nz */
- 0x06, /* be */
- 0x06, /* na */
- 0x07, /* nbe */
- 0x07, /* a */
- 0x08, /* s */
- 0x09, /* ns */
- 0x0a, /* p */
- 0x0a, /* pe */
- 0x0b, /* np */
- 0x0b, /* po */
- 0x0c, /* l */
- 0x0c, /* nge */
- 0x0d, /* nl */
- 0x0d, /* ge */
- 0x0e, /* le */
- 0x0e, /* ng */
- 0x0f, /* nle */
- 0x0f, /* g */
-};
-
-static const uint8_t segment_prefixes[] = {
- 0x26, /* es */
- 0x2e, /* cs */
- 0x36, /* ss */
- 0x3e, /* ds */
- 0x64, /* fs */
- 0x65 /* gs */
-};
-
-static const ASMInstr asm_instrs[] = {
-#define ALT(x) x
-/* This removes a 0x0f in the second byte */
-#define O(o) ((uint64_t) ((((o) & 0xff00) == 0x0f00) ? ((((o) >> 8) & ~0xff) | ((o) & 0xff)) : (o)))
-/* This constructs instr_type from opcode, type and group. */
-#define T(o,i,g) ((i) | ((g) << OPC_GROUP_SHIFT) | ((((o) & 0xff00) == 0x0f00) ? OPC_0F : 0))
-#define DEF_ASM_OP0(name, opcode)
-#define DEF_ASM_OP0L(name, opcode, group, instr_type) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 0, { 0 } },
-#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 1, { op0 }},
-#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 2, { op0, op1 }},
-#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) { TOK_ASM_ ## name, O(opcode), T(opcode, instr_type, group), 3, { op0, op1, op2 }},
-#ifdef TCC_TARGET_X86_64
-# include "x86_64-asm.h"
-#else
-# include "i386-asm.h"
-#endif
- /* last operation */
- { 0, },
-};
-
-static const uint16_t op0_codes[] = {
-#define ALT(x)
-#define DEF_ASM_OP0(x, opcode) opcode,
-#define DEF_ASM_OP0L(name, opcode, group, instr_type)
-#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
-#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
-#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
-#ifdef TCC_TARGET_X86_64
-# include "x86_64-asm.h"
-#else
-# include "i386-asm.h"
-#endif
-};
-
-static inline int get_reg_shift(TCCState *s1)
-{
- int shift, v;
- v = asm_int_expr(s1);
- switch(v) {
- case 1:
- shift = 0;
- break;
- case 2:
- shift = 1;
- break;
- case 4:
- shift = 2;
- break;
- case 8:
- shift = 3;
- break;
- default:
- expect("1, 2, 4 or 8 constant");
- shift = 0;
- break;
- }
- return shift;
-}
-
-#ifdef TCC_TARGET_X86_64
-static int asm_parse_numeric_reg(int t, unsigned int *type)
-{
- int reg = -1;
- if (t >= TOK_IDENT && t < tok_ident) {
- const char *s = table_ident[t - TOK_IDENT]->str;
- char c;
- *type = OP_REG64;
- if (*s == 'c') {
- s++;
- *type = OP_CR;
- }
- if (*s++ != 'r')
- return -1;
- /* Don't allow leading '0'. */
- if ((c = *s++) >= '1' && c <= '9')
- reg = c - '0';
- else
- return -1;
- if ((c = *s) >= '0' && c <= '5')
- s++, reg = reg * 10 + c - '0';
- if (reg > 15)
- return -1;
- if ((c = *s) == 0)
- ;
- else if (*type != OP_REG64)
- return -1;
- else if (c == 'b' && !s[1])
- *type = OP_REG8;
- else if (c == 'w' && !s[1])
- *type = OP_REG16;
- else if (c == 'd' && !s[1])
- *type = OP_REG32;
- else
- return -1;
- }
- return reg;
-}
-#endif
-
-static int asm_parse_reg(unsigned int *type)
-{
- int reg = 0;
- *type = 0;
- if (tok != '%')
- goto error_32;
- next();
- if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
- reg = tok - TOK_ASM_eax;
- *type = OP_REG32;
-#ifdef TCC_TARGET_X86_64
- } else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) {
- reg = tok - TOK_ASM_rax;
- *type = OP_REG64;
- } else if (tok == TOK_ASM_rip) {
- reg = -2; /* Probably should use different escape code. */
- *type = OP_REG64;
- } else if ((reg = asm_parse_numeric_reg(tok, type)) >= 0
- && (*type == OP_REG32 || *type == OP_REG64)) {
- ;
-#endif
- } else {
- error_32:
- expect("register");
- }
- next();
- return reg;
-}
-
-static void parse_operand(TCCState *s1, Operand *op)
-{
- ExprValue e;
- int reg, indir;
- const char *p;
-
- indir = 0;
- if (tok == '*') {
- next();
- indir = OP_INDIR;
- }
-
- if (tok == '%') {
- next();
- if (tok >= TOK_ASM_al && tok <= TOK_ASM_db7) {
- reg = tok - TOK_ASM_al;
- op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
- op->reg = reg & 7;
- if ((op->type & OP_REG) && op->reg == TREG_XAX)
- op->type |= OP_EAX;
- else if (op->type == OP_REG8 && op->reg == TREG_XCX)
- op->type |= OP_CL;
- else if (op->type == OP_REG16 && op->reg == TREG_XDX)
- op->type |= OP_DX;
- } else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
- op->type = OP_DB;
- op->reg = tok - TOK_ASM_dr0;
- } else if (tok >= TOK_ASM_es && tok <= TOK_ASM_gs) {
- op->type = OP_SEG;
- op->reg = tok - TOK_ASM_es;
- } else if (tok == TOK_ASM_st) {
- op->type = OP_ST;
- op->reg = 0;
- next();
- if (tok == '(') {
- next();
- if (tok != TOK_PPNUM)
- goto reg_error;
- p = tokc.str.data;
- reg = p[0] - '0';
- if ((unsigned)reg >= 8 || p[1] != '\0')
- goto reg_error;
- op->reg = reg;
- next();
- skip(')');
- }
- if (op->reg == 0)
- op->type |= OP_ST0;
- goto no_skip;
-#ifdef TCC_TARGET_X86_64
- } else if (tok >= TOK_ASM_spl && tok <= TOK_ASM_dil) {
- op->type = OP_REG8 | OP_REG8_LOW;
- op->reg = 4 + tok - TOK_ASM_spl;
- } else if ((op->reg = asm_parse_numeric_reg(tok, &op->type)) >= 0) {
- ;
-#endif
- } else {
- reg_error:
- tcc_error("unknown register %%%s", get_tok_str(tok, &tokc));
- }
- next();
- no_skip: ;
- } else if (tok == '$') {
- /* constant value */
- next();
- asm_expr(s1, &e);
- op->type = OP_IM32;
- op->e = e;
- if (!op->e.sym) {
- if (op->e.v == (uint8_t)op->e.v)
- op->type |= OP_IM8;
- if (op->e.v == (int8_t)op->e.v)
- op->type |= OP_IM8S;
- if (op->e.v == (uint16_t)op->e.v)
- op->type |= OP_IM16;
-#ifdef TCC_TARGET_X86_64
- if (op->e.v != (int32_t)op->e.v && op->e.v != (uint32_t)op->e.v)
- op->type = OP_IM64;
-#endif
- }
- } else {
- /* address(reg,reg2,shift) with all variants */
- op->type = OP_EA;
- op->reg = -1;
- op->reg2 = -1;
- op->shift = 0;
- if (tok != '(') {
- asm_expr(s1, &e);
- op->e = e;
- } else {
- next();
- if (tok == '%') {
- unget_tok('(');
- op->e.v = 0;
- op->e.sym = NULL;
- } else {
- /* bracketed offset expression */
- asm_expr(s1, &e);
- if (tok != ')')
- expect(")");
- next();
- op->e.v = e.v;
- op->e.sym = e.sym;
- }
- op->e.pcrel = 0;
- }
- if (tok == '(') {
- unsigned int type = 0;
- next();
- if (tok != ',') {
- op->reg = asm_parse_reg(&type);
- }
- if (tok == ',') {
- next();
- if (tok != ',') {
- op->reg2 = asm_parse_reg(&type);
- }
- if (tok == ',') {
- next();
- op->shift = get_reg_shift(s1);
- }
- }
- if (type & OP_REG32)
- op->type |= OP_EA32;
- skip(')');
- }
- if (op->reg == -1 && op->reg2 == -1)
- op->type |= OP_ADDR;
- }
- op->type |= indir;
-}
-
-/* XXX: unify with C code output ? */
-ST_FUNC void gen_expr32(ExprValue *pe)
-{
- if (pe->pcrel)
- /* If PC-relative, always set VT_SYM, even without symbol,
- so as to force a relocation to be emitted. */
- gen_addrpc32(VT_SYM, pe->sym, pe->v);
- else
- gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
-}
-
-#ifdef TCC_TARGET_X86_64
-ST_FUNC void gen_expr64(ExprValue *pe)
-{
- gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
-}
-#endif
-
-/* XXX: unify with C code output ? */
-static void gen_disp32(ExprValue *pe)
-{
- Sym *sym = pe->sym;
- ElfSym *esym = elfsym(sym);
- if (esym && esym->st_shndx == cur_text_section->sh_num) {
- /* same section: we can output an absolute value. Note
- that the TCC compiler behaves differently here because
- it always outputs a relocation to ease (future) code
- elimination in the linker */
- gen_le32(pe->v + esym->st_value - ind - 4);
- } else {
- if (sym && sym->type.t == VT_VOID) {
- sym->type.t = VT_FUNC;
- sym->type.ref = NULL;
- }
- gen_addrpc32(VT_SYM, sym, pe->v);
- }
-}
-
-/* generate the modrm operand */
-static inline int asm_modrm(int reg, Operand *op)
-{
- int mod, reg1, reg2, sib_reg1;
-
- if (op->type & (OP_REG | OP_MMX | OP_SSE)) {
- g(0xc0 + (reg << 3) + op->reg);
- } else if (op->reg == -1 && op->reg2 == -1) {
- /* displacement only */
-#ifdef TCC_TARGET_X86_64
- g(0x04 + (reg << 3));
- g(0x25);
-#else
- g(0x05 + (reg << 3));
-#endif
- gen_expr32(&op->e);
-#ifdef TCC_TARGET_X86_64
- } else if (op->reg == -2) {
- ExprValue *pe = &op->e;
- g(0x05 + (reg << 3));
- gen_addrpc32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
- return ind;
-#endif
- } else {
- sib_reg1 = op->reg;
- /* fist compute displacement encoding */
- if (sib_reg1 == -1) {
- sib_reg1 = 5;
- mod = 0x00;
- } else if (op->e.v == 0 && !op->e.sym && op->reg != 5) {
- mod = 0x00;
- } else if (op->e.v == (int8_t)op->e.v && !op->e.sym) {
- mod = 0x40;
- } else {
- mod = 0x80;
- }
- /* compute if sib byte needed */
- reg1 = op->reg;
- if (op->reg2 != -1)
- reg1 = 4;
- g(mod + (reg << 3) + reg1);
- if (reg1 == 4) {
- /* add sib byte */
- reg2 = op->reg2;
- if (reg2 == -1)
- reg2 = 4; /* indicate no index */
- g((op->shift << 6) + (reg2 << 3) + sib_reg1);
- }
- /* add offset */
- if (mod == 0x40) {
- g(op->e.v);
- } else if (mod == 0x80 || op->reg == -1) {
- gen_expr32(&op->e);
- }
- }
- return 0;
-}
-
-#ifdef TCC_TARGET_X86_64
-#define REX_W 0x48
-#define REX_R 0x44
-#define REX_X 0x42
-#define REX_B 0x41
-
-static void asm_rex(int width64, Operand *ops, int nb_ops, int *op_type,
- int regi, int rmi)
-{
- unsigned char rex = width64 ? 0x48 : 0;
- int saw_high_8bit = 0;
- int i;
- if (rmi == -1) {
- /* No mod/rm byte, but we might have a register op nevertheless
- (we will add it to the opcode later). */
- for(i = 0; i < nb_ops; i++) {
- if (op_type[i] & (OP_REG | OP_ST)) {
- if (ops[i].reg >= 8) {
- rex |= REX_B;
- ops[i].reg -= 8;
- } else if (ops[i].type & OP_REG8_LOW)
- rex |= 0x40;
- else if (ops[i].type & OP_REG8 && ops[i].reg >= 4)
- /* An 8 bit reg >= 4 without REG8 is ah/ch/dh/bh */
- saw_high_8bit = ops[i].reg;
- break;
- }
- }
- } else {
- if (regi != -1) {
- if (ops[regi].reg >= 8) {
- rex |= REX_R;
- ops[regi].reg -= 8;
- } else if (ops[regi].type & OP_REG8_LOW)
- rex |= 0x40;
- else if (ops[regi].type & OP_REG8 && ops[regi].reg >= 4)
- /* An 8 bit reg >= 4 without REG8 is ah/ch/dh/bh */
- saw_high_8bit = ops[regi].reg;
- }
- if (ops[rmi].type & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_EA)) {
- if (ops[rmi].reg >= 8) {
- rex |= REX_B;
- ops[rmi].reg -= 8;
- } else if (ops[rmi].type & OP_REG8_LOW)
- rex |= 0x40;
- else if (ops[rmi].type & OP_REG8 && ops[rmi].reg >= 4)
- /* An 8 bit reg >= 4 without REG8 is ah/ch/dh/bh */
- saw_high_8bit = ops[rmi].reg;
- }
- if (ops[rmi].type & OP_EA && ops[rmi].reg2 >= 8) {
- rex |= REX_X;
- ops[rmi].reg2 -= 8;
- }
- }
- if (rex) {
- if (saw_high_8bit)
- tcc_error("can't encode register %%%ch when REX prefix is required",
- "acdb"[saw_high_8bit-4]);
- g(rex);
- }
-}
-#endif
-
-
-static void maybe_print_stats (void)
-{
- static int already;
-
- if (0 && !already)
- /* print stats about opcodes */
- {
- const struct ASMInstr *pa;
- int freq[4];
- int op_vals[500];
- int nb_op_vals, i, j;
-
- already = 1;
- nb_op_vals = 0;
- memset(freq, 0, sizeof(freq));
- for(pa = asm_instrs; pa->sym != 0; pa++) {
- freq[pa->nb_ops]++;
- //for(i=0;i<pa->nb_ops;i++) {
- for(j=0;j<nb_op_vals;j++) {
- //if (pa->op_type[i] == op_vals[j])
- if (pa->instr_type == op_vals[j])
- goto found;
- }
- //op_vals[nb_op_vals++] = pa->op_type[i];
- op_vals[nb_op_vals++] = pa->instr_type;
- found: ;
- //}
- }
- for(i=0;i<nb_op_vals;i++) {
- int v = op_vals[i];
- //if ((v & (v - 1)) != 0)
- printf("%3d: %08x\n", i, v);
- }
- printf("size=%d nb=%d f0=%d f1=%d f2=%d f3=%d\n",
- (int)sizeof(asm_instrs),
- (int)sizeof(asm_instrs) / (int)sizeof(ASMInstr),
- freq[0], freq[1], freq[2], freq[3]);
- }
-}
-
-ST_FUNC void asm_opcode(TCCState *s1, int opcode)
-{
- const ASMInstr *pa;
- int i, modrm_index, modreg_index, reg, v, op1, seg_prefix, pc, p;
- int nb_ops, s;
- Operand ops[MAX_OPERANDS], *pop;
- int op_type[3]; /* decoded op type */
- int alltypes; /* OR of all operand types */
- int autosize;
- int p66;
-#ifdef TCC_TARGET_X86_64
- int rex64;
-#endif
-
- maybe_print_stats();
- /* force synthetic ';' after prefix instruction, so we can handle */
- /* one-line things like "rep stosb" instead of only "rep\nstosb" */
- if (opcode >= TOK_ASM_wait && opcode <= TOK_ASM_repnz)
- unget_tok(';');
-
- /* get operands */
- pop = ops;
- nb_ops = 0;
- seg_prefix = 0;
- alltypes = 0;
- for(;;) {
- if (tok == ';' || tok == TOK_LINEFEED)
- break;
- if (nb_ops >= MAX_OPERANDS) {
- tcc_error("incorrect number of operands");
- }
- parse_operand(s1, pop);
- if (tok == ':') {
- if (pop->type != OP_SEG || seg_prefix)
- tcc_error("incorrect prefix");
- seg_prefix = segment_prefixes[pop->reg];
- next();
- parse_operand(s1, pop);
- if (!(pop->type & OP_EA)) {
- tcc_error("segment prefix must be followed by memory reference");
- }
- }
- pop++;
- nb_ops++;
- if (tok != ',')
- break;
- next();
- }
-
- s = 0; /* avoid warning */
-
-again:
- /* optimize matching by using a lookup table (no hashing is needed
- !) */
- for(pa = asm_instrs; pa->sym != 0; pa++) {
- int it = pa->instr_type & OPCT_MASK;
- s = 0;
- if (it == OPC_FARITH) {
- v = opcode - pa->sym;
- if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
- continue;
- } else if (it == OPC_ARITH) {
- if (!(opcode >= pa->sym && opcode < pa->sym + 8*NBWLX))
- continue;
- s = (opcode - pa->sym) % NBWLX;
- if ((pa->instr_type & OPC_BWLX) == OPC_WLX)
- {
- /* We need to reject the xxxb opcodes that we accepted above.
- Note that pa->sym for WLX opcodes is the 'w' token,
- to get the 'b' token subtract one. */
- if (((opcode - pa->sym + 1) % NBWLX) == 0)
- continue;
- s++;
- }
- } else if (it == OPC_SHIFT) {
- if (!(opcode >= pa->sym && opcode < pa->sym + 7*NBWLX))
- continue;
- s = (opcode - pa->sym) % NBWLX;
- } else if (it == OPC_TEST) {
- if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
- continue;
- /* cmovxx is a test opcode but accepts multiple sizes.
- The suffixes aren't encoded in the table, instead we
- simply force size autodetection always and deal with suffixed
- variants below when we don't find e.g. "cmovzl". */
- if (pa->instr_type & OPC_WLX)
- s = NBWLX - 1;
- } else if (pa->instr_type & OPC_B) {
-#ifdef TCC_TARGET_X86_64
- /* Some instructions don't have the full size but only
- bwl form. insb e.g. */
- if ((pa->instr_type & OPC_WLQ) != OPC_WLQ
- && !(opcode >= pa->sym && opcode < pa->sym + NBWLX-1))
- continue;
-#endif
- if (!(opcode >= pa->sym && opcode < pa->sym + NBWLX))
- continue;
- s = opcode - pa->sym;
- } else if (pa->instr_type & OPC_WLX) {
- if (!(opcode >= pa->sym && opcode < pa->sym + NBWLX-1))
- continue;
- s = opcode - pa->sym + 1;
- } else {
- if (pa->sym != opcode)
- continue;
- }
- if (pa->nb_ops != nb_ops)
- continue;
-#ifdef TCC_TARGET_X86_64
- /* Special case for moves. Selecting the IM64->REG64 form
- should only be done if we really have an >32bit imm64, and that
- is hardcoded. Ignore it here. */
- if (pa->opcode == 0xb0 && ops[0].type != OP_IM64
- && (ops[1].type & OP_REG) == OP_REG64
- && !(pa->instr_type & OPC_0F))
- continue;
-#endif
- /* now decode and check each operand */
- alltypes = 0;
- for(i = 0; i < nb_ops; i++) {
- int op1, op2;
- op1 = pa->op_type[i];
- op2 = op1 & 0x1f;
- switch(op2) {
- case OPT_IM:
- v = OP_IM8 | OP_IM16 | OP_IM32;
- break;
- case OPT_REG:
- v = OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64;
- break;
- case OPT_REGW:
- v = OP_REG16 | OP_REG32 | OP_REG64;
- break;
- case OPT_IMW:
- v = OP_IM16 | OP_IM32;
- break;
- case OPT_MMXSSE:
- v = OP_MMX | OP_SSE;
- break;
- case OPT_DISP:
- case OPT_DISP8:
- v = OP_ADDR;
- break;
- default:
- v = 1 << op2;
- break;
- }
- if (op1 & OPT_EA)
- v |= OP_EA;
- op_type[i] = v;
- if ((ops[i].type & v) == 0)
- goto next;
- alltypes |= ops[i].type;
- }
- (void)alltypes; /* maybe unused */
- /* all is matching ! */
- break;
- next: ;
- }
- if (pa->sym == 0) {
- if (opcode >= TOK_ASM_first && opcode <= TOK_ASM_last) {
- int b;
- b = op0_codes[opcode - TOK_ASM_first];
- if (b & 0xff00)
- g(b >> 8);
- g(b);
- return;
- } else if (opcode <= TOK_ASM_alllast) {
- tcc_error("bad operand with opcode '%s'",
- get_tok_str(opcode, NULL));
- } else {
- /* Special case for cmovcc, we accept size suffixes but ignore
- them, but we don't want them to blow up our tables. */
- TokenSym *ts = table_ident[opcode - TOK_IDENT];
- if (ts->len >= 6
- && strchr("wlq", ts->str[ts->len-1])
- && !memcmp(ts->str, "cmov", 4)) {
- opcode = tok_alloc(ts->str, ts->len-1)->tok;
- goto again;
- }
- tcc_error("unknown opcode '%s'", ts->str);
- }
- }
- /* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
- autosize = NBWLX-1;
-#ifdef TCC_TARGET_X86_64
- /* XXX the autosize should rather be zero, to not have to adjust this
- all the time. */
- if ((pa->instr_type & OPC_BWLQ) == OPC_B)
- autosize = NBWLX-2;
-#endif
- if (s == autosize) {
- /* Check for register operands providing hints about the size.
- Start from the end, i.e. destination operands. This matters
- only for opcodes accepting different sized registers, lar and lsl
- are such opcodes. */
- for(i = nb_ops - 1; s == autosize && i >= 0; i--) {
- if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
- s = reg_to_size[ops[i].type & OP_REG];
- }
- if (s == autosize) {
- if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
- (ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))
- s = 2;
- else if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
- (ops[0].type & OP_EA))
- s = NBWLX - 2;
- else
- tcc_error("cannot infer opcode suffix");
- }
- }
-
-#ifdef TCC_TARGET_X86_64
- rex64 = 0;
- if (pa->instr_type & OPC_48)
- rex64 = 1;
- else if (s == 3 || (alltypes & OP_REG64)) {
- /* generate REX prefix */
- int default64 = 0;
- for(i = 0; i < nb_ops; i++) {
- if (op_type[i] == OP_REG64 && pa->opcode != 0xb8) {
- /* If only 64bit regs are accepted in one operand
- this is a default64 instruction without need for
- REX prefixes, except for movabs(0xb8). */
- default64 = 1;
- break;
- }
- }
- /* XXX find better encoding for the default64 instructions. */
- if (((opcode != TOK_ASM_push && opcode != TOK_ASM_pop
- && opcode != TOK_ASM_pushw && opcode != TOK_ASM_pushl
- && opcode != TOK_ASM_pushq && opcode != TOK_ASM_popw
- && opcode != TOK_ASM_popl && opcode != TOK_ASM_popq
- && opcode != TOK_ASM_call && opcode != TOK_ASM_jmp))
- && !default64)
- rex64 = 1;
- }
-#endif
-
- /* now generates the operation */
- if (OPCT_IS(pa->instr_type, OPC_FWAIT))
- g(0x9b);
- if (seg_prefix)
- g(seg_prefix);
-#ifdef TCC_TARGET_X86_64
- /* Generate addr32 prefix if needed */
- for(i = 0; i < nb_ops; i++) {
- if (ops[i].type & OP_EA32) {
- g(0x67);
- break;
- }
- }
-#endif
- /* generate data16 prefix if needed */
- p66 = 0;
- if (s == 1)
- p66 = 1;
- else {
- /* accepting mmx+sse in all operands --> needs 0x66 to
- switch to sse mode. Accepting only sse in an operand --> is
- already SSE insn and needs 0x66/f2/f3 handling. */
- for (i = 0; i < nb_ops; i++)
- if ((op_type[i] & (OP_MMX | OP_SSE)) == (OP_MMX | OP_SSE)
- && ops[i].type & OP_SSE)
- p66 = 1;
- }
- if (p66)
- g(0x66);
-
- v = pa->opcode;
- p = v >> 8; /* possibly prefix byte(s) */
- switch (p) {
- case 0: break; /* no prefix */
- case 0x48: break; /* REX, handled elsewhere */
- case 0x66:
- case 0x67:
- case 0xf2:
- case 0xf3: v = v & 0xff; g(p); break;
- case 0xd4: case 0xd5: break; /* aam and aad, not prefix, but hardcoded immediate argument "10" */
- case 0xd8: case 0xd9: case 0xda: case 0xdb: /* x87, no normal prefix */
- case 0xdc: case 0xdd: case 0xde: case 0xdf: break;
- default: tcc_error("bad prefix 0x%2x in opcode table", p); break;
- }
- if (pa->instr_type & OPC_0F)
- v = ((v & ~0xff) << 8) | 0x0f00 | (v & 0xff);
- if ((v == 0x69 || v == 0x6b) && nb_ops == 2) {
- /* kludge for imul $im, %reg */
- nb_ops = 3;
- ops[2] = ops[1];
- op_type[2] = op_type[1];
- } else if (v == 0xcd && ops[0].e.v == 3 && !ops[0].e.sym) {
- v--; /* int $3 case */
- nb_ops = 0;
- } else if ((v == 0x06 || v == 0x07)) {
- if (ops[0].reg >= 4) {
- /* push/pop %fs or %gs */
- v = 0x0fa0 + (v - 0x06) + ((ops[0].reg - 4) << 3);
- } else {
- v += ops[0].reg << 3;
- }
- nb_ops = 0;
- } else if (v <= 0x05) {
- /* arith case */
- v += ((opcode - TOK_ASM_addb) / NBWLX) << 3;
- } else if ((pa->instr_type & (OPCT_MASK | OPC_MODRM)) == OPC_FARITH) {
- /* fpu arith case */
- v += ((opcode - pa->sym) / 6) << 3;
- }
-
- /* search which operand will be used for modrm */
- modrm_index = -1;
- modreg_index = -1;
- if (pa->instr_type & OPC_MODRM) {
- if (!nb_ops) {
- /* A modrm opcode without operands is a special case (e.g. mfence).
- It has a group and acts as if there's an register operand 0
- (ax). */
- i = 0;
- ops[i].type = OP_REG;
- ops[i].reg = 0;
- goto modrm_found;
- }
- /* first look for an ea operand */
- for(i = 0;i < nb_ops; i++) {
- if (op_type[i] & OP_EA)
- goto modrm_found;
- }
- /* then if not found, a register or indirection (shift instructions) */
- for(i = 0;i < nb_ops; i++) {
- if (op_type[i] & (OP_REG | OP_MMX | OP_SSE | OP_INDIR))
- goto modrm_found;
- }
-#ifdef ASM_DEBUG
- tcc_error("bad op table");
-#endif
- modrm_found:
- modrm_index = i;
- /* if a register is used in another operand then it is
- used instead of group */
- for(i = 0;i < nb_ops; i++) {
- int t = op_type[i];
- if (i != modrm_index &&
- (t & (OP_REG | OP_MMX | OP_SSE | OP_CR | OP_TR | OP_DB | OP_SEG))) {
- modreg_index = i;
- break;
- }
- }
- }
-#ifdef TCC_TARGET_X86_64
- asm_rex (rex64, ops, nb_ops, op_type, modreg_index, modrm_index);
-#endif
-
- if (pa->instr_type & OPC_REG) {
- /* mov $im, %reg case */
- if (v == 0xb0 && s >= 1)
- v += 7;
- for(i = 0; i < nb_ops; i++) {
- if (op_type[i] & (OP_REG | OP_ST)) {
- v += ops[i].reg;
- break;
- }
- }
- }
- if (pa->instr_type & OPC_B)
- v += s >= 1;
- if (nb_ops == 1 && pa->op_type[0] == OPT_DISP8) {
- ElfSym *esym;
- int jmp_disp;
-
- /* see if we can really generate the jump with a byte offset */
- esym = elfsym(ops[0].e.sym);
- if (!esym || esym->st_shndx != cur_text_section->sh_num)
- goto no_short_jump;
- jmp_disp = ops[0].e.v + esym->st_value - ind - 2 - (v >= 0xff);
- if (jmp_disp == (int8_t)jmp_disp) {
- /* OK to generate jump */
- ops[0].e.sym = 0;
- ops[0].e.v = jmp_disp;
- op_type[0] = OP_IM8S;
- } else {
- no_short_jump:
- /* long jump will be allowed. need to modify the
- opcode slightly */
- if (v == 0xeb) /* jmp */
- v = 0xe9;
- else if (v == 0x70) /* jcc */
- v += 0x0f10;
- else
- tcc_error("invalid displacement");
- }
- }
- if (OPCT_IS(pa->instr_type, OPC_TEST))
- v += test_bits[opcode - pa->sym];
- else if (OPCT_IS(pa->instr_type, OPC_0F01))
- v |= 0x0f0100;
- op1 = v >> 16;
- if (op1)
- g(op1);
- op1 = (v >> 8) & 0xff;
- if (op1)
- g(op1);
- g(v);
-
- if (OPCT_IS(pa->instr_type, OPC_SHIFT)) {
- reg = (opcode - pa->sym) / NBWLX;
- if (reg == 6)
- reg = 7;
- } else if (OPCT_IS(pa->instr_type, OPC_ARITH)) {
- reg = (opcode - pa->sym) / NBWLX;
- } else if (OPCT_IS(pa->instr_type, OPC_FARITH)) {
- reg = (opcode - pa->sym) / 6;
- } else {
- reg = (pa->instr_type >> OPC_GROUP_SHIFT) & 7;
- }
-
- pc = 0;
- if (pa->instr_type & OPC_MODRM) {
- /* if a register is used in another operand then it is
- used instead of group */
- if (modreg_index >= 0)
- reg = ops[modreg_index].reg;
- pc = asm_modrm(reg, &ops[modrm_index]);
- }
-
- /* emit constants */
-#ifndef TCC_TARGET_X86_64
- if (!(pa->instr_type & OPC_0F)
- && (pa->opcode == 0x9a || pa->opcode == 0xea)) {
- /* ljmp or lcall kludge */
- gen_expr32(&ops[1].e);
- if (ops[0].e.sym)
- tcc_error("cannot relocate");
- gen_le16(ops[0].e.v);
- return;
- }
-#endif
- for(i = 0;i < nb_ops; i++) {
- v = op_type[i];
- if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64 | OP_IM8S | OP_ADDR)) {
- /* if multiple sizes are given it means we must look
- at the op size */
- if ((v | OP_IM8 | OP_IM64) == (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64)) {
- if (s == 0)
- v = OP_IM8;
- else if (s == 1)
- v = OP_IM16;
- else if (s == 2 || (v & OP_IM64) == 0)
- v = OP_IM32;
- else
- v = OP_IM64;
- }
-
- if ((v & (OP_IM8 | OP_IM8S | OP_IM16)) && ops[i].e.sym)
- tcc_error("cannot relocate");
-
- if (v & (OP_IM8 | OP_IM8S)) {
- g(ops[i].e.v);
- } else if (v & OP_IM16) {
- gen_le16(ops[i].e.v);
-#ifdef TCC_TARGET_X86_64
- } else if (v & OP_IM64) {
- gen_expr64(&ops[i].e);
-#endif
- } else if (pa->op_type[i] == OPT_DISP || pa->op_type[i] == OPT_DISP8) {
- gen_disp32(&ops[i].e);
- } else {
- gen_expr32(&ops[i].e);
- }
- }
- }
-
- /* after immediate operands, adjust pc-relative address */
- if (pc)
- add32le(cur_text_section->data + pc - 4, pc - ind);
-}
-
-/* return the constraint priority (we allocate first the lowest
- numbered constraints) */
-static inline int constraint_priority(const char *str)
-{
- int priority, c, pr;
-
- /* we take the lowest priority */
- priority = 0;
- for(;;) {
- c = *str;
- if (c == '\0')
- break;
- str++;
- switch(c) {
- case 'A':
- pr = 0;
- break;
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'S':
- case 'D':
- pr = 1;
- break;
- case 'q':
- pr = 2;
- break;
- case 'r':
- case 'R':
- case 'p':
- pr = 3;
- break;
- case 'N':
- case 'M':
- case 'I':
- case 'e':
- case 'i':
- case 'm':
- case 'g':
- pr = 4;
- break;
- default:
- tcc_error("unknown constraint '%c'", c);
- pr = 0;
- }
- if (pr > priority)
- priority = pr;
- }
- return priority;
-}
-
-static const char *skip_constraint_modifiers(const char *p)
-{
- while (*p == '=' || *p == '&' || *p == '+' || *p == '%')
- p++;
- return p;
-}
-
-/* If T (a token) is of the form "%reg" returns the register
- number and type, otherwise return -1. */
-ST_FUNC int asm_parse_regvar (int t)
-{
- const char *s;
- Operand op;
- if (t < TOK_IDENT || (t & SYM_FIELD))
- return -1;
- s = table_ident[t - TOK_IDENT]->str;
- if (s[0] != '%')
- return -1;
- t = tok_alloc_const(s + 1);
- unget_tok(t);
- unget_tok('%');
- parse_operand(tcc_state, &op);
- /* Accept only integer regs for now. */
- if (op.type & OP_REG)
- return op.reg;
- else
- return -1;
-}
-
-#define REG_OUT_MASK 0x01
-#define REG_IN_MASK 0x02
-
-#define is_reg_allocated(reg) (regs_allocated[reg] & reg_mask)
-
-ST_FUNC void asm_compute_constraints(ASMOperand *operands,
- int nb_operands, int nb_outputs,
- const uint8_t *clobber_regs,
- int *pout_reg)
-{
- ASMOperand *op;
- int sorted_op[MAX_ASM_OPERANDS];
- int i, j, k, p1, p2, tmp, reg, c, reg_mask;
- const char *str;
- uint8_t regs_allocated[NB_ASM_REGS];
-
- /* init fields */
- for(i=0;i<nb_operands;i++) {
- op = &operands[i];
- op->input_index = -1;
- op->ref_index = -1;
- op->reg = -1;
- op->is_memory = 0;
- op->is_rw = 0;
- }
- /* compute constraint priority and evaluate references to output
- constraints if input constraints */
- for(i=0;i<nb_operands;i++) {
- op = &operands[i];
- str = op->constraint;
- str = skip_constraint_modifiers(str);
- if (isnum(*str) || *str == '[') {
- /* this is a reference to another constraint */
- k = find_constraint(operands, nb_operands, str, NULL);
- if ((unsigned)k >= i || i < nb_outputs)
- tcc_error("invalid reference in constraint %d ('%s')",
- i, str);
- op->ref_index = k;
- if (operands[k].input_index >= 0)
- tcc_error("cannot reference twice the same operand");
- operands[k].input_index = i;
- op->priority = 5;
- } else if ((op->vt->r & VT_VALMASK) == VT_LOCAL
- && op->vt->sym
- && (reg = op->vt->sym->r & VT_VALMASK) < VT_CONST) {
- op->priority = 1;
- op->reg = reg;
- } else {
- op->priority = constraint_priority(str);
- }
- }
-
- /* sort operands according to their priority */
- for(i=0;i<nb_operands;i++)
- sorted_op[i] = i;
- for(i=0;i<nb_operands - 1;i++) {
- for(j=i+1;j<nb_operands;j++) {
- p1 = operands[sorted_op[i]].priority;
- p2 = operands[sorted_op[j]].priority;
- if (p2 < p1) {
- tmp = sorted_op[i];
- sorted_op[i] = sorted_op[j];
- sorted_op[j] = tmp;
- }
- }
- }
-
- for(i = 0;i < NB_ASM_REGS; i++) {
- if (clobber_regs[i])
- regs_allocated[i] = REG_IN_MASK | REG_OUT_MASK;
- else
- regs_allocated[i] = 0;
- }
- /* esp cannot be used */
- regs_allocated[4] = REG_IN_MASK | REG_OUT_MASK;
- /* ebp cannot be used yet */
- regs_allocated[5] = REG_IN_MASK | REG_OUT_MASK;
-
- /* allocate registers and generate corresponding asm moves */
- for(i=0;i<nb_operands;i++) {
- j = sorted_op[i];
- op = &operands[j];
- str = op->constraint;
- /* no need to allocate references */
- if (op->ref_index >= 0)
- continue;
- /* select if register is used for output, input or both */
- if (op->input_index >= 0) {
- reg_mask = REG_IN_MASK | REG_OUT_MASK;
- } else if (j < nb_outputs) {
- reg_mask = REG_OUT_MASK;
- } else {
- reg_mask = REG_IN_MASK;
- }
- if (op->reg >= 0) {
- if (is_reg_allocated(op->reg))
- tcc_error("asm regvar requests register that's taken already");
- reg = op->reg;
- goto reg_found;
- }
- try_next:
- c = *str++;
- switch(c) {
- case '=':
- goto try_next;
- case '+':
- op->is_rw = 1;
- /* FALL THRU */
- case '&':
- if (j >= nb_outputs)
- tcc_error("'%c' modifier can only be applied to outputs", c);
- reg_mask = REG_IN_MASK | REG_OUT_MASK;
- goto try_next;
- case 'A':
- /* allocate both eax and edx */
- if (is_reg_allocated(TREG_XAX) ||
- is_reg_allocated(TREG_XDX))
- goto try_next;
- op->is_llong = 1;
- op->reg = TREG_XAX;
- regs_allocated[TREG_XAX] |= reg_mask;
- regs_allocated[TREG_XDX] |= reg_mask;
- break;
- case 'a':
- reg = TREG_XAX;
- goto alloc_reg;
- case 'b':
- reg = 3;
- goto alloc_reg;
- case 'c':
- reg = TREG_XCX;
- goto alloc_reg;
- case 'd':
- reg = TREG_XDX;
- goto alloc_reg;
- case 'S':
- reg = 6;
- goto alloc_reg;
- case 'D':
- reg = 7;
- alloc_reg:
- if (is_reg_allocated(reg))
- goto try_next;
- goto reg_found;
- case 'q':
- /* eax, ebx, ecx or edx */
- for(reg = 0; reg < 4; reg++) {
- if (!is_reg_allocated(reg))
- goto reg_found;
- }
- goto try_next;
- case 'r':
- case 'R':
- case 'p': /* A general address, for x86(64) any register is acceptable*/
- /* any general register */
- for(reg = 0; reg < 8; reg++) {
- if (!is_reg_allocated(reg))
- goto reg_found;
- }
- goto try_next;
- reg_found:
- /* now we can reload in the register */
- op->is_llong = 0;
- op->reg = reg;
- regs_allocated[reg] |= reg_mask;
- break;
- case 'e':
- case 'i':
- if (!((op->vt->r & (VT_VALMASK | VT_LVAL)) == VT_CONST))
- goto try_next;
- break;
- case 'I':
- case 'N':
- case 'M':
- if (!((op->vt->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST))
- goto try_next;
- break;
- case 'm':
- case 'g':
- /* nothing special to do because the operand is already in
- memory, except if the pointer itself is stored in a
- memory variable (VT_LLOCAL case) */
- /* XXX: fix constant case */
- /* if it is a reference to a memory zone, it must lie
- in a register, so we reserve the register in the
- input registers and a load will be generated
- later */
- if (j < nb_outputs || c == 'm') {
- if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
- /* any general register */
- for(reg = 0; reg < 8; reg++) {
- if (!(regs_allocated[reg] & REG_IN_MASK))
- goto reg_found1;
- }
- goto try_next;
- reg_found1:
- /* now we can reload in the register */
- regs_allocated[reg] |= REG_IN_MASK;
- op->reg = reg;
- op->is_memory = 1;
- }
- }
- break;
- default:
- tcc_error("asm constraint %d ('%s') could not be satisfied",
- j, op->constraint);
- break;
- }
- /* if a reference is present for that operand, we assign it too */
- if (op->input_index >= 0) {
- operands[op->input_index].reg = op->reg;
- operands[op->input_index].is_llong = op->is_llong;
- }
- }
-
- /* compute out_reg. It is used to store outputs registers to memory
- locations references by pointers (VT_LLOCAL case) */
- *pout_reg = -1;
- for(i=0;i<nb_operands;i++) {
- op = &operands[i];
- if (op->reg >= 0 &&
- (op->vt->r & VT_VALMASK) == VT_LLOCAL &&
- !op->is_memory) {
- for(reg = 0; reg < 8; reg++) {
- if (!(regs_allocated[reg] & REG_OUT_MASK))
- goto reg_found2;
- }
- tcc_error("could not find free output register for reloading");
- reg_found2:
- *pout_reg = reg;
- break;
- }
- }
-
- /* print sorted constraints */
-#ifdef ASM_DEBUG
- for(i=0;i<nb_operands;i++) {
- j = sorted_op[i];
- op = &operands[j];
- printf("%%%d [%s]: \"%s\" r=0x%04x reg=%d\n",
- j,
- op->id ? get_tok_str(op->id, NULL) : "",
- op->constraint,
- op->vt->r,
- op->reg);
- }
- if (*pout_reg >= 0)
- printf("out_reg=%d\n", *pout_reg);
-#endif
-}
-
-ST_FUNC void subst_asm_operand(CString *add_str,
- SValue *sv, int modifier)
-{
- int r, reg, size, val;
- char buf[64];
-
- r = sv->r;
- if ((r & VT_VALMASK) == VT_CONST) {
- if (!(r & VT_LVAL) && modifier != 'c' && modifier != 'n' &&
- modifier != 'P')
- cstr_ccat(add_str, '$');
- if (r & VT_SYM) {
- const char *name = get_tok_str(sv->sym->v, NULL);
- if (sv->sym->v >= SYM_FIRST_ANOM) {
- /* In case of anonymous symbols ("L.42", used
- for static data labels) we can't find them
- in the C symbol table when later looking up
- this name. So enter them now into the asm label
- list when we still know the symbol. */
- get_asm_sym(tok_alloc_const(name), sv->sym);
- }
- if (tcc_state->leading_underscore)
- cstr_ccat(add_str, '_');
- cstr_cat(add_str, name, -1);
- if ((uint32_t)sv->c.i == 0)
- goto no_offset;
- cstr_ccat(add_str, '+');
- }
- val = sv->c.i;
- if (modifier == 'n')
- val = -val;
- snprintf(buf, sizeof(buf), "%d", (int)sv->c.i);
- cstr_cat(add_str, buf, -1);
- no_offset:;
-#ifdef TCC_TARGET_X86_64
- if (r & VT_LVAL)
- cstr_cat(add_str, "(%rip)", -1);
-#endif
- } else if ((r & VT_VALMASK) == VT_LOCAL) {
-#ifdef TCC_TARGET_X86_64
- snprintf(buf, sizeof(buf), "%d(%%rbp)", (int)sv->c.i);
-#else
- snprintf(buf, sizeof(buf), "%d(%%ebp)", (int)sv->c.i);
-#endif
- cstr_cat(add_str, buf, -1);
- } else if (r & VT_LVAL) {
- reg = r & VT_VALMASK;
- if (reg >= VT_CONST)
- tcc_internal_error("");
- snprintf(buf, sizeof(buf), "(%%%s)",
-#ifdef TCC_TARGET_X86_64
- get_tok_str(TOK_ASM_rax + reg, NULL)
-#else
- get_tok_str(TOK_ASM_eax + reg, NULL)
-#endif
- );
- cstr_cat(add_str, buf, -1);
- } else {
- /* register case */
- reg = r & VT_VALMASK;
- if (reg >= VT_CONST)
- tcc_internal_error("");
-
- /* choose register operand size */
- if ((sv->type.t & VT_BTYPE) == VT_BYTE ||
- (sv->type.t & VT_BTYPE) == VT_BOOL)
- size = 1;
- else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
- size = 2;
-#ifdef TCC_TARGET_X86_64
- else if ((sv->type.t & VT_BTYPE) == VT_LLONG ||
- (sv->type.t & VT_BTYPE) == VT_PTR)
- size = 8;
-#endif
- else
- size = 4;
- if (size == 1 && reg >= 4)
- size = 4;
-
- if (modifier == 'b') {
- if (reg >= 4)
- tcc_error("cannot use byte register");
- size = 1;
- } else if (modifier == 'h') {
- if (reg >= 4)
- tcc_error("cannot use byte register");
- size = -1;
- } else if (modifier == 'w') {
- size = 2;
- } else if (modifier == 'k') {
- size = 4;
-#ifdef TCC_TARGET_X86_64
- } else if (modifier == 'q') {
- size = 8;
-#endif
- }
-
- switch(size) {
- case -1:
- reg = TOK_ASM_ah + reg;
- break;
- case 1:
- reg = TOK_ASM_al + reg;
- break;
- case 2:
- reg = TOK_ASM_ax + reg;
- break;
- default:
- reg = TOK_ASM_eax + reg;
- break;
-#ifdef TCC_TARGET_X86_64
- case 8:
- reg = TOK_ASM_rax + reg;
- break;
-#endif
- }
- snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
- cstr_cat(add_str, buf, -1);
- }
-}
-
-/* generate prolog and epilog code for asm statement */
-ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands,
- int nb_outputs, int is_output,
- uint8_t *clobber_regs,
- int out_reg)
-{
- uint8_t regs_allocated[NB_ASM_REGS];
- ASMOperand *op;
- int i, reg;
-
- /* Strictly speaking %Xbp and %Xsp should be included in the
- call-preserved registers, but currently it doesn't matter. */
-#ifdef TCC_TARGET_X86_64
-#ifdef TCC_TARGET_PE
- static const uint8_t reg_saved[] = { 3, 6, 7, 12, 13, 14, 15 };
-#else
- static const uint8_t reg_saved[] = { 3, 12, 13, 14, 15 };
-#endif
-#else
- static const uint8_t reg_saved[] = { 3, 6, 7 };
-#endif
-
- /* mark all used registers */
- memcpy(regs_allocated, clobber_regs, sizeof(regs_allocated));
- for(i = 0; i < nb_operands;i++) {
- op = &operands[i];
- if (op->reg >= 0)
- regs_allocated[op->reg] = 1;
- }
- if (!is_output) {
- /* generate reg save code */
- for(i = 0; i < sizeof(reg_saved)/sizeof(reg_saved[0]); i++) {
- reg = reg_saved[i];
- if (regs_allocated[reg]) {
- if (reg >= 8)
- g(0x41), reg-=8;
- g(0x50 + reg);
- }
- }
-
- /* generate load code */
- for(i = 0; i < nb_operands; i++) {
- op = &operands[i];
- if (op->reg >= 0) {
- if ((op->vt->r & VT_VALMASK) == VT_LLOCAL &&
- op->is_memory) {
- /* memory reference case (for both input and
- output cases) */
- SValue sv;
- sv = *op->vt;
- sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
- sv.type.t = VT_PTR;
- load(op->reg, &sv);
- } else if (i >= nb_outputs || op->is_rw) {
- /* load value in register */
- load(op->reg, op->vt);
- if (op->is_llong) {
- SValue sv;
- sv = *op->vt;
- sv.c.i += 4;
- load(TREG_XDX, &sv);
- }
- }
- }
- }
- } else {
- /* generate save code */
- for(i = 0 ; i < nb_outputs; i++) {
- op = &operands[i];
- if (op->reg >= 0) {
- if ((op->vt->r & VT_VALMASK) == VT_LLOCAL) {
- if (!op->is_memory) {
- SValue sv;
- sv = *op->vt;
- sv.r = (sv.r & ~VT_VALMASK) | VT_LOCAL;
- sv.type.t = VT_PTR;
- load(out_reg, &sv);
-
- sv = *op->vt;
- sv.r = (sv.r & ~VT_VALMASK) | out_reg;
- store(op->reg, &sv);
- }
- } else {
- store(op->reg, op->vt);
- if (op->is_llong) {
- SValue sv;
- sv = *op->vt;
- sv.c.i += 4;
- store(TREG_XDX, &sv);
- }
- }
- }
- }
- /* generate reg restore code */
- for(i = sizeof(reg_saved)/sizeof(reg_saved[0]) - 1; i >= 0; i--) {
- reg = reg_saved[i];
- if (regs_allocated[reg]) {
- if (reg >= 8)
- g(0x41), reg-=8;
- g(0x58 + reg);
- }
- }
- }
-}
-
-ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str)
-{
- int reg;
-#ifdef TCC_TARGET_X86_64
- unsigned int type;
-#endif
-
- if (!strcmp(str, "memory") ||
- !strcmp(str, "cc") ||
- !strcmp(str, "flags"))
- return;
- reg = tok_alloc_const(str);
- if (reg >= TOK_ASM_eax && reg <= TOK_ASM_edi) {
- reg -= TOK_ASM_eax;
- } else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
- reg -= TOK_ASM_ax;
-#ifdef TCC_TARGET_X86_64
- } else if (reg >= TOK_ASM_rax && reg <= TOK_ASM_rdi) {
- reg -= TOK_ASM_rax;
- } else if ((reg = asm_parse_numeric_reg(reg, &type)) >= 0) {
- ;
-#endif
- } else {
- tcc_error("invalid clobber register '%s'", str);
- }
- clobber_regs[reg] = 1;
-}
diff --git a/tinycc/i386-asm.h b/tinycc/i386-asm.h
deleted file mode 100644
index 0f99b28..0000000
--- a/tinycc/i386-asm.h
+++ /dev/null
@@ -1,487 +0,0 @@
- DEF_ASM_OP0(clc, 0xf8) /* must be first OP0 */
- DEF_ASM_OP0(cld, 0xfc)
- DEF_ASM_OP0(cli, 0xfa)
- DEF_ASM_OP0(clts, 0x0f06)
- DEF_ASM_OP0(cmc, 0xf5)
- DEF_ASM_OP0(lahf, 0x9f)
- DEF_ASM_OP0(sahf, 0x9e)
- DEF_ASM_OP0(pusha, 0x60)
- DEF_ASM_OP0(popa, 0x61)
- DEF_ASM_OP0(pushfl, 0x9c)
- DEF_ASM_OP0(popfl, 0x9d)
- DEF_ASM_OP0(pushf, 0x9c)
- DEF_ASM_OP0(popf, 0x9d)
- DEF_ASM_OP0(stc, 0xf9)
- DEF_ASM_OP0(std, 0xfd)
- DEF_ASM_OP0(sti, 0xfb)
- DEF_ASM_OP0(aaa, 0x37)
- DEF_ASM_OP0(aas, 0x3f)
- DEF_ASM_OP0(daa, 0x27)
- DEF_ASM_OP0(das, 0x2f)
- DEF_ASM_OP0(aad, 0xd50a)
- DEF_ASM_OP0(aam, 0xd40a)
- DEF_ASM_OP0(cbw, 0x6698)
- DEF_ASM_OP0(cwd, 0x6699)
- DEF_ASM_OP0(cwde, 0x98)
- DEF_ASM_OP0(cdq, 0x99)
- DEF_ASM_OP0(cbtw, 0x6698)
- DEF_ASM_OP0(cwtl, 0x98)
- DEF_ASM_OP0(cwtd, 0x6699)
- DEF_ASM_OP0(cltd, 0x99)
- DEF_ASM_OP0(int3, 0xcc)
- DEF_ASM_OP0(into, 0xce)
- DEF_ASM_OP0(iret, 0xcf)
- DEF_ASM_OP0(rsm, 0x0faa)
- DEF_ASM_OP0(hlt, 0xf4)
- DEF_ASM_OP0(nop, 0x90)
- DEF_ASM_OP0(pause, 0xf390)
- DEF_ASM_OP0(xlat, 0xd7)
-
- /* strings */
-ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWLX))
-ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWLX))
-
-ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
-ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
-
-ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWLX))
-ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWLX))
-
-ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWLX))
-ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWLX))
-
-ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWLX))
-ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWLX))
-
-ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWLX))
-ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWLX))
-
- /* bits */
-
-ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-
-ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(popcntw, 0xf30fb8, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-
-ALT(DEF_ASM_OP2(tzcntw, 0xf30fbc, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(lzcntw, 0xf30fbd, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-
- /* prefixes */
- DEF_ASM_OP0(wait, 0x9b)
- DEF_ASM_OP0(fwait, 0x9b)
- DEF_ASM_OP0(aword, 0x67)
- DEF_ASM_OP0(addr16, 0x67)
- ALT(DEF_ASM_OP0(word, 0x66))
- DEF_ASM_OP0(data16, 0x66)
- DEF_ASM_OP0(lock, 0xf0)
- DEF_ASM_OP0(rep, 0xf3)
- DEF_ASM_OP0(repe, 0xf3)
- DEF_ASM_OP0(repz, 0xf3)
- DEF_ASM_OP0(repne, 0xf2)
- DEF_ASM_OP0(repnz, 0xf2)
-
- DEF_ASM_OP0(invd, 0x0f08)
- DEF_ASM_OP0(wbinvd, 0x0f09)
- DEF_ASM_OP0(cpuid, 0x0fa2)
- DEF_ASM_OP0(wrmsr, 0x0f30)
- DEF_ASM_OP0(rdtsc, 0x0f31)
- DEF_ASM_OP0(rdmsr, 0x0f32)
- DEF_ASM_OP0(rdpmc, 0x0f33)
- DEF_ASM_OP0(ud2, 0x0f0b)
-
- /* NOTE: we took the same order as gas opcode definition order */
-ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWLX, OPT_ADDR, OPT_EAX))
-ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWLX, OPT_EAX, OPT_ADDR))
-ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
-ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLX, OPT_IM, OPT_REG))
-ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WLX, OPT_SEG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_SEG))
-
-ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WLX, OPT_CR, OPT_REG32))
-ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WLX, OPT_DB, OPT_REG32))
-ALT(DEF_ASM_OP2(movw, 0x0f24, 0, OPC_MODRM | OPC_WLX, OPT_TR, OPT_REG32))
-ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WLX, OPT_REG32, OPT_CR))
-ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WLX, OPT_REG32, OPT_DB))
-ALT(DEF_ASM_OP2(movw, 0x0f26, 0, OPC_MODRM | OPC_WLX, OPT_REG32, OPT_TR))
-
-ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(movsbw, 0x660fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG16))
-ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WLX, OPT_REG8 | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
-
-ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WLX, OPT_REGW))
-ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WLX, OPT_IM8S))
-ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WLX, OPT_IM32))
-ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WLX, OPT_SEG))
-
-ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLX, OPT_REGW))
-ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WLX, OPT_SEG))
-
-ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLX, OPT_REGW, OPT_EAX))
-ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLX, OPT_EAX, OPT_REGW))
-ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
-
-ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
-ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
-ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
-ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
-
-ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
-ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
-ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
-ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
-
-ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WLX, OPT_EA, OPT_REG))
-
-ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-
- /* arith */
-ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
-ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
-ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLX, OPT_IM, OPT_EAX))
-ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG))
-
-ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
-ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWLX, OPT_IM, OPT_EAX))
-ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG))
-
-ALT(DEF_ASM_OP1(incw, 0x40, 0, OPC_REG | OPC_WLX, OPT_REGW))
-ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP1(decw, 0x48, 0, OPC_REG | OPC_WLX, OPT_REGW))
-ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG))
-ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_REGW))
-ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WLX, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WLX, OPT_IMW, OPT_REGW))
-
-ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA, OPT_EAX))
-ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA, OPT_EAX))
-
- /* shifts */
-ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_EA | OPT_REG))
-
-ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WLX, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WLX, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_EA | OPT_REGW))
-
-ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
-ALT(DEF_ASM_OP1(call, 0xe8, 0, 0, OPT_DISP))
-ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
-ALT(DEF_ASM_OP1(jmp, 0xeb, 0, 0, OPT_DISP8))
-
-ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
-ALT(DEF_ASM_OP1(lcall, 0xff, 3, OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP2(ljmp, 0xea, 0, 0, OPT_IM16, OPT_IM32))
-ALT(DEF_ASM_OP1(ljmp, 0xff, 5, OPC_MODRM, OPT_EA))
-
-ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
-ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
-ALT(DEF_ASM_OP1(setob, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
- DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
- DEF_ASM_OP0(leave, 0xc9)
- DEF_ASM_OP0(ret, 0xc3)
- DEF_ASM_OP0(retl,0xc3)
-ALT(DEF_ASM_OP1(retl,0xc2, 0, 0, OPT_IM16))
-ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
- DEF_ASM_OP0(lret, 0xcb)
-ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
-
-ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_TEST, OPT_DISP8))
- DEF_ASM_OP1(loopne, 0xe0, 0, 0, OPT_DISP8)
- DEF_ASM_OP1(loopnz, 0xe0, 0, 0, OPT_DISP8)
- DEF_ASM_OP1(loope, 0xe1, 0, 0, OPT_DISP8)
- DEF_ASM_OP1(loopz, 0xe1, 0, 0, OPT_DISP8)
- DEF_ASM_OP1(loop, 0xe2, 0, 0, OPT_DISP8)
- DEF_ASM_OP1(jecxz, 0xe3, 0, 0, OPT_DISP8)
-
- /* float */
- /* specific fcomp handling */
-ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
-
-ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
-ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
-ALT(DEF_ASM_OP2(fadd, 0xdcc0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
-ALT(DEF_ASM_OP2(fmul, 0xdcc8, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
-ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
-ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
-ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
-ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
-ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
-ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-
- DEF_ASM_OP0(fucompp, 0xdae9)
- DEF_ASM_OP0(ftst, 0xd9e4)
- DEF_ASM_OP0(fxam, 0xd9e5)
- DEF_ASM_OP0(fld1, 0xd9e8)
- DEF_ASM_OP0(fldl2t, 0xd9e9)
- DEF_ASM_OP0(fldl2e, 0xd9ea)
- DEF_ASM_OP0(fldpi, 0xd9eb)
- DEF_ASM_OP0(fldlg2, 0xd9ec)
- DEF_ASM_OP0(fldln2, 0xd9ed)
- DEF_ASM_OP0(fldz, 0xd9ee)
-
- DEF_ASM_OP0(f2xm1, 0xd9f0)
- DEF_ASM_OP0(fyl2x, 0xd9f1)
- DEF_ASM_OP0(fptan, 0xd9f2)
- DEF_ASM_OP0(fpatan, 0xd9f3)
- DEF_ASM_OP0(fxtract, 0xd9f4)
- DEF_ASM_OP0(fprem1, 0xd9f5)
- DEF_ASM_OP0(fdecstp, 0xd9f6)
- DEF_ASM_OP0(fincstp, 0xd9f7)
- DEF_ASM_OP0(fprem, 0xd9f8)
- DEF_ASM_OP0(fyl2xp1, 0xd9f9)
- DEF_ASM_OP0(fsqrt, 0xd9fa)
- DEF_ASM_OP0(fsincos, 0xd9fb)
- DEF_ASM_OP0(frndint, 0xd9fc)
- DEF_ASM_OP0(fscale, 0xd9fd)
- DEF_ASM_OP0(fsin, 0xd9fe)
- DEF_ASM_OP0(fcos, 0xd9ff)
- DEF_ASM_OP0(fchs, 0xd9e0)
- DEF_ASM_OP0(fabs, 0xd9e1)
- DEF_ASM_OP0(fninit, 0xdbe3)
- DEF_ASM_OP0(fnclex, 0xdbe2)
- DEF_ASM_OP0(fnop, 0xd9d0)
-
- /* fp load */
- DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
- DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
- DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
-ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
- DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
- DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
-
- /* fp store */
- DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
- DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
- DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
-ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
- DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
-
- DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
- DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
-
- /* exchange */
- DEF_ASM_OP0(fxch, 0xd9c9)
-ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
-
- /* misc FPU */
- DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
- DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
-
- DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
- DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
- DEF_ASM_OP0(fnstsw, 0xdfe0)
-ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
-ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
- DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
-ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
-ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
- DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
- DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
- DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
- DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
- DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
- DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
-
- /* segments */
- DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
-ALT(DEF_ASM_OP2(larw, 0x0f02, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG))
- DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
- DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
-ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_REG))
- DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG)
- DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
- DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
- DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG16| OPT_EA)
- DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
- DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
-
- /* 486 */
- DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
-ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))
-ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))
- DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
-
- DEF_ASM_OP2(boundl, 0x62, 0, OPC_MODRM, OPT_REG32, OPT_EA)
- DEF_ASM_OP2(boundw, 0x6662, 0, OPC_MODRM, OPT_REG16, OPT_EA)
-
- /* pentium */
- DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
-
- /* pentium pro */
-ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
- DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
-
- DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
-
- /* mmx */
- DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
- DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMXSSE )
- DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
-ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG32 ))
-ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
-ALT(DEF_ASM_OP2(movq, 0x660fd6, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_SSE ))
-ALT(DEF_ASM_OP2(movq, 0xf30f7e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ))
-
- DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-
- /* sse */
- DEF_ASM_OP1(ldmxcsr, 0x0fae, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(stmxcsr, 0x0fae, 3, OPC_MODRM, OPT_EA)
- DEF_ASM_OP2(movups, 0x0f10, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
-ALT(DEF_ASM_OP2(movups, 0x0f11, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
- DEF_ASM_OP2(movaps, 0x0f28, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
-ALT(DEF_ASM_OP2(movaps, 0x0f29, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
- DEF_ASM_OP2(movhps, 0x0f16, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
-ALT(DEF_ASM_OP2(movhps, 0x0f17, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
- DEF_ASM_OP2(addps, 0x0f58, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(cvtpi2ps, 0x0f2a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_SSE )
- DEF_ASM_OP2(cvtps2pi, 0x0f2d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX )
- DEF_ASM_OP2(cvttps2pi, 0x0f2c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX )
- DEF_ASM_OP2(divps, 0x0f5e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(maxps, 0x0f5f, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(minps, 0x0f5d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(mulps, 0x0f59, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(pavgb, 0x0fe0, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(pavgw, 0x0fe3, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(pmaxsw, 0x0fee, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pmaxub, 0x0fde, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pminsw, 0x0fea, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pminub, 0x0fda, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(rcpss, 0x0f53, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(rsqrtps, 0x0f52, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(sqrtps, 0x0f51, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(subps, 0x0f5c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
-
-#undef ALT
-#undef DEF_ASM_OP0
-#undef DEF_ASM_OP0L
-#undef DEF_ASM_OP1
-#undef DEF_ASM_OP2
-#undef DEF_ASM_OP3
diff --git a/tinycc/i386-gen.c b/tinycc/i386-gen.c
deleted file mode 100644
index 62bc2ad..0000000
--- a/tinycc/i386-gen.c
+++ /dev/null
@@ -1,1140 +0,0 @@
-/*
- * X86 code generator for TCC
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifdef TARGET_DEFS_ONLY
-
-/* number of available registers */
-#define NB_REGS 5
-#define NB_ASM_REGS 8
-#define CONFIG_TCC_ASM
-
-/* a register can belong to several classes. The classes must be
- sorted from more general to more precise (see gv2() code which does
- assumptions on it). */
-#define RC_INT 0x0001 /* generic integer register */
-#define RC_FLOAT 0x0002 /* generic float register */
-#define RC_EAX 0x0004
-#define RC_ST0 0x0008
-#define RC_ECX 0x0010
-#define RC_EDX 0x0020
-#define RC_EBX 0x0040
-
-#define RC_IRET RC_EAX /* function return: integer register */
-#define RC_IRE2 RC_EDX /* function return: second integer register */
-#define RC_FRET RC_ST0 /* function return: float register */
-
-/* pretty names for the registers */
-enum {
- TREG_EAX = 0,
- TREG_ECX,
- TREG_EDX,
- TREG_EBX,
- TREG_ST0,
- TREG_ESP = 4
-};
-
-/* return registers for function */
-#define REG_IRET TREG_EAX /* single word int return register */
-#define REG_IRE2 TREG_EDX /* second word return register (for long long) */
-#define REG_FRET TREG_ST0 /* float return register */
-
-/* defined if function parameters must be evaluated in reverse order */
-#define INVERT_FUNC_PARAMS
-
-/* defined if structures are passed as pointers. Otherwise structures
- are directly pushed on stack. */
-/* #define FUNC_STRUCT_PARAM_AS_PTR */
-
-/* pointer size, in bytes */
-#define PTR_SIZE 4
-
-/* long double size and alignment, in bytes */
-#define LDOUBLE_SIZE 12
-#define LDOUBLE_ALIGN 4
-/* maximum alignment (for aligned attribute support) */
-#define MAX_ALIGN 8
-
-/* define if return values need to be extended explicitely
- at caller side (for interfacing with non-TCC compilers) */
-#define PROMOTE_RET
-
-/******************************************************/
-#else /* ! TARGET_DEFS_ONLY */
-/******************************************************/
-#define USING_GLOBALS
-#include "tcc.h"
-
-ST_DATA const char * const target_machine_defs =
- "__i386__\0"
- "__i386\0"
- ;
-
-/* define to 1/0 to [not] have EBX as 4th register */
-#define USE_EBX 0
-
-ST_DATA const int reg_classes[NB_REGS] = {
- /* eax */ RC_INT | RC_EAX,
- /* ecx */ RC_INT | RC_ECX,
- /* edx */ RC_INT | RC_EDX,
- /* ebx */ (RC_INT | RC_EBX) * USE_EBX,
- /* st0 */ RC_FLOAT | RC_ST0,
-};
-
-static unsigned long func_sub_sp_offset;
-static int func_ret_sub;
-#ifdef CONFIG_TCC_BCHECK
-static addr_t func_bound_offset;
-static unsigned long func_bound_ind;
-ST_DATA int func_bound_add_epilog;
-static void gen_bounds_prolog(void);
-static void gen_bounds_epilog(void);
-#endif
-
-/* XXX: make it faster ? */
-ST_FUNC void g(int c)
-{
- int ind1;
- if (nocode_wanted)
- return;
- ind1 = ind + 1;
- if (ind1 > cur_text_section->data_allocated)
- section_realloc(cur_text_section, ind1);
- cur_text_section->data[ind] = c;
- ind = ind1;
-}
-
-ST_FUNC void o(unsigned int c)
-{
- while (c) {
- g(c);
- c = c >> 8;
- }
-}
-
-ST_FUNC void gen_le16(int v)
-{
- g(v);
- g(v >> 8);
-}
-
-ST_FUNC void gen_le32(int c)
-{
- g(c);
- g(c >> 8);
- g(c >> 16);
- g(c >> 24);
-}
-
-/* output a symbol and patch all calls to it */
-ST_FUNC void gsym_addr(int t, int a)
-{
- while (t) {
- unsigned char *ptr = cur_text_section->data + t;
- uint32_t n = read32le(ptr); /* next value */
- write32le(ptr, a - t - 4);
- t = n;
- }
-}
-
-/* instruction + 4 bytes data. Return the address of the data */
-static int oad(int c, int s)
-{
- int t;
- if (nocode_wanted)
- return s;
- o(c);
- t = ind;
- gen_le32(s);
- return t;
-}
-
-ST_FUNC void gen_fill_nops(int bytes)
-{
- while (bytes--)
- g(0x90);
-}
-
-/* generate jmp to a label */
-#define gjmp2(instr,lbl) oad(instr,lbl)
-
-/* output constant with relocation if 'r & VT_SYM' is true */
-ST_FUNC void gen_addr32(int r, Sym *sym, int c)
-{
- if (r & VT_SYM)
- greloc(cur_text_section, sym, ind, R_386_32);
- gen_le32(c);
-}
-
-ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
-{
- if (r & VT_SYM)
- greloc(cur_text_section, sym, ind, R_386_PC32);
- gen_le32(c - 4);
-}
-
-/* generate a modrm reference. 'op_reg' contains the additional 3
- opcode bits */
-static void gen_modrm(int op_reg, int r, Sym *sym, int c)
-{
- op_reg = op_reg << 3;
- if ((r & VT_VALMASK) == VT_CONST) {
- /* constant memory reference */
- o(0x05 | op_reg);
- gen_addr32(r, sym, c);
- } else if ((r & VT_VALMASK) == VT_LOCAL) {
- /* currently, we use only ebp as base */
- if (c == (char)c) {
- /* short reference */
- o(0x45 | op_reg);
- g(c);
- } else {
- oad(0x85 | op_reg, c);
- }
- } else {
- g(0x00 | op_reg | (r & VT_VALMASK));
- }
-}
-
-/* load 'r' from value 'sv' */
-ST_FUNC void load(int r, SValue *sv)
-{
- int v, t, ft, fc, fr;
- SValue v1;
-
-#ifdef TCC_TARGET_PE
- SValue v2;
- sv = pe_getimport(sv, &v2);
-#endif
-
- fr = sv->r;
- ft = sv->type.t & ~VT_DEFSIGN;
- fc = sv->c.i;
-
- ft &= ~(VT_VOLATILE | VT_CONSTANT);
-
- v = fr & VT_VALMASK;
- if (fr & VT_LVAL) {
- if (v == VT_LLOCAL) {
- v1.type.t = VT_INT;
- v1.r = VT_LOCAL | VT_LVAL;
- v1.c.i = fc;
- v1.sym = NULL;
- fr = r;
- if (!(reg_classes[fr] & RC_INT))
- fr = get_reg(RC_INT);
- load(fr, &v1);
- }
- if ((ft & VT_BTYPE) == VT_FLOAT) {
- o(0xd9); /* flds */
- r = 0;
- } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
- o(0xdd); /* fldl */
- r = 0;
- } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
- o(0xdb); /* fldt */
- r = 5;
- } else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) {
- o(0xbe0f); /* movsbl */
- } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
- o(0xb60f); /* movzbl */
- } else if ((ft & VT_TYPE) == VT_SHORT) {
- o(0xbf0f); /* movswl */
- } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
- o(0xb70f); /* movzwl */
- } else {
- o(0x8b); /* movl */
- }
- gen_modrm(r, fr, sv->sym, fc);
- } else {
- if (v == VT_CONST) {
- o(0xb8 + r); /* mov $xx, r */
- gen_addr32(fr, sv->sym, fc);
- } else if (v == VT_LOCAL) {
- if (fc) {
- o(0x8d); /* lea xxx(%ebp), r */
- gen_modrm(r, VT_LOCAL, sv->sym, fc);
- } else {
- o(0x89);
- o(0xe8 + r); /* mov %ebp, r */
- }
- } else if (v == VT_CMP) {
- o(0x0f); /* setxx %br */
- o(fc);
- o(0xc0 + r);
- o(0xc0b60f + r * 0x90000); /* movzbl %al, %eax */
- } else if (v == VT_JMP || v == VT_JMPI) {
- t = v & 1;
- oad(0xb8 + r, t); /* mov $1, r */
- o(0x05eb); /* jmp after */
- gsym(fc);
- oad(0xb8 + r, t ^ 1); /* mov $0, r */
- } else if (v != r) {
- o(0x89);
- o(0xc0 + r + v * 8); /* mov v, r */
- }
- }
-}
-
-/* store register 'r' in lvalue 'v' */
-ST_FUNC void store(int r, SValue *v)
-{
- int fr, bt, ft, fc;
-
-#ifdef TCC_TARGET_PE
- SValue v2;
- v = pe_getimport(v, &v2);
-#endif
-
- ft = v->type.t;
- fc = v->c.i;
- fr = v->r & VT_VALMASK;
- ft &= ~(VT_VOLATILE | VT_CONSTANT);
- bt = ft & VT_BTYPE;
- /* XXX: incorrect if float reg to reg */
- if (bt == VT_FLOAT) {
- o(0xd9); /* fsts */
- r = 2;
- } else if (bt == VT_DOUBLE) {
- o(0xdd); /* fstpl */
- r = 2;
- } else if (bt == VT_LDOUBLE) {
- o(0xc0d9); /* fld %st(0) */
- o(0xdb); /* fstpt */
- r = 7;
- } else {
- if (bt == VT_SHORT)
- o(0x66);
- if (bt == VT_BYTE || bt == VT_BOOL)
- o(0x88);
- else
- o(0x89);
- }
- if (fr == VT_CONST ||
- fr == VT_LOCAL ||
- (v->r & VT_LVAL)) {
- gen_modrm(r, v->r, v->sym, fc);
- } else if (fr != r) {
- o(0xc0 + fr + r * 8); /* mov r, fr */
- }
-}
-
-static void gadd_sp(int val)
-{
- if (val == (char)val) {
- o(0xc483);
- g(val);
- } else {
- oad(0xc481, val); /* add $xxx, %esp */
- }
-}
-
-#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_PE
-static void gen_static_call(int v)
-{
- Sym *sym;
-
- sym = external_helper_sym(v);
- oad(0xe8, -4);
- greloc(cur_text_section, sym, ind-4, R_386_PC32);
-}
-#endif
-
-/* 'is_jmp' is '1' if it is a jump */
-static void gcall_or_jmp(int is_jmp)
-{
- int r;
- if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && (vtop->r & VT_SYM)) {
- /* constant and relocation case */
- greloc(cur_text_section, vtop->sym, ind + 1, R_386_PC32);
- oad(0xe8 + is_jmp, vtop->c.i - 4); /* call/jmp im */
- } else {
- /* otherwise, indirect call */
- r = gv(RC_INT);
- o(0xff); /* call/jmp *r */
- o(0xd0 + r + (is_jmp << 4));
- }
-}
-
-static const uint8_t fastcall_regs[3] = { TREG_EAX, TREG_EDX, TREG_ECX };
-static const uint8_t fastcallw_regs[2] = { TREG_ECX, TREG_EDX };
-
-/* Return the number of registers needed to return the struct, or 0 if
- returning via struct pointer. */
-ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
-{
-#if defined(TCC_TARGET_PE) || TARGETOS_FreeBSD || TARGETOS_OpenBSD
- int size, align;
- *ret_align = 1; // Never have to re-align return values for x86
- *regsize = 4;
- size = type_size(vt, &align);
- if (size > 8 || (size & (size - 1)))
- return 0;
- if (size == 8)
- ret->t = VT_LLONG;
- else if (size == 4)
- ret->t = VT_INT;
- else if (size == 2)
- ret->t = VT_SHORT;
- else
- ret->t = VT_BYTE;
- ret->ref = NULL;
- return 1;
-#else
- *ret_align = 1; // Never have to re-align return values for x86
- return 0;
-#endif
-}
-
-/* Generate function call. The function address is pushed first, then
- all the parameters in call order. This functions pops all the
- parameters and the function address. */
-ST_FUNC void gfunc_call(int nb_args)
-{
- int size, align, r, args_size, i, func_call;
- Sym *func_sym;
-
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- gbound_args(nb_args);
-#endif
-
- args_size = 0;
- for(i = 0;i < nb_args; i++) {
- if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
- size = type_size(&vtop->type, &align);
- /* align to stack align size */
- size = (size + 3) & ~3;
- /* allocate the necessary size on stack */
-#ifdef TCC_TARGET_PE
- if (size >= 4096) {
- r = get_reg(RC_EAX);
- oad(0x68, size); // push size
- /* cannot call normal 'alloca' with bound checking */
- gen_static_call(tok_alloc_const("__alloca"));
- gadd_sp(4);
- } else
-#endif
- {
- oad(0xec81, size); /* sub $xxx, %esp */
- /* generate structure store */
- r = get_reg(RC_INT);
- o(0xe089 + (r << 8)); /* mov %esp, r */
- }
- vset(&vtop->type, r | VT_LVAL, 0);
- vswap();
- vstore();
- args_size += size;
- } else if (is_float(vtop->type.t)) {
- gv(RC_FLOAT); /* only one float register */
- if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
- size = 4;
- else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
- size = 8;
- else
- size = 12;
- oad(0xec81, size); /* sub $xxx, %esp */
- if (size == 12)
- o(0x7cdb);
- else
- o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
- g(0x24);
- g(0x00);
- args_size += size;
- } else {
- /* simple type (currently always same size) */
- /* XXX: implicit cast ? */
- r = gv(RC_INT);
- if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
- size = 8;
- o(0x50 + vtop->r2); /* push r */
- } else {
- size = 4;
- }
- o(0x50 + r); /* push r */
- args_size += size;
- }
- vtop--;
- }
- save_regs(0); /* save used temporary registers */
- func_sym = vtop->type.ref;
- func_call = func_sym->f.func_call;
- /* fast call case */
- if ((func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) ||
- func_call == FUNC_FASTCALLW) {
- int fastcall_nb_regs;
- const uint8_t *fastcall_regs_ptr;
- if (func_call == FUNC_FASTCALLW) {
- fastcall_regs_ptr = fastcallw_regs;
- fastcall_nb_regs = 2;
- } else {
- fastcall_regs_ptr = fastcall_regs;
- fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
- }
- for(i = 0;i < fastcall_nb_regs; i++) {
- if (args_size <= 0)
- break;
- o(0x58 + fastcall_regs_ptr[i]); /* pop r */
- /* XXX: incorrect for struct/floats */
- args_size -= 4;
- }
- }
-#if !defined(TCC_TARGET_PE) && !TARGETOS_FreeBSD || TARGETOS_OpenBSD
- else if ((vtop->type.ref->type.t & VT_BTYPE) == VT_STRUCT)
- args_size -= 4;
-#endif
-
- gcall_or_jmp(0);
-
- if (args_size && func_call != FUNC_STDCALL && func_call != FUNC_FASTCALLW)
- gadd_sp(args_size);
- vtop--;
-}
-
-#ifdef TCC_TARGET_PE
-#define FUNC_PROLOG_SIZE (10 + USE_EBX)
-#else
-#define FUNC_PROLOG_SIZE (9 + USE_EBX)
-#endif
-
-/* generate function prolog of type 't' */
-ST_FUNC void gfunc_prolog(Sym *func_sym)
-{
- CType *func_type = &func_sym->type;
- int addr, align, size, func_call, fastcall_nb_regs;
- int param_index, param_addr;
- const uint8_t *fastcall_regs_ptr;
- Sym *sym;
- CType *type;
-
- sym = func_type->ref;
- func_call = sym->f.func_call;
- addr = 8;
- loc = 0;
- func_vc = 0;
-
- if (func_call >= FUNC_FASTCALL1 && func_call <= FUNC_FASTCALL3) {
- fastcall_nb_regs = func_call - FUNC_FASTCALL1 + 1;
- fastcall_regs_ptr = fastcall_regs;
- } else if (func_call == FUNC_FASTCALLW) {
- fastcall_nb_regs = 2;
- fastcall_regs_ptr = fastcallw_regs;
- } else {
- fastcall_nb_regs = 0;
- fastcall_regs_ptr = NULL;
- }
- param_index = 0;
-
- ind += FUNC_PROLOG_SIZE;
- func_sub_sp_offset = ind;
- /* if the function returns a structure, then add an
- implicit pointer parameter */
-#if defined(TCC_TARGET_PE) || TARGETOS_FreeBSD || TARGETOS_OpenBSD
- size = type_size(&func_vt,&align);
- if (((func_vt.t & VT_BTYPE) == VT_STRUCT)
- && (size > 8 || (size & (size - 1)))) {
-#else
- if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
-#endif
- /* XXX: fastcall case ? */
- func_vc = addr;
- addr += 4;
- param_index++;
- }
- /* define parameters */
- while ((sym = sym->next) != NULL) {
- type = &sym->type;
- size = type_size(type, &align);
- size = (size + 3) & ~3;
-#ifdef FUNC_STRUCT_PARAM_AS_PTR
- /* structs are passed as pointer */
- if ((type->t & VT_BTYPE) == VT_STRUCT) {
- size = 4;
- }
-#endif
- if (param_index < fastcall_nb_regs) {
- /* save FASTCALL register */
- loc -= 4;
- o(0x89); /* movl */
- gen_modrm(fastcall_regs_ptr[param_index], VT_LOCAL, NULL, loc);
- param_addr = loc;
- } else {
- param_addr = addr;
- addr += size;
- }
- sym_push(sym->v & ~SYM_FIELD, type,
- VT_LOCAL | VT_LVAL, param_addr);
- param_index++;
- }
- func_ret_sub = 0;
- /* pascal type call or fastcall ? */
- if (func_call == FUNC_STDCALL || func_call == FUNC_FASTCALLW)
- func_ret_sub = addr - 8;
-#if !defined(TCC_TARGET_PE) && !TARGETOS_FreeBSD || TARGETOS_OpenBSD
- else if (func_vc)
- func_ret_sub = 4;
-#endif
-
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- gen_bounds_prolog();
-#endif
-}
-
-/* generate function epilog */
-ST_FUNC void gfunc_epilog(void)
-{
- addr_t v, saved_ind;
-
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- gen_bounds_epilog();
-#endif
-
- /* align local size to word & save local variables */
- v = (-loc + 3) & -4;
-
-#if USE_EBX
- o(0x8b);
- gen_modrm(TREG_EBX, VT_LOCAL, NULL, -(v+4));
-#endif
-
- o(0xc9); /* leave */
- if (func_ret_sub == 0) {
- o(0xc3); /* ret */
- } else {
- o(0xc2); /* ret n */
- g(func_ret_sub);
- g(func_ret_sub >> 8);
- }
- saved_ind = ind;
- ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
-#ifdef TCC_TARGET_PE
- if (v >= 4096) {
- oad(0xb8, v); /* mov stacksize, %eax */
- gen_static_call(TOK___chkstk); /* call __chkstk, (does the stackframe too) */
- } else
-#endif
- {
- o(0xe58955); /* push %ebp, mov %esp, %ebp */
- o(0xec81); /* sub esp, stacksize */
- gen_le32(v);
-#ifdef TCC_TARGET_PE
- o(0x90); /* adjust to FUNC_PROLOG_SIZE */
-#endif
- }
- o(0x53 * USE_EBX); /* push ebx */
- ind = saved_ind;
-}
-
-/* generate a jump to a label */
-ST_FUNC int gjmp(int t)
-{
- return gjmp2(0xe9, t);
-}
-
-/* generate a jump to a fixed address */
-ST_FUNC void gjmp_addr(int a)
-{
- int r;
- r = a - ind - 2;
- if (r == (char)r) {
- g(0xeb);
- g(r);
- } else {
- oad(0xe9, a - ind - 5);
- }
-}
-
-#if 0
-/* generate a jump to a fixed address */
-ST_FUNC void gjmp_cond_addr(int a, int op)
-{
- int r = a - ind - 2;
- if (r == (char)r)
- g(op - 32), g(r);
- else
- g(0x0f), gjmp2(op - 16, r - 4);
-}
-#endif
-
-ST_FUNC int gjmp_append(int n, int t)
-{
- void *p;
- /* insert vtop->c jump list in t */
- if (n) {
- uint32_t n1 = n, n2;
- while ((n2 = read32le(p = cur_text_section->data + n1)))
- n1 = n2;
- write32le(p, t);
- t = n;
- }
- return t;
-}
-
-ST_FUNC int gjmp_cond(int op, int t)
-{
- g(0x0f);
- t = gjmp2(op - 16, t);
- return t;
-}
-
-ST_FUNC void gen_opi(int op)
-{
- int r, fr, opc, c;
-
- switch(op) {
- case '+':
- case TOK_ADDC1: /* add with carry generation */
- opc = 0;
- gen_op8:
- if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
- /* constant case */
- vswap();
- r = gv(RC_INT);
- vswap();
- c = vtop->c.i;
- if (c == (char)c) {
- /* generate inc and dec for smaller code */
- if ((c == 1 || c == -1) && (op == '+' || op == '-')) {
- opc = (c == 1) ^ (op == '+');
- o (0x40 | (opc << 3) | r); // inc,dec
- } else {
- o(0x83);
- o(0xc0 | (opc << 3) | r);
- g(c);
- }
- } else {
- o(0x81);
- oad(0xc0 | (opc << 3) | r, c);
- }
- } else {
- gv2(RC_INT, RC_INT);
- r = vtop[-1].r;
- fr = vtop[0].r;
- o((opc << 3) | 0x01);
- o(0xc0 + r + fr * 8);
- }
- vtop--;
- if (op >= TOK_ULT && op <= TOK_GT)
- vset_VT_CMP(op);
- break;
- case '-':
- case TOK_SUBC1: /* sub with carry generation */
- opc = 5;
- goto gen_op8;
- case TOK_ADDC2: /* add with carry use */
- opc = 2;
- goto gen_op8;
- case TOK_SUBC2: /* sub with carry use */
- opc = 3;
- goto gen_op8;
- case '&':
- opc = 4;
- goto gen_op8;
- case '^':
- opc = 6;
- goto gen_op8;
- case '|':
- opc = 1;
- goto gen_op8;
- case '*':
- gv2(RC_INT, RC_INT);
- r = vtop[-1].r;
- fr = vtop[0].r;
- vtop--;
- o(0xaf0f); /* imul fr, r */
- o(0xc0 + fr + r * 8);
- break;
- case TOK_SHL:
- opc = 4;
- goto gen_shift;
- case TOK_SHR:
- opc = 5;
- goto gen_shift;
- case TOK_SAR:
- opc = 7;
- gen_shift:
- opc = 0xc0 | (opc << 3);
- if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
- /* constant case */
- vswap();
- r = gv(RC_INT);
- vswap();
- c = vtop->c.i & 0x1f;
- o(0xc1); /* shl/shr/sar $xxx, r */
- o(opc | r);
- g(c);
- } else {
- /* we generate the shift in ecx */
- gv2(RC_INT, RC_ECX);
- r = vtop[-1].r;
- o(0xd3); /* shl/shr/sar %cl, r */
- o(opc | r);
- }
- vtop--;
- break;
- case '/':
- case TOK_UDIV:
- case TOK_PDIV:
- case '%':
- case TOK_UMOD:
- case TOK_UMULL:
- /* first operand must be in eax */
- /* XXX: need better constraint for second operand */
- gv2(RC_EAX, RC_ECX);
- r = vtop[-1].r;
- fr = vtop[0].r;
- vtop--;
- save_reg(TREG_EDX);
- /* save EAX too if used otherwise */
- save_reg_upstack(TREG_EAX, 1);
- if (op == TOK_UMULL) {
- o(0xf7); /* mul fr */
- o(0xe0 + fr);
- vtop->r2 = TREG_EDX;
- r = TREG_EAX;
- } else {
- if (op == TOK_UDIV || op == TOK_UMOD) {
- o(0xf7d231); /* xor %edx, %edx, div fr, %eax */
- o(0xf0 + fr);
- } else {
- o(0xf799); /* cltd, idiv fr, %eax */
- o(0xf8 + fr);
- }
- if (op == '%' || op == TOK_UMOD)
- r = TREG_EDX;
- else
- r = TREG_EAX;
- }
- vtop->r = r;
- break;
- default:
- opc = 7;
- goto gen_op8;
- }
-}
-
-/* generate a floating point operation 'v = t1 op t2' instruction. The
- two operands are guaranteed to have the same floating point type */
-/* XXX: need to use ST1 too */
-ST_FUNC void gen_opf(int op)
-{
- int a, ft, fc, swapped, r;
-
- if (op == TOK_NEG) { /* unary minus */
- gv(RC_FLOAT);
- o(0xe0d9); /* fchs */
- return;
- }
-
- /* convert constants to memory references */
- if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
- vswap();
- gv(RC_FLOAT);
- vswap();
- }
- if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
- gv(RC_FLOAT);
-
- /* must put at least one value in the floating point register */
- if ((vtop[-1].r & VT_LVAL) &&
- (vtop[0].r & VT_LVAL)) {
- vswap();
- gv(RC_FLOAT);
- vswap();
- }
- swapped = 0;
- /* swap the stack if needed so that t1 is the register and t2 is
- the memory reference */
- if (vtop[-1].r & VT_LVAL) {
- vswap();
- swapped = 1;
- }
- if (op >= TOK_ULT && op <= TOK_GT) {
- /* load on stack second operand */
- load(TREG_ST0, vtop);
- save_reg(TREG_EAX); /* eax is used by FP comparison code */
- if (op == TOK_GE || op == TOK_GT)
- swapped = !swapped;
- else if (op == TOK_EQ || op == TOK_NE)
- swapped = 0;
- if (swapped)
- o(0xc9d9); /* fxch %st(1) */
- if (op == TOK_EQ || op == TOK_NE)
- o(0xe9da); /* fucompp */
- else
- o(0xd9de); /* fcompp */
- o(0xe0df); /* fnstsw %ax */
- if (op == TOK_EQ) {
- o(0x45e480); /* and $0x45, %ah */
- o(0x40fC80); /* cmp $0x40, %ah */
- } else if (op == TOK_NE) {
- o(0x45e480); /* and $0x45, %ah */
- o(0x40f480); /* xor $0x40, %ah */
- op = TOK_NE;
- } else if (op == TOK_GE || op == TOK_LE) {
- o(0x05c4f6); /* test $0x05, %ah */
- op = TOK_EQ;
- } else {
- o(0x45c4f6); /* test $0x45, %ah */
- op = TOK_EQ;
- }
- vtop--;
- vset_VT_CMP(op);
- } else {
- /* no memory reference possible for long double operations */
- if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
- load(TREG_ST0, vtop);
- swapped = !swapped;
- }
-
- switch(op) {
- default:
- case '+':
- a = 0;
- break;
- case '-':
- a = 4;
- if (swapped)
- a++;
- break;
- case '*':
- a = 1;
- break;
- case '/':
- a = 6;
- if (swapped)
- a++;
- break;
- }
- ft = vtop->type.t;
- fc = vtop->c.i;
- if ((ft & VT_BTYPE) == VT_LDOUBLE) {
- o(0xde); /* fxxxp %st, %st(1) */
- o(0xc1 + (a << 3));
- } else {
- /* if saved lvalue, then we must reload it */
- r = vtop->r;
- if ((r & VT_VALMASK) == VT_LLOCAL) {
- SValue v1;
- r = get_reg(RC_INT);
- v1.type.t = VT_INT;
- v1.r = VT_LOCAL | VT_LVAL;
- v1.c.i = fc;
- v1.sym = NULL;
- load(r, &v1);
- fc = 0;
- }
-
- if ((ft & VT_BTYPE) == VT_DOUBLE)
- o(0xdc);
- else
- o(0xd8);
- gen_modrm(a, r, vtop->sym, fc);
- }
- vtop--;
- }
-}
-
-/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
- and 'long long' cases. */
-ST_FUNC void gen_cvt_itof(int t)
-{
- save_reg(TREG_ST0);
- gv(RC_INT);
- if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
- /* signed long long to float/double/long double (unsigned case
- is handled generically) */
- o(0x50 + vtop->r2); /* push r2 */
- o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
- o(0x242cdf); /* fildll (%esp) */
- o(0x08c483); /* add $8, %esp */
- vtop->r2 = VT_CONST;
- } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
- (VT_INT | VT_UNSIGNED)) {
- /* unsigned int to float/double/long double */
- o(0x6a); /* push $0 */
- g(0x00);
- o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
- o(0x242cdf); /* fildll (%esp) */
- o(0x08c483); /* add $8, %esp */
- } else {
- /* int to float/double/long double */
- o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
- o(0x2404db); /* fildl (%esp) */
- o(0x04c483); /* add $4, %esp */
- }
- vtop->r2 = VT_CONST;
- vtop->r = TREG_ST0;
-}
-
-/* convert fp to int 't' type */
-ST_FUNC void gen_cvt_ftoi(int t)
-{
- int bt = vtop->type.t & VT_BTYPE;
- if (bt == VT_FLOAT)
- vpush_helper_func(TOK___fixsfdi);
- else if (bt == VT_LDOUBLE)
- vpush_helper_func(TOK___fixxfdi);
- else
- vpush_helper_func(TOK___fixdfdi);
- vswap();
- gfunc_call(1);
- vpushi(0);
- vtop->r = REG_IRET;
- if ((t & VT_BTYPE) == VT_LLONG)
- vtop->r2 = REG_IRE2;
-}
-
-/* convert from one floating point type to another */
-ST_FUNC void gen_cvt_ftof(int t)
-{
- /* all we have to do on i386 is to put the float in a register */
- gv(RC_FLOAT);
-}
-
-/* char/short to int conversion */
-ST_FUNC void gen_cvt_csti(int t)
-{
- int r, sz, xl;
- r = gv(RC_INT);
- sz = !(t & VT_UNSIGNED);
- xl = (t & VT_BTYPE) == VT_SHORT;
- o(0xc0b60f /* mov[sz] %a[xl], %eax */
- | (sz << 3 | xl) << 8
- | (r << 3 | r) << 16
- );
-}
-
-/* increment tcov counter */
-ST_FUNC void gen_increment_tcov (SValue *sv)
-{
- o(0x0583); /* addl $1, xxx */
- greloc(cur_text_section, sv->sym, ind, R_386_32);
- gen_le32(0);
- o(1);
- o(0x1583); /* addcl $0, xxx */
- greloc(cur_text_section, sv->sym, ind, R_386_32);
- gen_le32(4);
- g(0);
-}
-
-/* computed goto support */
-ST_FUNC void ggoto(void)
-{
- gcall_or_jmp(1);
- vtop--;
-}
-
-/* bound check support functions */
-#ifdef CONFIG_TCC_BCHECK
-
-static void gen_bounds_prolog(void)
-{
- /* leave some room for bound checking code */
- func_bound_offset = lbounds_section->data_offset;
- func_bound_ind = ind;
- func_bound_add_epilog = 0;
- oad(0xb8, 0); /* lbound section pointer */
- oad(0xb8, 0); /* call to function */
-}
-
-static void gen_bounds_epilog(void)
-{
- addr_t saved_ind;
- addr_t *bounds_ptr;
- Sym *sym_data;
- int offset_modified = func_bound_offset != lbounds_section->data_offset;
-
- if (!offset_modified && !func_bound_add_epilog)
- return;
-
- /* add end of table info */
- bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
- *bounds_ptr = 0;
-
- sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
- func_bound_offset, PTR_SIZE);
-
- /* generate bound local allocation */
- if (offset_modified) {
- saved_ind = ind;
- ind = func_bound_ind;
- greloc(cur_text_section, sym_data, ind + 1, R_386_32);
- ind = ind + 5;
- gen_static_call(TOK___bound_local_new);
- ind = saved_ind;
- }
-
- /* generate bound check local freeing */
- o(0x5250); /* save returned value, if any */
- greloc(cur_text_section, sym_data, ind + 1, R_386_32);
- oad(0xb8, 0); /* mov %eax, xxx */
- gen_static_call(TOK___bound_local_delete);
- o(0x585a); /* restore returned value, if any */
-}
-#endif
-
-/* Save the stack pointer onto the stack */
-ST_FUNC void gen_vla_sp_save(int addr) {
- /* mov %esp,addr(%ebp)*/
- o(0x89);
- gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
-}
-
-/* Restore the SP from a location on the stack */
-ST_FUNC void gen_vla_sp_restore(int addr) {
- o(0x8b);
- gen_modrm(TREG_ESP, VT_LOCAL, NULL, addr);
-}
-
-/* Subtract from the stack pointer, and push the resulting value onto the stack */
-ST_FUNC void gen_vla_alloc(CType *type, int align) {
- int use_call = 0;
-
-#if defined(CONFIG_TCC_BCHECK)
- use_call = tcc_state->do_bounds_check;
-#endif
-#ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */
- use_call = 1;
-#endif
- if (use_call)
- {
- vpush_helper_func(TOK_alloca);
- vswap(); /* Move alloca ref past allocation size */
- gfunc_call(1);
- }
- else {
- int r;
- r = gv(RC_INT); /* allocation size */
- /* sub r,%rsp */
- o(0x2b);
- o(0xe0 | r);
- /* We align to 16 bytes rather than align */
- /* and ~15, %esp */
- o(0xf0e483);
- vpop();
- }
-}
-
-/* end of X86 code generator */
-/*************************************************************/
-#endif
-/*************************************************************/
diff --git a/tinycc/i386-link.c b/tinycc/i386-link.c
deleted file mode 100644
index 2fb1463..0000000
--- a/tinycc/i386-link.c
+++ /dev/null
@@ -1,325 +0,0 @@
-#ifdef TARGET_DEFS_ONLY
-
-#define EM_TCC_TARGET EM_386
-
-/* relocation type for 32 bit data relocation */
-#define R_DATA_32 R_386_32
-#define R_DATA_PTR R_386_32
-#define R_JMP_SLOT R_386_JMP_SLOT
-#define R_GLOB_DAT R_386_GLOB_DAT
-#define R_COPY R_386_COPY
-#define R_RELATIVE R_386_RELATIVE
-
-#define R_NUM R_386_NUM
-
-#define ELF_START_ADDR 0x08048000
-#define ELF_PAGE_SIZE 0x1000
-
-#define PCRELATIVE_DLLPLT 0
-#define RELOCATE_DLLPLT 1
-
-#else /* !TARGET_DEFS_ONLY */
-
-#include "tcc.h"
-
-#ifdef NEED_RELOC_TYPE
-/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
- relocations, returns -1. */
-int code_reloc (int reloc_type)
-{
- switch (reloc_type) {
- case R_386_RELATIVE:
- case R_386_16:
- case R_386_32:
- case R_386_GOTPC:
- case R_386_GOTOFF:
- case R_386_GOT32:
- case R_386_GOT32X:
- case R_386_GLOB_DAT:
- case R_386_COPY:
- case R_386_TLS_GD:
- case R_386_TLS_LDM:
- case R_386_TLS_LDO_32:
- case R_386_TLS_LE:
- return 0;
-
- case R_386_PC16:
- case R_386_PC32:
- case R_386_PLT32:
- case R_386_JMP_SLOT:
- return 1;
- }
- return -1;
-}
-
-/* Returns an enumerator to describe whether and when the relocation needs a
- GOT and/or PLT entry to be created. See tcc.h for a description of the
- different values. */
-int gotplt_entry_type (int reloc_type)
-{
- switch (reloc_type) {
- case R_386_RELATIVE:
- case R_386_16:
- case R_386_GLOB_DAT:
- case R_386_JMP_SLOT:
- case R_386_COPY:
- return NO_GOTPLT_ENTRY;
-
- case R_386_32:
- /* This relocations shouldn't normally need GOT or PLT
- slots if it weren't for simplicity in the code generator.
- See our caller for comments. */
- return AUTO_GOTPLT_ENTRY;
-
- case R_386_PC16:
- case R_386_PC32:
- return AUTO_GOTPLT_ENTRY;
-
- case R_386_GOTPC:
- case R_386_GOTOFF:
- return BUILD_GOT_ONLY;
-
- case R_386_GOT32:
- case R_386_GOT32X:
- case R_386_PLT32:
- case R_386_TLS_GD:
- case R_386_TLS_LDM:
- case R_386_TLS_LDO_32:
- case R_386_TLS_LE:
- return ALWAYS_GOTPLT_ENTRY;
- }
- return -1;
-}
-
-#ifdef NEED_BUILD_GOT
-ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
-{
- Section *plt = s1->plt;
- uint8_t *p;
- int modrm;
- unsigned plt_offset, relofs;
-
- /* on i386 if we build a DLL, we add a %ebx offset */
- if (s1->output_type & TCC_OUTPUT_DYN)
- modrm = 0xa3;
- else
- modrm = 0x25;
-
- /* empty PLT: create PLT0 entry that pushes the library identifier
- (GOT + PTR_SIZE) and jumps to ld.so resolution routine
- (GOT + 2 * PTR_SIZE) */
- if (plt->data_offset == 0) {
- p = section_ptr_add(plt, 16);
- p[0] = 0xff; /* pushl got + PTR_SIZE */
- p[1] = modrm + 0x10;
- write32le(p + 2, PTR_SIZE);
- p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
- p[7] = modrm;
- write32le(p + 8, PTR_SIZE * 2);
- }
- plt_offset = plt->data_offset;
-
- /* The PLT slot refers to the relocation entry it needs via offset.
- The reloc entry is created below, so its offset is the current
- data_offset */
- relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
-
- /* Jump to GOT entry where ld.so initially put the address of ip + 4 */
- p = section_ptr_add(plt, 16);
- p[0] = 0xff; /* jmp *(got + x) */
- p[1] = modrm;
- write32le(p + 2, got_offset);
- p[6] = 0x68; /* push $xxx */
- write32le(p + 7, relofs - sizeof (ElfW_Rel));
- p[11] = 0xe9; /* jmp plt_start */
- write32le(p + 12, -(plt->data_offset));
- return plt_offset;
-}
-
-/* relocate the PLT: compute addresses and offsets in the PLT now that final
- address for PLT and GOT are known (see fill_program_header) */
-ST_FUNC void relocate_plt(TCCState *s1)
-{
- uint8_t *p, *p_end;
-
- if (!s1->plt)
- return;
-
- p = s1->plt->data;
- p_end = p + s1->plt->data_offset;
-
- if (!(s1->output_type & TCC_OUTPUT_DYN) && p < p_end) {
- add32le(p + 2, s1->got->sh_addr);
- add32le(p + 8, s1->got->sh_addr);
- p += 16;
- while (p < p_end) {
- add32le(p + 2, s1->got->sh_addr);
- p += 16;
- }
- }
-
- if (s1->plt->reloc) {
- ElfW_Rel *rel;
- int x = s1->plt->sh_addr + 16 + 6;
- p = s1->got->data;
- for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
- write32le(p + rel->r_offset, x);
- x += 16;
- }
- }
-}
-#endif
-#endif
-
-void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
-{
- int sym_index, esym_index;
-
- sym_index = ELFW(R_SYM)(rel->r_info);
-
- switch (type) {
- case R_386_32:
- if (s1->output_type & TCC_OUTPUT_DYN) {
- esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
- qrel->r_offset = rel->r_offset;
- if (esym_index) {
- qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
- qrel++;
- return;
- } else {
- qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
- qrel++;
- }
- }
- add32le(ptr, val);
- return;
- case R_386_PC32:
- if (s1->output_type == TCC_OUTPUT_DLL) {
- /* DLL relocation */
- esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
- if (esym_index) {
- qrel->r_offset = rel->r_offset;
- qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
- qrel++;
- return;
- }
- }
- add32le(ptr, val - addr);
- return;
- case R_386_PLT32:
- add32le(ptr, val - addr);
- return;
- case R_386_GLOB_DAT:
- case R_386_JMP_SLOT:
- write32le(ptr, val);
- return;
- case R_386_GOTPC:
- add32le(ptr, s1->got->sh_addr - addr);
- return;
- case R_386_GOTOFF:
- add32le(ptr, val - s1->got->sh_addr);
- return;
- case R_386_GOT32:
- case R_386_GOT32X:
- /* we load the got offset */
- add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
- return;
- case R_386_16:
- if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
- output_file:
- tcc_error_noabort("can only produce 16-bit binary files");
- }
- write16le(ptr, read16le(ptr) + val);
- return;
- case R_386_PC16:
- if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
- goto output_file;
- write16le(ptr, read16le(ptr) + val - addr);
- return;
- case R_386_RELATIVE:
-#ifdef TCC_TARGET_PE
- add32le(ptr, val - s1->pe_imagebase);
-#endif
- /* do nothing */
- return;
- case R_386_COPY:
- /* This relocation must copy initialized data from the library
- to the program .bss segment. Currently made like for ARM
- (to remove noise of default case). Is this true?
- */
- return;
- case R_386_TLS_GD:
- {
- static const unsigned char expect[] = {
- /* lea 0(,%ebx,1),%eax */
- 0x8d, 0x04, 0x1d, 0x00, 0x00, 0x00, 0x00,
- /* call __tls_get_addr@PLT */
- 0xe8, 0xfc, 0xff, 0xff, 0xff };
- static const unsigned char replace[] = {
- /* mov %gs:0,%eax */
- 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00,
- /* sub 0,%eax */
- 0x81, 0xe8, 0x00, 0x00, 0x00, 0x00 };
-
- if (memcmp (ptr-3, expect, sizeof(expect)) == 0) {
- ElfW(Sym) *sym;
- Section *sec;
- int32_t x;
-
- memcpy(ptr-3, replace, sizeof(replace));
- rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- sec = s1->sections[sym->st_shndx];
- x = sym->st_value - sec->sh_addr - sec->data_offset;
- add32le(ptr + 5, -x);
- }
- else
- tcc_error_noabort("unexpected R_386_TLS_GD pattern");
- }
- return;
- case R_386_TLS_LDM:
- {
- static const unsigned char expect[] = {
- /* lea 0(%ebx),%eax */
- 0x8d, 0x83, 0x00, 0x00, 0x00, 0x00,
- /* call __tls_get_addr@PLT */
- 0xe8, 0xfc, 0xff, 0xff, 0xff };
- static const unsigned char replace[] = {
- /* mov %gs:0,%eax */
- 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00,
- /* nop */
- 0x90,
- /* lea 0(%esi,%eiz,1),%esi */
- 0x8d, 0x74, 0x26, 0x00 };
-
- if (memcmp (ptr-2, expect, sizeof(expect)) == 0) {
- memcpy(ptr-2, replace, sizeof(replace));
- rel[1].r_info = ELFW(R_INFO)(0, R_386_NONE);
- }
- else
- tcc_error_noabort("unexpected R_386_TLS_LDM pattern");
- }
- return;
- case R_386_TLS_LDO_32:
- case R_386_TLS_LE:
- {
- ElfW(Sym) *sym;
- Section *sec;
- int32_t x;
-
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- sec = s1->sections[sym->st_shndx];
- x = val - sec->sh_addr - sec->data_offset;
- add32le(ptr, x);
- }
- return;
- case R_386_NONE:
- return;
- default:
- fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
- type, (unsigned)addr, ptr, (unsigned)val);
- return;
- }
-}
-
-#endif /* !TARGET_DEFS_ONLY */
diff --git a/tinycc/i386-tok.h b/tinycc/i386-tok.h
deleted file mode 100644
index 2907105..0000000
--- a/tinycc/i386-tok.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/* ------------------------------------------------------------------ */
-/* WARNING: relative order of tokens is important. */
-
-#define DEF_BWL(x) \
- DEF(TOK_ASM_ ## x ## b, #x "b") \
- DEF(TOK_ASM_ ## x ## w, #x "w") \
- DEF(TOK_ASM_ ## x ## l, #x "l") \
- DEF(TOK_ASM_ ## x, #x)
-#define DEF_WL(x) \
- DEF(TOK_ASM_ ## x ## w, #x "w") \
- DEF(TOK_ASM_ ## x ## l, #x "l") \
- DEF(TOK_ASM_ ## x, #x)
-#ifdef TCC_TARGET_X86_64
-# define DEF_BWLQ(x) \
- DEF(TOK_ASM_ ## x ## b, #x "b") \
- DEF(TOK_ASM_ ## x ## w, #x "w") \
- DEF(TOK_ASM_ ## x ## l, #x "l") \
- DEF(TOK_ASM_ ## x ## q, #x "q") \
- DEF(TOK_ASM_ ## x, #x)
-# define DEF_WLQ(x) \
- DEF(TOK_ASM_ ## x ## w, #x "w") \
- DEF(TOK_ASM_ ## x ## l, #x "l") \
- DEF(TOK_ASM_ ## x ## q, #x "q") \
- DEF(TOK_ASM_ ## x, #x)
-# define DEF_BWLX DEF_BWLQ
-# define DEF_WLX DEF_WLQ
-/* number of sizes + 1 */
-# define NBWLX 5
-#else
-# define DEF_BWLX DEF_BWL
-# define DEF_WLX DEF_WL
-/* number of sizes + 1 */
-# define NBWLX 4
-#endif
-
-#define DEF_FP1(x) \
- DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
- DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
- DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
- DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
-
-#define DEF_FP(x) \
- DEF(TOK_ASM_ ## f ## x, "f" #x ) \
- DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
- DEF_FP1(x)
-
-#define DEF_ASMTEST(x,suffix) \
- DEF_ASM(x ## o ## suffix) \
- DEF_ASM(x ## no ## suffix) \
- DEF_ASM(x ## b ## suffix) \
- DEF_ASM(x ## c ## suffix) \
- DEF_ASM(x ## nae ## suffix) \
- DEF_ASM(x ## nb ## suffix) \
- DEF_ASM(x ## nc ## suffix) \
- DEF_ASM(x ## ae ## suffix) \
- DEF_ASM(x ## e ## suffix) \
- DEF_ASM(x ## z ## suffix) \
- DEF_ASM(x ## ne ## suffix) \
- DEF_ASM(x ## nz ## suffix) \
- DEF_ASM(x ## be ## suffix) \
- DEF_ASM(x ## na ## suffix) \
- DEF_ASM(x ## nbe ## suffix) \
- DEF_ASM(x ## a ## suffix) \
- DEF_ASM(x ## s ## suffix) \
- DEF_ASM(x ## ns ## suffix) \
- DEF_ASM(x ## p ## suffix) \
- DEF_ASM(x ## pe ## suffix) \
- DEF_ASM(x ## np ## suffix) \
- DEF_ASM(x ## po ## suffix) \
- DEF_ASM(x ## l ## suffix) \
- DEF_ASM(x ## nge ## suffix) \
- DEF_ASM(x ## nl ## suffix) \
- DEF_ASM(x ## ge ## suffix) \
- DEF_ASM(x ## le ## suffix) \
- DEF_ASM(x ## ng ## suffix) \
- DEF_ASM(x ## nle ## suffix) \
- DEF_ASM(x ## g ## suffix)
-
-/* ------------------------------------------------------------------ */
-/* register */
- DEF_ASM(al)
- DEF_ASM(cl)
- DEF_ASM(dl)
- DEF_ASM(bl)
- DEF_ASM(ah)
- DEF_ASM(ch)
- DEF_ASM(dh)
- DEF_ASM(bh)
- DEF_ASM(ax)
- DEF_ASM(cx)
- DEF_ASM(dx)
- DEF_ASM(bx)
- DEF_ASM(sp)
- DEF_ASM(bp)
- DEF_ASM(si)
- DEF_ASM(di)
- DEF_ASM(eax)
- DEF_ASM(ecx)
- DEF_ASM(edx)
- DEF_ASM(ebx)
- DEF_ASM(esp)
- DEF_ASM(ebp)
- DEF_ASM(esi)
- DEF_ASM(edi)
-#ifdef TCC_TARGET_X86_64
- DEF_ASM(rax)
- DEF_ASM(rcx)
- DEF_ASM(rdx)
- DEF_ASM(rbx)
- DEF_ASM(rsp)
- DEF_ASM(rbp)
- DEF_ASM(rsi)
- DEF_ASM(rdi)
-#endif
- DEF_ASM(mm0)
- DEF_ASM(mm1)
- DEF_ASM(mm2)
- DEF_ASM(mm3)
- DEF_ASM(mm4)
- DEF_ASM(mm5)
- DEF_ASM(mm6)
- DEF_ASM(mm7)
- DEF_ASM(xmm0)
- DEF_ASM(xmm1)
- DEF_ASM(xmm2)
- DEF_ASM(xmm3)
- DEF_ASM(xmm4)
- DEF_ASM(xmm5)
- DEF_ASM(xmm6)
- DEF_ASM(xmm7)
- DEF_ASM(cr0)
- DEF_ASM(cr1)
- DEF_ASM(cr2)
- DEF_ASM(cr3)
- DEF_ASM(cr4)
- DEF_ASM(cr5)
- DEF_ASM(cr6)
- DEF_ASM(cr7)
- DEF_ASM(tr0)
- DEF_ASM(tr1)
- DEF_ASM(tr2)
- DEF_ASM(tr3)
- DEF_ASM(tr4)
- DEF_ASM(tr5)
- DEF_ASM(tr6)
- DEF_ASM(tr7)
- DEF_ASM(db0)
- DEF_ASM(db1)
- DEF_ASM(db2)
- DEF_ASM(db3)
- DEF_ASM(db4)
- DEF_ASM(db5)
- DEF_ASM(db6)
- DEF_ASM(db7)
- DEF_ASM(dr0)
- DEF_ASM(dr1)
- DEF_ASM(dr2)
- DEF_ASM(dr3)
- DEF_ASM(dr4)
- DEF_ASM(dr5)
- DEF_ASM(dr6)
- DEF_ASM(dr7)
- DEF_ASM(es)
- DEF_ASM(cs)
- DEF_ASM(ss)
- DEF_ASM(ds)
- DEF_ASM(fs)
- DEF_ASM(gs)
- DEF_ASM(st)
- DEF_ASM(rip)
-
-#ifdef TCC_TARGET_X86_64
- /* The four low parts of sp/bp/si/di that exist only on
- x86-64 (encoding aliased to ah,ch,dh,dh when not using REX). */
- DEF_ASM(spl)
- DEF_ASM(bpl)
- DEF_ASM(sil)
- DEF_ASM(dil)
-#endif
- /* generic two operands */
- DEF_BWLX(mov)
-
- DEF_BWLX(add)
- DEF_BWLX(or)
- DEF_BWLX(adc)
- DEF_BWLX(sbb)
- DEF_BWLX(and)
- DEF_BWLX(sub)
- DEF_BWLX(xor)
- DEF_BWLX(cmp)
-
- /* unary ops */
- DEF_BWLX(inc)
- DEF_BWLX(dec)
- DEF_BWLX(not)
- DEF_BWLX(neg)
- DEF_BWLX(mul)
- DEF_BWLX(imul)
- DEF_BWLX(div)
- DEF_BWLX(idiv)
-
- DEF_BWLX(xchg)
- DEF_BWLX(test)
-
- /* shifts */
- DEF_BWLX(rol)
- DEF_BWLX(ror)
- DEF_BWLX(rcl)
- DEF_BWLX(rcr)
- DEF_BWLX(shl)
- DEF_BWLX(shr)
- DEF_BWLX(sar)
-
- DEF_WLX(shld)
- DEF_WLX(shrd)
-
- DEF_ASM(pushw)
- DEF_ASM(pushl)
-#ifdef TCC_TARGET_X86_64
- DEF_ASM(pushq)
-#endif
- DEF_ASM(push)
-
- DEF_ASM(popw)
- DEF_ASM(popl)
-#ifdef TCC_TARGET_X86_64
- DEF_ASM(popq)
-#endif
- DEF_ASM(pop)
-
- DEF_BWL(in)
- DEF_BWL(out)
-
- DEF_WLX(movzb)
- DEF_ASM(movzwl)
- DEF_ASM(movsbw)
- DEF_ASM(movsbl)
- DEF_ASM(movswl)
-#ifdef TCC_TARGET_X86_64
- DEF_ASM(movsbq)
- DEF_ASM(movswq)
- DEF_ASM(movzwq)
- DEF_ASM(movslq)
-#endif
-
- DEF_WLX(lea)
-
- DEF_ASM(les)
- DEF_ASM(lds)
- DEF_ASM(lss)
- DEF_ASM(lfs)
- DEF_ASM(lgs)
-
- DEF_ASM(call)
- DEF_ASM(jmp)
- DEF_ASM(lcall)
- DEF_ASM(ljmp)
-
- DEF_ASMTEST(j,)
-
- DEF_ASMTEST(set,)
- DEF_ASMTEST(set,b)
- DEF_ASMTEST(cmov,)
-
- DEF_WLX(bsf)
- DEF_WLX(bsr)
- DEF_WLX(bt)
- DEF_WLX(bts)
- DEF_WLX(btr)
- DEF_WLX(btc)
- DEF_WLX(popcnt)
- DEF_WLX(tzcnt)
- DEF_WLX(lzcnt)
-
- DEF_WLX(lar)
- DEF_WLX(lsl)
-
- /* generic FP ops */
- DEF_FP(add)
- DEF_FP(mul)
-
- DEF_ASM(fcom)
- DEF_ASM(fcom_1) /* non existent op, just to have a regular table */
- DEF_FP1(com)
-
- DEF_FP(comp)
- DEF_FP(sub)
- DEF_FP(subr)
- DEF_FP(div)
- DEF_FP(divr)
-
- DEF_BWLX(xadd)
- DEF_BWLX(cmpxchg)
-
- /* string ops */
- DEF_BWLX(cmps)
- DEF_BWLX(scmp)
- DEF_BWL(ins)
- DEF_BWL(outs)
- DEF_BWLX(lods)
- DEF_BWLX(slod)
- DEF_BWLX(movs)
- DEF_BWLX(smov)
- DEF_BWLX(scas)
- DEF_BWLX(ssca)
- DEF_BWLX(stos)
- DEF_BWLX(ssto)
-
- /* generic asm ops */
-#define ALT(x)
-#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
-#define DEF_ASM_OP0L(name, opcode, group, instr_type)
-#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
-#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
-#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
-#ifdef TCC_TARGET_X86_64
-# include "x86_64-asm.h"
-#else
-# include "i386-asm.h"
-#endif
-
-#define ALT(x)
-#define DEF_ASM_OP0(name, opcode)
-#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
-#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
-#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
-#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
-#ifdef TCC_TARGET_X86_64
-# include "x86_64-asm.h"
-#else
-# include "i386-asm.h"
-#endif
diff --git a/tinycc/il-gen.c b/tinycc/il-gen.c
deleted file mode 100644
index bb670cc..0000000
--- a/tinycc/il-gen.c
+++ /dev/null
@@ -1,657 +0,0 @@
-/*
- * CIL code generator for TCC
- *
- * Copyright (c) 2002 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#error this code has bit-rotted since 2003
-
-/* number of available registers */
-#define NB_REGS 3
-
-/* a register can belong to several classes. The classes must be
- sorted from more general to more precise (see gv2() code which does
- assumptions on it). */
-#define RC_ST 0x0001 /* any stack entry */
-#define RC_ST0 0x0002 /* top of stack */
-#define RC_ST1 0x0004 /* top - 1 */
-
-#define RC_INT RC_ST
-#define RC_FLOAT RC_ST
-#define RC_IRET RC_ST0 /* function return: integer register */
-#define RC_LRET RC_ST0 /* function return: second integer register */
-#define RC_FRET RC_ST0 /* function return: float register */
-
-/* pretty names for the registers */
-enum {
- REG_ST0 = 0,
- REG_ST1,
- REG_ST2,
-};
-
-const int reg_classes[NB_REGS] = {
- /* ST0 */ RC_ST | RC_ST0,
- /* ST1 */ RC_ST | RC_ST1,
- /* ST2 */ RC_ST,
-};
-
-/* return registers for function */
-#define REG_IRET REG_ST0 /* single word int return register */
-#define REG_LRET REG_ST0 /* second word return register (for long long) */
-#define REG_FRET REG_ST0 /* float return register */
-
-/* defined if function parameters must be evaluated in reverse order */
-/* #define INVERT_FUNC_PARAMS */
-
-/* defined if structures are passed as pointers. Otherwise structures
- are directly pushed on stack. */
-/* #define FUNC_STRUCT_PARAM_AS_PTR */
-
-/* pointer size, in bytes */
-#define PTR_SIZE 4
-
-/* long double size and alignment, in bytes */
-#define LDOUBLE_SIZE 8
-#define LDOUBLE_ALIGN 8
-
-/* function call context */
-typedef struct GFuncContext {
- int func_call; /* func call type (FUNC_STDCALL or FUNC_CDECL) */
-} GFuncContext;
-
-/******************************************************/
-/* opcode definitions */
-
-#define IL_OP_PREFIX 0xFE
-
-enum ILOPCodes {
-#define OP(name, str, n) IL_OP_ ## name = n,
-#include "il-opcodes.h"
-#undef OP
-};
-
-char *il_opcodes_str[] = {
-#define OP(name, str, n) [n] = str,
-#include "il-opcodes.h"
-#undef OP
-};
-
-/******************************************************/
-
-/* arguments variable numbers start from there */
-#define ARG_BASE 0x70000000
-
-static FILE *il_outfile;
-
-static void out_byte(int c)
-{
- *(char *)ind++ = c;
-}
-
-static void out_le32(int c)
-{
- out_byte(c);
- out_byte(c >> 8);
- out_byte(c >> 16);
- out_byte(c >> 24);
-}
-
-static void init_outfile(void)
-{
- if (!il_outfile) {
- il_outfile = stdout;
- fprintf(il_outfile,
- ".assembly extern mscorlib\n"
- "{\n"
- ".ver 1:0:2411:0\n"
- "}\n\n");
- }
-}
-
-static void out_op1(int op)
-{
- if (op & 0x100)
- out_byte(IL_OP_PREFIX);
- out_byte(op & 0xff);
-}
-
-/* output an opcode with prefix */
-static void out_op(int op)
-{
- out_op1(op);
- fprintf(il_outfile, " %s\n", il_opcodes_str[op]);
-}
-
-static void out_opb(int op, int c)
-{
- out_op1(op);
- out_byte(c);
- fprintf(il_outfile, " %s %d\n", il_opcodes_str[op], c);
-}
-
-static void out_opi(int op, int c)
-{
- out_op1(op);
- out_le32(c);
- fprintf(il_outfile, " %s 0x%x\n", il_opcodes_str[op], c);
-}
-
-/* XXX: not complete */
-static void il_type_to_str(char *buf, int buf_size,
- int t, const char *varstr)
-{
- int bt;
- Sym *s, *sa;
- char buf1[256];
- const char *tstr;
-
- t = t & VT_TYPE;
- bt = t & VT_BTYPE;
- buf[0] = '\0';
- if (t & VT_UNSIGNED)
- pstrcat(buf, buf_size, "unsigned ");
- switch(bt) {
- case VT_VOID:
- tstr = "void";
- goto add_tstr;
- case VT_BOOL:
- tstr = "bool";
- goto add_tstr;
- case VT_BYTE:
- tstr = "int8";
- goto add_tstr;
- case VT_SHORT:
- tstr = "int16";
- goto add_tstr;
- case VT_ENUM:
- case VT_INT:
- case VT_LONG:
- tstr = "int32";
- goto add_tstr;
- case VT_LLONG:
- tstr = "int64";
- goto add_tstr;
- case VT_FLOAT:
- tstr = "float32";
- goto add_tstr;
- case VT_DOUBLE:
- case VT_LDOUBLE:
- tstr = "float64";
- add_tstr:
- pstrcat(buf, buf_size, tstr);
- break;
- case VT_STRUCT:
- tcc_error("structures not handled yet");
- break;
- case VT_FUNC:
- s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
- il_type_to_str(buf, buf_size, s->t, varstr);
- pstrcat(buf, buf_size, "(");
- sa = s->next;
- while (sa != NULL) {
- il_type_to_str(buf1, sizeof(buf1), sa->t, NULL);
- pstrcat(buf, buf_size, buf1);
- sa = sa->next;
- if (sa)
- pstrcat(buf, buf_size, ", ");
- }
- pstrcat(buf, buf_size, ")");
- goto no_var;
- case VT_PTR:
- s = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
- pstrcpy(buf1, sizeof(buf1), "*");
- if (varstr)
- pstrcat(buf1, sizeof(buf1), varstr);
- il_type_to_str(buf, buf_size, s->t, buf1);
- goto no_var;
- }
- if (varstr) {
- pstrcat(buf, buf_size, " ");
- pstrcat(buf, buf_size, varstr);
- }
- no_var: ;
-}
-
-
-/* patch relocation entry with value 'val' */
-void greloc_patch1(Reloc *p, int val)
-{
-}
-
-/* output a symbol and patch all calls to it */
-void gsym_addr(t, a)
-{
-}
-
-/* output jump and return symbol */
-static int out_opj(int op, int c)
-{
- out_op1(op);
- out_le32(0);
- if (c == 0) {
- c = ind - (int)cur_text_section->data;
- }
- fprintf(il_outfile, " %s L%d\n", il_opcodes_str[op], c);
- return c;
-}
-
-void gsym(int t)
-{
- fprintf(il_outfile, "L%d:\n", t);
-}
-
-/* load 'r' from value 'sv' */
-void load(int r, SValue *sv)
-{
- int v, fc, ft;
-
- v = sv->r & VT_VALMASK;
- fc = sv->c.i;
- ft = sv->t;
-
- if (sv->r & VT_LVAL) {
- if (v == VT_LOCAL) {
- if (fc >= ARG_BASE) {
- fc -= ARG_BASE;
- if (fc >= 0 && fc <= 4) {
- out_op(IL_OP_LDARG_0 + fc);
- } else if (fc <= 0xff) {
- out_opb(IL_OP_LDARG_S, fc);
- } else {
- out_opi(IL_OP_LDARG, fc);
- }
- } else {
- if (fc >= 0 && fc <= 4) {
- out_op(IL_OP_LDLOC_0 + fc);
- } else if (fc <= 0xff) {
- out_opb(IL_OP_LDLOC_S, fc);
- } else {
- out_opi(IL_OP_LDLOC, fc);
- }
- }
- } else if (v == VT_CONST) {
- /* XXX: handle globals */
- out_opi(IL_OP_LDSFLD, 0);
- } else {
- if ((ft & VT_BTYPE) == VT_FLOAT) {
- out_op(IL_OP_LDIND_R4);
- } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
- out_op(IL_OP_LDIND_R8);
- } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
- out_op(IL_OP_LDIND_R8);
- } else if ((ft & VT_TYPE) == VT_BYTE)
- out_op(IL_OP_LDIND_I1);
- else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED))
- out_op(IL_OP_LDIND_U1);
- else if ((ft & VT_TYPE) == VT_SHORT)
- out_op(IL_OP_LDIND_I2);
- else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED))
- out_op(IL_OP_LDIND_U2);
- else
- out_op(IL_OP_LDIND_I4);
- }
- } else {
- if (v == VT_CONST) {
- /* XXX: handle globals */
- if (fc >= -1 && fc <= 8) {
- out_op(IL_OP_LDC_I4_M1 + fc + 1);
- } else {
- out_opi(IL_OP_LDC_I4, fc);
- }
- } else if (v == VT_LOCAL) {
- if (fc >= ARG_BASE) {
- fc -= ARG_BASE;
- if (fc <= 0xff) {
- out_opb(IL_OP_LDARGA_S, fc);
- } else {
- out_opi(IL_OP_LDARGA, fc);
- }
- } else {
- if (fc <= 0xff) {
- out_opb(IL_OP_LDLOCA_S, fc);
- } else {
- out_opi(IL_OP_LDLOCA, fc);
- }
- }
- } else {
- /* XXX: do it */
- }
- }
-}
-
-/* store register 'r' in lvalue 'v' */
-void store(int r, SValue *sv)
-{
- int v, fc, ft;
-
- v = sv->r & VT_VALMASK;
- fc = sv->c.i;
- ft = sv->t;
- if (v == VT_LOCAL) {
- if (fc >= ARG_BASE) {
- fc -= ARG_BASE;
- /* XXX: check IL arg store semantics */
- if (fc <= 0xff) {
- out_opb(IL_OP_STARG_S, fc);
- } else {
- out_opi(IL_OP_STARG, fc);
- }
- } else {
- if (fc >= 0 && fc <= 4) {
- out_op(IL_OP_STLOC_0 + fc);
- } else if (fc <= 0xff) {
- out_opb(IL_OP_STLOC_S, fc);
- } else {
- out_opi(IL_OP_STLOC, fc);
- }
- }
- } else if (v == VT_CONST) {
- /* XXX: handle globals */
- out_opi(IL_OP_STSFLD, 0);
- } else {
- if ((ft & VT_BTYPE) == VT_FLOAT)
- out_op(IL_OP_STIND_R4);
- else if ((ft & VT_BTYPE) == VT_DOUBLE)
- out_op(IL_OP_STIND_R8);
- else if ((ft & VT_BTYPE) == VT_LDOUBLE)
- out_op(IL_OP_STIND_R8);
- else if ((ft & VT_BTYPE) == VT_BYTE)
- out_op(IL_OP_STIND_I1);
- else if ((ft & VT_BTYPE) == VT_SHORT)
- out_op(IL_OP_STIND_I2);
- else
- out_op(IL_OP_STIND_I4);
- }
-}
-
-/* start function call and return function call context */
-void gfunc_start(GFuncContext *c, int func_call)
-{
- c->func_call = func_call;
-}
-
-/* push function parameter which is in (vtop->t, vtop->c). Stack entry
- is then popped. */
-void gfunc_param(GFuncContext *c)
-{
- if ((vtop->t & VT_BTYPE) == VT_STRUCT) {
- tcc_error("structures passed as value not handled yet");
- } else {
- /* simply push on stack */
- gv(RC_ST0);
- }
- vtop--;
-}
-
-/* generate function call with address in (vtop->t, vtop->c) and free function
- context. Stack entry is popped */
-void gfunc_call(GFuncContext *c)
-{
- char buf[1024];
-
- if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
- /* XXX: more info needed from tcc */
- il_type_to_str(buf, sizeof(buf), vtop->t, "xxx");
- fprintf(il_outfile, " call %s\n", buf);
- } else {
- /* indirect call */
- gv(RC_INT);
- il_type_to_str(buf, sizeof(buf), vtop->t, NULL);
- fprintf(il_outfile, " calli %s\n", buf);
- }
- vtop--;
-}
-
-/* generate function prolog of type 't' */
-void gfunc_prolog(int t)
-{
- int addr, u, func_call;
- Sym *sym;
- char buf[1024];
-
- init_outfile();
-
- /* XXX: pass function name to gfunc_prolog */
- il_type_to_str(buf, sizeof(buf), t, funcname);
- fprintf(il_outfile, ".method static %s il managed\n", buf);
- fprintf(il_outfile, "{\n");
- /* XXX: cannot do better now */
- fprintf(il_outfile, " .maxstack %d\n", NB_REGS);
- fprintf(il_outfile, " .locals (int32, int32, int32, int32, int32, int32, int32, int32)\n");
-
- if (!strcmp(funcname, "main"))
- fprintf(il_outfile, " .entrypoint\n");
-
- sym = sym_find((unsigned)t >> VT_STRUCT_SHIFT);
- func_call = sym->r;
-
- addr = ARG_BASE;
- /* if the function returns a structure, then add an
- implicit pointer parameter */
- func_vt = sym->t;
- func_var = (sym->c == FUNC_ELLIPSIS);
- if ((func_vt & VT_BTYPE) == VT_STRUCT) {
- func_vc = addr;
- addr++;
- }
- /* define parameters */
- while ((sym = sym->next) != NULL) {
- u = sym->t;
- sym_push(sym->v & ~SYM_FIELD, u,
- VT_LOCAL | lvalue_type(sym->type.t), addr);
- addr++;
- }
-}
-
-/* generate function epilog */
-void gfunc_epilog(void)
-{
- out_op(IL_OP_RET);
- fprintf(il_outfile, "}\n\n");
-}
-
-/* generate a jump to a label */
-int gjmp(int t)
-{
- return out_opj(IL_OP_BR, t);
-}
-
-/* generate a jump to a fixed address */
-void gjmp_addr(int a)
-{
- /* XXX: handle syms */
- out_opi(IL_OP_BR, a);
-}
-
-/* generate a test. set 'inv' to invert test. Stack entry is popped */
-int gtst(int inv, int t)
-{
- int v, *p, c;
-
- v = vtop->r & VT_VALMASK;
- if (v == VT_CMP) {
- c = vtop->c.i ^ inv;
- switch(c) {
- case TOK_EQ:
- c = IL_OP_BEQ;
- break;
- case TOK_NE:
- c = IL_OP_BNE_UN;
- break;
- case TOK_LT:
- c = IL_OP_BLT;
- break;
- case TOK_LE:
- c = IL_OP_BLE;
- break;
- case TOK_GT:
- c = IL_OP_BGT;
- break;
- case TOK_GE:
- c = IL_OP_BGE;
- break;
- case TOK_ULT:
- c = IL_OP_BLT_UN;
- break;
- case TOK_ULE:
- c = IL_OP_BLE_UN;
- break;
- case TOK_UGT:
- c = IL_OP_BGT_UN;
- break;
- case TOK_UGE:
- c = IL_OP_BGE_UN;
- break;
- }
- t = out_opj(c, t);
- } else if (v == VT_JMP || v == VT_JMPI) {
- /* && or || optimization */
- if ((v & 1) == inv) {
- /* insert vtop->c jump list in t */
- p = &vtop->c.i;
- while (*p != 0)
- p = (int *)*p;
- *p = t;
- t = vtop->c.i;
- } else {
- t = gjmp(t);
- gsym(vtop->c.i);
- }
- }
- vtop--;
- return t;
-}
-
-/* generate an integer binary operation */
-void gen_opi(int op)
-{
- gv2(RC_ST1, RC_ST0);
- switch(op) {
- case '+':
- out_op(IL_OP_ADD);
- goto std_op;
- case '-':
- out_op(IL_OP_SUB);
- goto std_op;
- case '&':
- out_op(IL_OP_AND);
- goto std_op;
- case '^':
- out_op(IL_OP_XOR);
- goto std_op;
- case '|':
- out_op(IL_OP_OR);
- goto std_op;
- case '*':
- out_op(IL_OP_MUL);
- goto std_op;
- case TOK_SHL:
- out_op(IL_OP_SHL);
- goto std_op;
- case TOK_SHR:
- out_op(IL_OP_SHR_UN);
- goto std_op;
- case TOK_SAR:
- out_op(IL_OP_SHR);
- goto std_op;
- case '/':
- case TOK_PDIV:
- out_op(IL_OP_DIV);
- goto std_op;
- case TOK_UDIV:
- out_op(IL_OP_DIV_UN);
- goto std_op;
- case '%':
- out_op(IL_OP_REM);
- goto std_op;
- case TOK_UMOD:
- out_op(IL_OP_REM_UN);
- std_op:
- vtop--;
- vtop[0].r = REG_ST0;
- break;
- case TOK_EQ:
- case TOK_NE:
- case TOK_LT:
- case TOK_LE:
- case TOK_GT:
- case TOK_GE:
- case TOK_ULT:
- case TOK_ULE:
- case TOK_UGT:
- case TOK_UGE:
- vtop--;
- vtop[0].r = VT_CMP;
- vtop[0].c.i = op;
- break;
- }
-}
-
-/* generate a floating point operation 'v = t1 op t2' instruction. The
- two operands are guaranteed to have the same floating point type */
-void gen_opf(int op)
-{
- /* same as integer */
- gen_opi(op);
-}
-
-/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
- and 'long long' cases. */
-void gen_cvt_itof(int t)
-{
- gv(RC_ST0);
- if (t == VT_FLOAT)
- out_op(IL_OP_CONV_R4);
- else
- out_op(IL_OP_CONV_R8);
-}
-
-/* convert fp to int 't' type */
-/* XXX: handle long long case */
-void gen_cvt_ftoi(int t)
-{
- gv(RC_ST0);
- switch(t) {
- case VT_INT | VT_UNSIGNED:
- out_op(IL_OP_CONV_U4);
- break;
- case VT_LLONG:
- out_op(IL_OP_CONV_I8);
- break;
- case VT_LLONG | VT_UNSIGNED:
- out_op(IL_OP_CONV_U8);
- break;
- default:
- out_op(IL_OP_CONV_I4);
- break;
- }
-}
-
-/* convert from one floating point type to another */
-void gen_cvt_ftof(int t)
-{
- gv(RC_ST0);
- if (t == VT_FLOAT) {
- out_op(IL_OP_CONV_R4);
- } else {
- out_op(IL_OP_CONV_R8);
- }
-}
-
-/* end of CIL code generator */
-/*************************************************************/
-
diff --git a/tinycc/il-opcodes.h b/tinycc/il-opcodes.h
deleted file mode 100644
index d53ffb2..0000000
--- a/tinycc/il-opcodes.h
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- * CIL opcode definition
- *
- * Copyright (c) 2002 Fabrice Bellard
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-OP(NOP, "nop", 0x00)
-OP(BREAK, "break", 0x01)
-OP(LDARG_0, "ldarg.0", 0x02)
-OP(LDARG_1, "ldarg.1", 0x03)
-OP(LDARG_2, "ldarg.2", 0x04)
-OP(LDARG_3, "ldarg.3", 0x05)
-OP(LDLOC_0, "ldloc.0", 0x06)
-OP(LDLOC_1, "ldloc.1", 0x07)
-OP(LDLOC_2, "ldloc.2", 0x08)
-OP(LDLOC_3, "ldloc.3", 0x09)
-OP(STLOC_0, "stloc.0", 0x0a)
-OP(STLOC_1, "stloc.1", 0x0b)
-OP(STLOC_2, "stloc.2", 0x0c)
-OP(STLOC_3, "stloc.3", 0x0d)
-OP(LDARG_S, "ldarg.s", 0x0e)
-OP(LDARGA_S, "ldarga.s", 0x0f)
-OP(STARG_S, "starg.s", 0x10)
-OP(LDLOC_S, "ldloc.s", 0x11)
-OP(LDLOCA_S, "ldloca.s", 0x12)
-OP(STLOC_S, "stloc.s", 0x13)
-OP(LDNULL, "ldnull", 0x14)
-OP(LDC_I4_M1, "ldc.i4.m1", 0x15)
-OP(LDC_I4_0, "ldc.i4.0", 0x16)
-OP(LDC_I4_1, "ldc.i4.1", 0x17)
-OP(LDC_I4_2, "ldc.i4.2", 0x18)
-OP(LDC_I4_3, "ldc.i4.3", 0x19)
-OP(LDC_I4_4, "ldc.i4.4", 0x1a)
-OP(LDC_I4_5, "ldc.i4.5", 0x1b)
-OP(LDC_I4_6, "ldc.i4.6", 0x1c)
-OP(LDC_I4_7, "ldc.i4.7", 0x1d)
-OP(LDC_I4_8, "ldc.i4.8", 0x1e)
-OP(LDC_I4_S, "ldc.i4.s", 0x1f)
-OP(LDC_I4, "ldc.i4", 0x20)
-OP(LDC_I8, "ldc.i8", 0x21)
-OP(LDC_R4, "ldc.r4", 0x22)
-OP(LDC_R8, "ldc.r8", 0x23)
-OP(LDPTR, "ldptr", 0x24)
-OP(DUP, "dup", 0x25)
-OP(POP, "pop", 0x26)
-OP(JMP, "jmp", 0x27)
-OP(CALL, "call", 0x28)
-OP(CALLI, "calli", 0x29)
-OP(RET, "ret", 0x2a)
-OP(BR_S, "br.s", 0x2b)
-OP(BRFALSE_S, "brfalse.s", 0x2c)
-OP(BRTRUE_S, "brtrue.s", 0x2d)
-OP(BEQ_S, "beq.s", 0x2e)
-OP(BGE_S, "bge.s", 0x2f)
-OP(BGT_S, "bgt.s", 0x30)
-OP(BLE_S, "ble.s", 0x31)
-OP(BLT_S, "blt.s", 0x32)
-OP(BNE_UN_S, "bne.un.s", 0x33)
-OP(BGE_UN_S, "bge.un.s", 0x34)
-OP(BGT_UN_S, "bgt.un.s", 0x35)
-OP(BLE_UN_S, "ble.un.s", 0x36)
-OP(BLT_UN_S, "blt.un.s", 0x37)
-OP(BR, "br", 0x38)
-OP(BRFALSE, "brfalse", 0x39)
-OP(BRTRUE, "brtrue", 0x3a)
-OP(BEQ, "beq", 0x3b)
-OP(BGE, "bge", 0x3c)
-OP(BGT, "bgt", 0x3d)
-OP(BLE, "ble", 0x3e)
-OP(BLT, "blt", 0x3f)
-OP(BNE_UN, "bne.un", 0x40)
-OP(BGE_UN, "bge.un", 0x41)
-OP(BGT_UN, "bgt.un", 0x42)
-OP(BLE_UN, "ble.un", 0x43)
-OP(BLT_UN, "blt.un", 0x44)
-OP(SWITCH, "switch", 0x45)
-OP(LDIND_I1, "ldind.i1", 0x46)
-OP(LDIND_U1, "ldind.u1", 0x47)
-OP(LDIND_I2, "ldind.i2", 0x48)
-OP(LDIND_U2, "ldind.u2", 0x49)
-OP(LDIND_I4, "ldind.i4", 0x4a)
-OP(LDIND_U4, "ldind.u4", 0x4b)
-OP(LDIND_I8, "ldind.i8", 0x4c)
-OP(LDIND_I, "ldind.i", 0x4d)
-OP(LDIND_R4, "ldind.r4", 0x4e)
-OP(LDIND_R8, "ldind.r8", 0x4f)
-OP(LDIND_REF, "ldind.ref", 0x50)
-OP(STIND_REF, "stind.ref", 0x51)
-OP(STIND_I1, "stind.i1", 0x52)
-OP(STIND_I2, "stind.i2", 0x53)
-OP(STIND_I4, "stind.i4", 0x54)
-OP(STIND_I8, "stind.i8", 0x55)
-OP(STIND_R4, "stind.r4", 0x56)
-OP(STIND_R8, "stind.r8", 0x57)
-OP(ADD, "add", 0x58)
-OP(SUB, "sub", 0x59)
-OP(MUL, "mul", 0x5a)
-OP(DIV, "div", 0x5b)
-OP(DIV_UN, "div.un", 0x5c)
-OP(REM, "rem", 0x5d)
-OP(REM_UN, "rem.un", 0x5e)
-OP(AND, "and", 0x5f)
-OP(OR, "or", 0x60)
-OP(XOR, "xor", 0x61)
-OP(SHL, "shl", 0x62)
-OP(SHR, "shr", 0x63)
-OP(SHR_UN, "shr.un", 0x64)
-OP(NEG, "neg", 0x65)
-OP(NOT, "not", 0x66)
-OP(CONV_I1, "conv.i1", 0x67)
-OP(CONV_I2, "conv.i2", 0x68)
-OP(CONV_I4, "conv.i4", 0x69)
-OP(CONV_I8, "conv.i8", 0x6a)
-OP(CONV_R4, "conv.r4", 0x6b)
-OP(CONV_R8, "conv.r8", 0x6c)
-OP(CONV_U4, "conv.u4", 0x6d)
-OP(CONV_U8, "conv.u8", 0x6e)
-OP(CALLVIRT, "callvirt", 0x6f)
-OP(CPOBJ, "cpobj", 0x70)
-OP(LDOBJ, "ldobj", 0x71)
-OP(LDSTR, "ldstr", 0x72)
-OP(NEWOBJ, "newobj", 0x73)
-OP(CASTCLASS, "castclass", 0x74)
-OP(ISINST, "isinst", 0x75)
-OP(CONV_R_UN, "conv.r.un", 0x76)
-OP(ANN_DATA_S, "ann.data.s", 0x77)
-OP(UNBOX, "unbox", 0x79)
-OP(THROW, "throw", 0x7a)
-OP(LDFLD, "ldfld", 0x7b)
-OP(LDFLDA, "ldflda", 0x7c)
-OP(STFLD, "stfld", 0x7d)
-OP(LDSFLD, "ldsfld", 0x7e)
-OP(LDSFLDA, "ldsflda", 0x7f)
-OP(STSFLD, "stsfld", 0x80)
-OP(STOBJ, "stobj", 0x81)
-OP(CONV_OVF_I1_UN, "conv.ovf.i1.un", 0x82)
-OP(CONV_OVF_I2_UN, "conv.ovf.i2.un", 0x83)
-OP(CONV_OVF_I4_UN, "conv.ovf.i4.un", 0x84)
-OP(CONV_OVF_I8_UN, "conv.ovf.i8.un", 0x85)
-OP(CONV_OVF_U1_UN, "conv.ovf.u1.un", 0x86)
-OP(CONV_OVF_U2_UN, "conv.ovf.u2.un", 0x87)
-OP(CONV_OVF_U4_UN, "conv.ovf.u4.un", 0x88)
-OP(CONV_OVF_U8_UN, "conv.ovf.u8.un", 0x89)
-OP(CONV_OVF_I_UN, "conv.ovf.i.un", 0x8a)
-OP(CONV_OVF_U_UN, "conv.ovf.u.un", 0x8b)
-OP(BOX, "box", 0x8c)
-OP(NEWARR, "newarr", 0x8d)
-OP(LDLEN, "ldlen", 0x8e)
-OP(LDELEMA, "ldelema", 0x8f)
-OP(LDELEM_I1, "ldelem.i1", 0x90)
-OP(LDELEM_U1, "ldelem.u1", 0x91)
-OP(LDELEM_I2, "ldelem.i2", 0x92)
-OP(LDELEM_U2, "ldelem.u2", 0x93)
-OP(LDELEM_I4, "ldelem.i4", 0x94)
-OP(LDELEM_U4, "ldelem.u4", 0x95)
-OP(LDELEM_I8, "ldelem.i8", 0x96)
-OP(LDELEM_I, "ldelem.i", 0x97)
-OP(LDELEM_R4, "ldelem.r4", 0x98)
-OP(LDELEM_R8, "ldelem.r8", 0x99)
-OP(LDELEM_REF, "ldelem.ref", 0x9a)
-OP(STELEM_I, "stelem.i", 0x9b)
-OP(STELEM_I1, "stelem.i1", 0x9c)
-OP(STELEM_I2, "stelem.i2", 0x9d)
-OP(STELEM_I4, "stelem.i4", 0x9e)
-OP(STELEM_I8, "stelem.i8", 0x9f)
-OP(STELEM_R4, "stelem.r4", 0xa0)
-OP(STELEM_R8, "stelem.r8", 0xa1)
-OP(STELEM_REF, "stelem.ref", 0xa2)
-OP(CONV_OVF_I1, "conv.ovf.i1", 0xb3)
-OP(CONV_OVF_U1, "conv.ovf.u1", 0xb4)
-OP(CONV_OVF_I2, "conv.ovf.i2", 0xb5)
-OP(CONV_OVF_U2, "conv.ovf.u2", 0xb6)
-OP(CONV_OVF_I4, "conv.ovf.i4", 0xb7)
-OP(CONV_OVF_U4, "conv.ovf.u4", 0xb8)
-OP(CONV_OVF_I8, "conv.ovf.i8", 0xb9)
-OP(CONV_OVF_U8, "conv.ovf.u8", 0xba)
-OP(REFANYVAL, "refanyval", 0xc2)
-OP(CKFINITE, "ckfinite", 0xc3)
-OP(MKREFANY, "mkrefany", 0xc6)
-OP(ANN_CALL, "ann.call", 0xc7)
-OP(ANN_CATCH, "ann.catch", 0xc8)
-OP(ANN_DEAD, "ann.dead", 0xc9)
-OP(ANN_HOISTED, "ann.hoisted", 0xca)
-OP(ANN_HOISTED_CALL, "ann.hoisted.call", 0xcb)
-OP(ANN_LAB, "ann.lab", 0xcc)
-OP(ANN_DEF, "ann.def", 0xcd)
-OP(ANN_REF_S, "ann.ref.s", 0xce)
-OP(ANN_PHI, "ann.phi", 0xcf)
-OP(LDTOKEN, "ldtoken", 0xd0)
-OP(CONV_U2, "conv.u2", 0xd1)
-OP(CONV_U1, "conv.u1", 0xd2)
-OP(CONV_I, "conv.i", 0xd3)
-OP(CONV_OVF_I, "conv.ovf.i", 0xd4)
-OP(CONV_OVF_U, "conv.ovf.u", 0xd5)
-OP(ADD_OVF, "add.ovf", 0xd6)
-OP(ADD_OVF_UN, "add.ovf.un", 0xd7)
-OP(MUL_OVF, "mul.ovf", 0xd8)
-OP(MUL_OVF_UN, "mul.ovf.un", 0xd9)
-OP(SUB_OVF, "sub.ovf", 0xda)
-OP(SUB_OVF_UN, "sub.ovf.un", 0xdb)
-OP(ENDFINALLY, "endfinally", 0xdc)
-OP(LEAVE, "leave", 0xdd)
-OP(LEAVE_S, "leave.s", 0xde)
-OP(STIND_I, "stind.i", 0xdf)
-OP(CONV_U, "conv.u", 0xe0)
-
-/* prefix instructions. we use an opcode >= 256 to ease coding */
-
-OP(ARGLIST, "arglist", 0x100)
-OP(CEQ, "ceq", 0x101)
-OP(CGT, "cgt", 0x102)
-OP(CGT_UN, "cgt.un", 0x103)
-OP(CLT, "clt", 0x104)
-OP(CLT_UN, "clt.un", 0x105)
-OP(LDFTN, "ldftn", 0x106)
-OP(LDVIRTFTN, "ldvirtftn", 0x107)
-OP(JMPI, "jmpi", 0x108)
-OP(LDARG, "ldarg", 0x109)
-OP(LDARGA, "ldarga", 0x10a)
-OP(STARG, "starg", 0x10b)
-OP(LDLOC, "ldloc", 0x10c)
-OP(LDLOCA, "ldloca", 0x10d)
-OP(STLOC, "stloc", 0x10e)
-OP(LOCALLOC, "localloc", 0x10f)
-OP(ENDFILTER, "endfilter", 0x111)
-OP(UNALIGNED, "unaligned", 0x112)
-OP(VOLATILE, "volatile", 0x113)
-OP(TAIL, "tail", 0x114)
-OP(INITOBJ, "initobj", 0x115)
-OP(ANN_LIVE, "ann.live", 0x116)
-OP(CPBLK, "cpblk", 0x117)
-OP(INITBLK, "initblk", 0x118)
-OP(ANN_REF, "ann.ref", 0x119)
-OP(RETHROW, "rethrow", 0x11a)
-OP(SIZEOF, "sizeof", 0x11c)
-OP(REFANYTYPE, "refanytype", 0x11d)
-OP(ANN_DATA, "ann.data", 0x122)
-OP(ANN_ARG, "ann.arg", 0x123)
diff --git a/tinycc/include/float.h b/tinycc/include/float.h
deleted file mode 100644
index 24b7410..0000000
--- a/tinycc/include/float.h
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef _FLOAT_H_
-#define _FLOAT_H_
-
-#define FLT_RADIX 2
-
-/* IEEE float */
-#define FLT_MANT_DIG 24
-#define FLT_DIG 6
-#define FLT_ROUNDS 1
-#define FLT_EPSILON 1.19209290e-07F
-#define FLT_MIN_EXP (-125)
-#define FLT_MIN 1.17549435e-38F
-#define FLT_MIN_10_EXP (-37)
-#define FLT_MAX_EXP 128
-#define FLT_MAX 3.40282347e+38F
-#define FLT_MAX_10_EXP 38
-
-/* IEEE double */
-#define DBL_MANT_DIG 53
-#define DBL_DIG 15
-#define DBL_EPSILON 2.2204460492503131e-16
-#define DBL_MIN_EXP (-1021)
-#define DBL_MIN 2.2250738585072014e-308
-#define DBL_MIN_10_EXP (-307)
-#define DBL_MAX_EXP 1024
-#define DBL_MAX 1.7976931348623157e+308
-#define DBL_MAX_10_EXP 308
-
-/* horrible intel long double */
-#if defined __i386__ || defined __x86_64__
-
-#define LDBL_MANT_DIG 64
-#define LDBL_DIG 18
-#define LDBL_EPSILON 1.08420217248550443401e-19L
-#define LDBL_MIN_EXP (-16381)
-#define LDBL_MIN 3.36210314311209350626e-4932L
-#define LDBL_MIN_10_EXP (-4931)
-#define LDBL_MAX_EXP 16384
-#define LDBL_MAX 1.18973149535723176502e+4932L
-#define LDBL_MAX_10_EXP 4932
-#define DECIMAL_DIG 21
-
-#elif defined __aarch64__ || defined __riscv
-/*
- * Use values from:
- * gcc -dM -E -xc /dev/null | grep LDBL | sed -e "s/__//g"
- */
-#define LDBL_MANT_DIG 113
-#define LDBL_DIG 33
-#define LDBL_EPSILON 1.92592994438723585305597794258492732e-34L
-#define LDBL_MIN_EXP (-16381)
-#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
-#define LDBL_MIN_10_EXP (-4931)
-#define LDBL_MAX_EXP 16384
-#define LDBL_MAX 1.18973149535723176508575932662800702e+4932L
-#define LDBL_MAX_EXP 16384
-#define DECIMAL_DIG 36
-
-#else
-
-/* same as IEEE double */
-#define LDBL_MANT_DIG 53
-#define LDBL_DIG 15
-#define LDBL_EPSILON 2.2204460492503131e-16L
-#define LDBL_MIN_EXP (-1021)
-#define LDBL_MIN 2.2250738585072014e-308L
-#define LDBL_MIN_10_EXP (-307)
-#define LDBL_MAX_EXP 1024
-#define LDBL_MAX 1.7976931348623157e+308L
-#define LDBL_MAX_10_EXP 308
-#define DECIMAL_DIG 17
-
-#endif
-
-#endif /* _FLOAT_H_ */
diff --git a/tinycc/include/stdalign.h b/tinycc/include/stdalign.h
deleted file mode 100644
index ae46c34..0000000
--- a/tinycc/include/stdalign.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef _STDALIGN_H
-#define _STDALIGN_H
-
-#if __STDC_VERSION__ < 201112L && (defined(__GNUC__) || defined(__TINYC__))
-# define _Alignas(t) __attribute__((__aligned__(t)))
-# define _Alignof(t) __alignof__(t)
-#endif
-
-#define alignas _Alignas
-#define alignof _Alignof
-
-#define __alignas_is_defined 1
-#define __alignof_is_defined 1
-
-#endif /* _STDALIGN_H */
-
diff --git a/tinycc/include/stdarg.h b/tinycc/include/stdarg.h
deleted file mode 100644
index aa784da..0000000
--- a/tinycc/include/stdarg.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _STDARG_H
-#define _STDARG_H
-
-typedef __builtin_va_list va_list;
-#define va_start __builtin_va_start
-#define va_arg __builtin_va_arg
-#define va_copy __builtin_va_copy
-#define va_end __builtin_va_end
-
-/* fix a buggy dependency on GCC in libio.h */
-typedef va_list __gnuc_va_list;
-#define _VA_LIST_DEFINED
-
-#endif /* _STDARG_H */
diff --git a/tinycc/include/stdatomic.h b/tinycc/include/stdatomic.h
deleted file mode 100644
index a8372ee..0000000
--- a/tinycc/include/stdatomic.h
+++ /dev/null
@@ -1,172 +0,0 @@
-/* This file is derived from clang's stdatomic.h */
-
-/*===---- stdatomic.h - Standard header for atomic types and operations -----===
- *
- * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- * See https://llvm.org/LICENSE.txt for license information.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- *
- *===-----------------------------------------------------------------------===
- */
-
-#ifndef _STDATOMIC_H
-#define _STDATOMIC_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#define __ATOMIC_RELAXED 0
-#define __ATOMIC_CONSUME 1
-#define __ATOMIC_ACQUIRE 2
-#define __ATOMIC_RELEASE 3
-#define __ATOMIC_ACQ_REL 4
-#define __ATOMIC_SEQ_CST 5
-
-/* Memory ordering */
-typedef enum {
- memory_order_relaxed = __ATOMIC_RELAXED,
- memory_order_consume = __ATOMIC_CONSUME,
- memory_order_acquire = __ATOMIC_ACQUIRE,
- memory_order_release = __ATOMIC_RELEASE,
- memory_order_acq_rel = __ATOMIC_ACQ_REL,
- memory_order_seq_cst = __ATOMIC_SEQ_CST,
-} memory_order;
-
-/* Atomic typedefs */
-typedef _Atomic(_Bool) atomic_bool;
-typedef _Atomic(char) atomic_char;
-typedef _Atomic(signed char) atomic_schar;
-typedef _Atomic(unsigned char) atomic_uchar;
-typedef _Atomic(short) atomic_short;
-typedef _Atomic(unsigned short) atomic_ushort;
-typedef _Atomic(int) atomic_int;
-typedef _Atomic(unsigned int) atomic_uint;
-typedef _Atomic(long) atomic_long;
-typedef _Atomic(unsigned long) atomic_ulong;
-typedef _Atomic(long long) atomic_llong;
-typedef _Atomic(unsigned long long) atomic_ullong;
-typedef _Atomic(uint_least16_t) atomic_char16_t;
-typedef _Atomic(uint_least32_t) atomic_char32_t;
-typedef _Atomic(wchar_t) atomic_wchar_t;
-typedef _Atomic(int_least8_t) atomic_int_least8_t;
-typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
-typedef _Atomic(int_least16_t) atomic_int_least16_t;
-typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
-typedef _Atomic(int_least32_t) atomic_int_least32_t;
-typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
-typedef _Atomic(int_least64_t) atomic_int_least64_t;
-typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
-typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
-typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
-typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
-typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
-typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
-typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
-typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
-typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
-typedef _Atomic(intptr_t) atomic_intptr_t;
-typedef _Atomic(uintptr_t) atomic_uintptr_t;
-typedef _Atomic(size_t) atomic_size_t;
-typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
-typedef _Atomic(intmax_t) atomic_intmax_t;
-typedef _Atomic(uintmax_t) atomic_uintmax_t;
-
-/* Atomic flag */
-typedef struct {
- atomic_bool value;
-} atomic_flag;
-
-#define ATOMIC_FLAG_INIT {0}
-
-#define atomic_flag_test_and_set_explicit(object, order) \
- __atomic_test_and_set((void *)(&((object)->value)), order)
-#define atomic_flag_test_and_set(object) \
- atomic_flag_test_and_set_explicit(object, __ATOMIC_SEQ_CST)
-
-#define atomic_flag_clear_explicit(object, order) \
- __atomic_clear((bool *)(&((object)->value)), order)
-#define atomic_flag_clear(object) \
- atomic_flag_clear_explicit(object, __ATOMIC_SEQ_CST)
-
-/* Generic routines */
-#define atomic_init(object, desired) \
- atomic_store_explicit(object, desired, __ATOMIC_RELAXED)
-
-#define atomic_store_explicit(object, desired, order) \
- ({ __typeof__ (object) ptr = (object); \
- __typeof__ (*ptr) tmp = (desired); \
- __atomic_store (ptr, &tmp, (order)); \
- })
-#define atomic_store(object, desired) \
- atomic_store_explicit (object, desired, __ATOMIC_SEQ_CST)
-
-#define atomic_load_explicit(object, order) \
- ({ __typeof__ (object) ptr = (object); \
- __typeof__ (*ptr) tmp; \
- __atomic_load (ptr, &tmp, (order)); \
- tmp; \
- })
-#define atomic_load(object) atomic_load_explicit (object, __ATOMIC_SEQ_CST)
-
-#define atomic_exchange_explicit(object, desired, order) \
- ({ __typeof__ (object) ptr = (object); \
- __typeof__ (*ptr) val = (desired); \
- __typeof__ (*ptr) tmp; \
- __atomic_exchange (ptr, &val, &tmp, (order)); \
- tmp; \
- })
-#define atomic_exchange(object, desired) \
- atomic_exchange_explicit (object, desired, __ATOMIC_SEQ_CST)
-
-#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
- ({ __typeof__ (object) ptr = (object); \
- __typeof__ (*ptr) tmp = desired; \
- __atomic_compare_exchange(ptr, expected, &tmp, 0, success, failure); \
- })
-#define atomic_compare_exchange_strong(object, expected, desired) \
- atomic_compare_exchange_strong_explicit (object, expected, desired, \
- __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
-
-#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
- ({ __typeof__ (object) ptr = (object); \
- __typeof__ (*ptr) tmp = desired; \
- __atomic_compare_exchange(ptr, expected, &tmp, 1, success, failure); \
- })
-#define atomic_compare_exchange_weak(object, expected, desired) \
- atomic_compare_exchange_weak_explicit (PTR, VAL, DES, \
- __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
-
-#define atomic_fetch_add(object, operand) \
- __atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
-#define atomic_fetch_add_explicit __atomic_fetch_add
-
-#define atomic_fetch_sub(object, operand) \
- __atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST)
-#define atomic_fetch_sub_explicit __atomic_fetch_sub
-
-#define atomic_fetch_or(object, operand) \
- __atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST)
-#define atomic_fetch_or_explicit __atomic_fetch_or
-
-#define atomic_fetch_xor(object, operand) \
- __atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST)
-#define atomic_fetch_xor_explicit __atomic_fetch_xor
-
-#define atomic_fetch_and(object, operand) \
- __atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST)
-#define atomic_fetch_and_explicit __atomic_fetch_and
-
-extern void atomic_thread_fence (memory_order);
-extern void __atomic_thread_fence (memory_order);
-#define atomic_thread_fence(order) __atomic_thread_fence (order)
-extern void atomic_signal_fence (memory_order);
-extern void __atomic_signal_fence (memory_order);
-#define atomic_signal_fence(order) __atomic_signal_fence (order)
-extern bool __atomic_is_lock_free(size_t size, void *ptr);
-#define atomic_is_lock_free(OBJ) __atomic_is_lock_free (sizeof (*(OBJ)), (OBJ))
-
-extern bool __atomic_test_and_set (void *, memory_order);
-extern void __atomic_clear (bool *, memory_order);
-
-#endif /* _STDATOMIC_H */
diff --git a/tinycc/include/stdbool.h b/tinycc/include/stdbool.h
deleted file mode 100644
index d2ee446..0000000
--- a/tinycc/include/stdbool.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _STDBOOL_H
-#define _STDBOOL_H
-
-/* ISOC99 boolean */
-
-#define bool _Bool
-#define true 1
-#define false 0
-#define __bool_true_false_are_defined 1
-
-#endif /* _STDBOOL_H */
diff --git a/tinycc/include/stddef.h b/tinycc/include/stddef.h
deleted file mode 100644
index da9b9e0..0000000
--- a/tinycc/include/stddef.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef _STDDEF_H
-#define _STDDEF_H
-
-typedef __SIZE_TYPE__ size_t;
-typedef __PTRDIFF_TYPE__ ssize_t;
-typedef __WCHAR_TYPE__ wchar_t;
-typedef __PTRDIFF_TYPE__ ptrdiff_t;
-typedef __PTRDIFF_TYPE__ intptr_t;
-typedef __SIZE_TYPE__ uintptr_t;
-
-#if __STDC_VERSION__ >= 201112L
-typedef union { long long __ll; long double __ld; } max_align_t;
-#endif
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
-
-#undef offsetof
-#define offsetof(type, field) ((size_t)&((type *)0)->field)
-
-#if defined __i386__ || defined __x86_64__
-void *alloca(size_t size);
-#endif
-
-#endif
-
-/* Older glibc require a wint_t from <stddef.h> (when requested
- by __need_wint_t, as otherwise stddef.h isn't allowed to
- define this type). Note that this must be outside the normal
- _STDDEF_H guard, so that it works even when we've included the file
- already (without requiring wint_t). Some other libs define _WINT_T
- if they've already provided that type, so we can use that as guard.
- TCC defines __WINT_TYPE__ for us. */
-#if defined (__need_wint_t)
-#ifndef _WINT_T
-#define _WINT_T
-typedef __WINT_TYPE__ wint_t;
-#endif
-#undef __need_wint_t
-#endif
diff --git a/tinycc/include/stdnoreturn.h b/tinycc/include/stdnoreturn.h
deleted file mode 100644
index 4d580ea..0000000
--- a/tinycc/include/stdnoreturn.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _STDNORETURN_H
-#define _STDNORETURN_H
-
-/* ISOC11 noreturn */
-#define noreturn _Noreturn
-
-#endif /* _STDNORETURN_H */
diff --git a/tinycc/include/tccdefs.h b/tinycc/include/tccdefs.h
deleted file mode 100644
index 4e03cb9..0000000
--- a/tinycc/include/tccdefs.h
+++ /dev/null
@@ -1,325 +0,0 @@
-/* tccdefs.h
-
- Nothing is defined before this file except target machine, target os
- and the few things related to option settings in tccpp.c:tcc_predefs().
-
- This file is either included at runtime as is, or converted and
- included as C-strings at compile-time (depending on CONFIG_TCC_PREDEFS).
-
- Note that line indent matters:
-
- - in lines starting at column 1, platform macros are replaced by
- corresponding TCC target compile-time macros. See conftest.c for
- the list of platform macros supported in lines starting at column 1.
-
- - only lines indented >= 4 are actually included into the executable,
- check tccdefs_.h.
-*/
-
-#if __SIZEOF_POINTER__ == 4
- /* 32bit systems. */
-#if defined __OpenBSD__
- #define __SIZE_TYPE__ unsigned long
- #define __PTRDIFF_TYPE__ long
-#else
- #define __SIZE_TYPE__ unsigned int
- #define __PTRDIFF_TYPE__ int
-#endif
- #define __ILP32__ 1
- #define __INT64_TYPE__ long long
-#elif __SIZEOF_LONG__ == 4
- /* 64bit Windows. */
- #define __SIZE_TYPE__ unsigned long long
- #define __PTRDIFF_TYPE__ long long
- #define __LLP64__ 1
- #define __INT64_TYPE__ long long
-#else
- /* Other 64bit systems. */
- #define __SIZE_TYPE__ unsigned long
- #define __PTRDIFF_TYPE__ long
- #define __LP64__ 1
-# if defined __linux__
- #define __INT64_TYPE__ long
-# else /* APPLE, BSD */
- #define __INT64_TYPE__ long long
-# endif
-#endif
- #define __SIZEOF_INT__ 4
- #define __INT_MAX__ 0x7fffffff
-#if __SIZEOF_LONG__ == 4
- #define __LONG_MAX__ 0x7fffffffL
-#else
- #define __LONG_MAX__ 0x7fffffffffffffffL
-#endif
- #define __SIZEOF_LONG_LONG__ 8
- #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
- #define __CHAR_BIT__ 8
- #define __ORDER_LITTLE_ENDIAN__ 1234
- #define __ORDER_BIG_ENDIAN__ 4321
- #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
-#if defined _WIN32
- #define __WCHAR_TYPE__ unsigned short
- #define __WINT_TYPE__ unsigned short
-#elif defined __linux__
- #define __WCHAR_TYPE__ int
- #define __WINT_TYPE__ unsigned int
-#else
- #define __WCHAR_TYPE__ int
- #define __WINT_TYPE__ int
-#endif
-
- #if __STDC_VERSION__ >= 201112L
- # define __STDC_NO_ATOMICS__ 1
- # define __STDC_NO_COMPLEX__ 1
- # define __STDC_NO_THREADS__ 1
-#if !defined _WIN32
- # define __STDC_UTF_16__ 1
- # define __STDC_UTF_32__ 1
-#endif
- #endif
-
-#if defined _WIN32
- #define __declspec(x) __attribute__((x))
- #define __cdecl
-
-#elif defined __FreeBSD__
- #define __GNUC__ 9
- #define __GNUC_MINOR__ 3
- #define __GNUC_PATCHLEVEL__ 0
- #define __GNUC_STDC_INLINE__ 1
- #define __NO_TLS 1
- #define __RUNETYPE_INTERNAL 1
-# if __SIZEOF_POINTER__ == 8
- /* FIXME, __int128_t is used by setjump */
- #define __int128_t struct { unsigned char _dummy[16] __attribute((aligned(16))); }
- #define __SIZEOF_SIZE_T__ 8
- #define __SIZEOF_PTRDIFF_T__ 8
-#else
- #define __SIZEOF_SIZE_T__ 4
- #define __SIZEOF_PTRDIFF_T__ 4
-# endif
-
-#elif defined __FreeBSD_kernel__
-
-#elif defined __NetBSD__
- #define __GNUC__ 4
- #define __GNUC_MINOR__ 1
- #define __GNUC_PATCHLEVEL__ 0
- #define _Pragma(x)
- #define __ELF__ 1
-#if defined __aarch64__
- #define _LOCORE /* avoids usage of __asm */
-#endif
-
-#elif defined __OpenBSD__
- #define __GNUC__ 4
- #define _ANSI_LIBRARY 1
-
-#elif defined __APPLE__
- /* emulate APPLE-GCC to make libc's headerfiles compile: */
- #define __GNUC__ 4 /* darwin emits warning on GCC<4 */
- #define __APPLE_CC__ 1 /* for <TargetConditionals.h> */
- #define __LITTLE_ENDIAN__ 1
- #define _DONT_USE_CTYPE_INLINE_ 1
- /* avoids usage of GCC/clang specific builtins in libc-headerfiles: */
- #define __FINITE_MATH_ONLY__ 1
- #define _FORTIFY_SOURCE 0
-
-#elif defined __ANDROID__
- #define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
- #define __PRETTY_FUNCTION__ __FUNCTION__
- #define __has_builtin(x) 0
- #define __has_feature(x) 0
- #define _Nonnull
- #define _Nullable
-
-#else
- /* Linux */
-
-#endif
- /* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
-#ifndef __NetBSD__
- #define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
- #define __INTPTR_TYPE__ __PTRDIFF_TYPE__
-#endif
- #define __INT32_TYPE__ int
-
-#if !defined _WIN32
- /* glibc defines */
- #define __REDIRECT(name, proto, alias) name proto __asm__ (#alias)
- #define __REDIRECT_NTH(name, proto, alias) name proto __asm__ (#alias) __THROW
-#endif
-
- /* skip __builtin... with -E */
- #ifndef __TCC_PP__
-
- #define __builtin_offsetof(type, field) ((__SIZE_TYPE__)&((type*)0)->field)
- #define __builtin_extract_return_addr(x) x
-#if !defined __linux__ && !defined _WIN32
- /* used by math.h */
- #define __builtin_huge_val() 1e500
- #define __builtin_huge_valf() 1e50f
- #define __builtin_huge_vall() 1e5000L
-# if defined __APPLE__
- #define __builtin_nanf(ignored_string) (0.0F/0.0F)
- /* used by floats.h to implement FLT_ROUNDS C99 macro. 1 == to nearest */
- #define __builtin_flt_rounds() 1
- /* used by _fd_def.h */
- #define __builtin_bzero(p, ignored_size) bzero(p, sizeof(*(p)))
-# else
- #define __builtin_nanf(ignored_string) (0.0F/0.0F)
-# endif
-#endif
-
- /* __builtin_va_list */
-#if defined __x86_64__
-#if !defined _WIN32
- /* GCC compatible definition of va_list. */
- /* This should be in sync with the declaration in our lib/libtcc1.c */
- typedef struct {
- unsigned gp_offset, fp_offset;
- union {
- unsigned overflow_offset;
- char *overflow_arg_area;
- };
- char *reg_save_area;
- } __builtin_va_list[1];
-
- void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align);
- #define __builtin_va_start(ap, last) \
- (*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24))
- #define __builtin_va_arg(ap, t) \
- (*(t *)(__va_arg(ap, __builtin_va_arg_types(t), sizeof(t), __alignof__(t))))
- #define __builtin_va_copy(dest, src) (*(dest) = *(src))
-
-#else /* _WIN64 */
- typedef char* __builtin_va_list;
- #define __builtin_va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
- ? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
-#endif
-
-#elif defined __arm__
- typedef char *__builtin_va_list;
- #define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
- #define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
- & ~(_tcc_alignof(type) - 1))
- #define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
- #define __builtin_va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
- &~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
-
-#elif defined __aarch64__
-#if defined __APPLE__
- typedef struct {
- void *__stack;
- } __builtin_va_list;
-
-#else
- typedef struct {
- void *__stack, *__gr_top, *__vr_top;
- int __gr_offs, __vr_offs;
- } __builtin_va_list;
-
-#endif
-#elif defined __riscv
- typedef char *__builtin_va_list;
- #define __va_reg_size (__riscv_xlen >> 3)
- #define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
- & -(__alignof__(type)))
- #define __builtin_va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
-
-#else /* __i386__ */
- typedef char *__builtin_va_list;
- #define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
- #define __builtin_va_arg(ap,t) (*(t*)((ap+=(sizeof(t)+3)&~3)-((sizeof(t)+3)&~3)))
-
-#endif
- #define __builtin_va_end(ap) (void)(ap)
- #ifndef __builtin_va_copy
- # define __builtin_va_copy(dest, src) (dest) = (src)
- #endif
-
- /* TCC BBUILTIN AND BOUNDS ALIASES */
- #ifdef __leading_underscore
- # define __RENAME(X) __asm__("_"X)
- #else
- # define __RENAME(X) __asm__(X)
- #endif
-
- #ifdef __TCC_BCHECK__
- # define __BUILTINBC(ret,name,params) ret __builtin_##name params __RENAME("__bound_"#name);
- # define __BOUND(ret,name,params) ret name params __RENAME("__bound_"#name);
- #else
- # define __BUILTINBC(ret,name,params) ret __builtin_##name params __RENAME(#name);
- # define __BOUND(ret,name,params)
- #endif
-#ifdef _WIN32
- #define __BOTH __BOUND
- #define __BUILTIN(ret,name,params)
-#else
- #define __BOTH(ret,name,params) __BUILTINBC(ret,name,params)__BOUND(ret,name,params)
- #define __BUILTIN(ret,name,params) ret __builtin_##name params __RENAME(#name);
-#endif
-
- __BOTH(void*, memcpy, (void *, const void*, __SIZE_TYPE__))
- __BOTH(void*, memmove, (void *, const void*, __SIZE_TYPE__))
- __BOTH(void*, memset, (void *, int, __SIZE_TYPE__))
- __BOTH(int, memcmp, (const void *, const void*, __SIZE_TYPE__))
- __BOTH(__SIZE_TYPE__, strlen, (const char *))
- __BOTH(char*, strcpy, (char *, const char *))
- __BOTH(char*, strncpy, (char *, const char*, __SIZE_TYPE__))
- __BOTH(int, strcmp, (const char*, const char*))
- __BOTH(int, strncmp, (const char*, const char*, __SIZE_TYPE__))
- __BOTH(char*, strcat, (char*, const char*))
- __BOTH(char*, strncat, (char*, const char*, __SIZE_TYPE__))
- __BOTH(char*, strchr, (const char*, int))
- __BOTH(char*, strrchr, (const char*, int))
- __BOTH(char*, strdup, (const char*))
-#if defined __ARM_EABI__
- __BOUND(void*,__aeabi_memcpy,(void*,const void*,__SIZE_TYPE__))
- __BOUND(void*,__aeabi_memmove,(void*,const void*,__SIZE_TYPE__))
- __BOUND(void*,__aeabi_memmove4,(void*,const void*,__SIZE_TYPE__))
- __BOUND(void*,__aeabi_memmove8,(void*,const void*,__SIZE_TYPE__))
- __BOUND(void*,__aeabi_memset,(void*,int,__SIZE_TYPE__))
-#endif
-
-#if defined __linux__ || defined __APPLE__ // HAVE MALLOC_REDIR
- #define __MAYBE_REDIR __BUILTIN
-#else
- #define __MAYBE_REDIR __BOTH
-#endif
- __MAYBE_REDIR(void*, malloc, (__SIZE_TYPE__))
- __MAYBE_REDIR(void*, realloc, (void *, __SIZE_TYPE__))
- __MAYBE_REDIR(void*, calloc, (__SIZE_TYPE__, __SIZE_TYPE__))
- __MAYBE_REDIR(void*, memalign, (__SIZE_TYPE__, __SIZE_TYPE__))
- __MAYBE_REDIR(void, free, (void*))
-#if defined __i386__ || defined __x86_64__
- __BOTH(void*, alloca, (__SIZE_TYPE__))
-#else
- __BUILTIN(void*, alloca, (__SIZE_TYPE__))
-#endif
- __BUILTIN(void, abort, (void))
- __BOUND(void, longjmp, ())
-#if !defined _WIN32
- __BOUND(void*, mmap, ())
- __BOUND(int, munmap, ())
-#endif
- #undef __BUILTINBC
- #undef __BUILTIN
- #undef __BOUND
- #undef __BOTH
- #undef __MAYBE_REDIR
- #undef __RENAME
-
- #define __BUILTIN_EXTERN(name,u) \
- int __builtin_##name(u int); \
- int __builtin_##name##l(u long); \
- int __builtin_##name##ll(u long long);
- __BUILTIN_EXTERN(ffs,)
- __BUILTIN_EXTERN(clz, unsigned)
- __BUILTIN_EXTERN(ctz, unsigned)
- __BUILTIN_EXTERN(clrsb,)
- __BUILTIN_EXTERN(popcount, unsigned)
- __BUILTIN_EXTERN(parity, unsigned)
- #undef __BUILTIN_EXTERN
-
- #endif /* ndef __TCC_PP__ */ \ No newline at end of file
diff --git a/tinycc/include/tgmath.h b/tinycc/include/tgmath.h
deleted file mode 100644
index 5d3e357..0000000
--- a/tinycc/include/tgmath.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * ISO C Standard: 7.22 Type-generic math <tgmath.h>
- */
-
-#ifndef _TGMATH_H
-#define _TGMATH_H
-
-#include <math.h>
-
-#ifndef __cplusplus
-#define __tgmath_real(x, F) \
- _Generic ((x), float: F##f, long double: F##l, default: F)(x)
-#define __tgmath_real_2_1(x, y, F) \
- _Generic ((x), float: F##f, long double: F##l, default: F)(x, y)
-#define __tgmath_real_2(x, y, F) \
- _Generic ((x)+(y), float: F##f, long double: F##l, default: F)(x, y)
-#define __tgmath_real_3_2(x, y, z, F) \
- _Generic ((x)+(y), float: F##f, long double: F##l, default: F)(x, y, z)
-#define __tgmath_real_3(x, y, z, F) \
- _Generic ((x)+(y)+(z), float: F##f, long double: F##l, default: F)(x, y, z)
-
-/* Functions defined in both <math.h> and <complex.h> (7.22p4) */
-#define acos(z) __tgmath_real(z, acos)
-#define asin(z) __tgmath_real(z, asin)
-#define atan(z) __tgmath_real(z, atan)
-#define acosh(z) __tgmath_real(z, acosh)
-#define asinh(z) __tgmath_real(z, asinh)
-#define atanh(z) __tgmath_real(z, atanh)
-#define cos(z) __tgmath_real(z, cos)
-#define sin(z) __tgmath_real(z, sin)
-#define tan(z) __tgmath_real(z, tan)
-#define cosh(z) __tgmath_real(z, cosh)
-#define sinh(z) __tgmath_real(z, sinh)
-#define tanh(z) __tgmath_real(z, tanh)
-#define exp(z) __tgmath_real(z, exp)
-#define log(z) __tgmath_real(z, log)
-#define pow(z1,z2) __tgmath_real_2(z1, z2, pow)
-#define sqrt(z) __tgmath_real(z, sqrt)
-#define fabs(z) __tgmath_real(z, fabs)
-
-/* Functions defined in <math.h> only (7.22p5) */
-#define atan2(x,y) __tgmath_real_2(x, y, atan2)
-#define cbrt(x) __tgmath_real(x, cbrt)
-#define ceil(x) __tgmath_real(x, ceil)
-#define copysign(x,y) __tgmath_real_2(x, y, copysign)
-#define erf(x) __tgmath_real(x, erf)
-#define erfc(x) __tgmath_real(x, erfc)
-#define exp2(x) __tgmath_real(x, exp2)
-#define expm1(x) __tgmath_real(x, expm1)
-#define fdim(x,y) __tgmath_real_2(x, y, fdim)
-#define floor(x) __tgmath_real(x, floor)
-#define fma(x,y,z) __tgmath_real_3(x, y, z, fma)
-#define fmax(x,y) __tgmath_real_2(x, y, fmax)
-#define fmin(x,y) __tgmath_real_2(x, y, fmin)
-#define fmod(x,y) __tgmath_real_2(x, y, fmod)
-#define frexp(x,y) __tgmath_real_2_1(x, y, frexp)
-#define hypot(x,y) __tgmath_real_2(x, y, hypot)
-#define ilogb(x) __tgmath_real(x, ilogb)
-#define ldexp(x,y) __tgmath_real_2_1(x, y, ldexp)
-#define lgamma(x) __tgmath_real(x, lgamma)
-#define llrint(x) __tgmath_real(x, llrint)
-#define llround(x) __tgmath_real(x, llround)
-#define log10(x) __tgmath_real(x, log10)
-#define log1p(x) __tgmath_real(x, log1p)
-#define log2(x) __tgmath_real(x, log2)
-#define logb(x) __tgmath_real(x, logb)
-#define lrint(x) __tgmath_real(x, lrint)
-#define lround(x) __tgmath_real(x, lround)
-#define nearbyint(x) __tgmath_real(x, nearbyint)
-#define nextafter(x,y) __tgmath_real_2(x, y, nextafter)
-#define nexttoward(x,y) __tgmath_real_2(x, y, nexttoward)
-#define remainder(x,y) __tgmath_real_2(x, y, remainder)
-#define remquo(x,y,z) __tgmath_real_3_2(x, y, z, remquo)
-#define rint(x) __tgmath_real(x, rint)
-#define round(x) __tgmath_real(x, round)
-#define scalbln(x,y) __tgmath_real_2_1(x, y, scalbln)
-#define scalbn(x,y) __tgmath_real_2_1(x, y, scalbn)
-#define tgamma(x) __tgmath_real(x, tgamma)
-#define trunc(x) __tgmath_real(x, trunc)
-
-/* Functions defined in <complex.h> only (7.22p6)
-#define carg(z) __tgmath_cplx_only(z, carg)
-#define cimag(z) __tgmath_cplx_only(z, cimag)
-#define conj(z) __tgmath_cplx_only(z, conj)
-#define cproj(z) __tgmath_cplx_only(z, cproj)
-#define creal(z) __tgmath_cplx_only(z, creal)
-*/
-#endif /* __cplusplus */
-#endif /* _TGMATH_H */
diff --git a/tinycc/include/varargs.h b/tinycc/include/varargs.h
deleted file mode 100644
index d614366..0000000
--- a/tinycc/include/varargs.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is part of the w64 mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within this package.
- */
-#ifndef _VARARGS_H
-#define _VARARGS_H
-
-#error "TinyCC no longer implements <varargs.h>."
-#error "Revise your code to use <stdarg.h>."
-
-#endif
diff --git a/tinycc/lib/Makefile b/tinycc/lib/Makefile
deleted file mode 100644
index 6f08376..0000000
--- a/tinycc/lib/Makefile
+++ /dev/null
@@ -1,94 +0,0 @@
-#
-# Tiny C Compiler Makefile for libtcc1.a
-#
-
-TOP = ..
-include $(TOP)/Makefile
-VPATH = $(TOPSRC)/lib $(TOPSRC)/win32/lib
-T = $(or $(CROSS_TARGET),$(NATIVE_TARGET),unknown)
-X = $(if $(CROSS_TARGET),$(CROSS_TARGET)-)
-
-XTCC ?= $(TOP)/$(X)tcc$(EXESUF)
-XCC = $(XTCC)
-XAR = $(XTCC) -ar
-XFLAGS-unx = -B$(TOPSRC)
-XFLAGS-win = -B$(TOPSRC)/win32 -I$(TOPSRC)/include
-XFLAGS = $(XFLAGS$(XCFG)) -I$(TOP)
-XCFG = $(or $(findstring -win,$T),-unx)
-S = $(if $(findstring yes,$(SILENT)),@$(info * $@))
-
-# in order to use gcc, type: make <target>-libtcc1-usegcc=yes
-arm-libtcc1-usegcc ?= no
-
-# This makes bounds checking 40%..60% faster.
-x86_64-libtcc1-usegcc=yes
-#i386-libtcc1-usegcc=yes
-
-ifeq "$($(T)-libtcc1-usegcc)" "yes"
- XCC = $(CC)
- XAR = $(AR)
- XFLAGS = $(CFLAGS) -fPIC -gdwarf -fno-omit-frame-pointer -Wno-unused-function -Wno-unused-variable
-endif
-
-ifneq ($(CONFIG_backtrace),no)
-# only for native compiler
-ifneq ($(CONFIG_bcheck),no)
-$(X)BCHECK_O = bcheck.o
-endif
-$(X)BT_O = bt-exe.o bt-log.o
-$(X)B_O = $(BCHECK_O) bt-exe.o bt-log.o bt-dll.o
-endif
-$(X)BT_O += tcov.o
-
-DSO_O = dsohandle.o
-
-I386_O = libtcc1.o alloca.o alloca-bt.o stdatomic.o atomic.o builtin.o $(BT_O)
-X86_64_O = libtcc1.o alloca.o alloca-bt.o stdatomic.o atomic.o builtin.o $(BT_O)
-ARM_O = libtcc1.o armeabi.o alloca.o armflush.o stdatomic.o atomic.o builtin.o $(BT_O)
-ARM64_O = lib-arm64.o stdatomic.o atomic.o builtin.o $(BT_O)
-RISCV64_O = lib-arm64.o stdatomic.o atomic.o builtin.o $(BT_O)
-WIN_O = crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o
-
-OBJ-i386 = $(I386_O) $(BCHECK_O) $(DSO_O)
-OBJ-x86_64 = $(X86_64_O) va_list.o $(BCHECK_O) $(DSO_O)
-OBJ-x86_64-osx = $(X86_64_O) va_list.o $(BCHECK_O)
-OBJ-i386-win32 = $(I386_O) chkstk.o $(B_O) $(WIN_O)
-OBJ-x86_64-win32 = $(X86_64_O) chkstk.o $(B_O) $(WIN_O)
-OBJ-arm64 = $(ARM64_O) $(BCHECK_O) $(DSO_O)
-OBJ-arm64-osx = $(ARM64_O) $(BCHECK_O)
-OBJ-arm = $(ARM_O) $(BCHECK_O) $(DSO_O)
-OBJ-arm-fpa = $(ARM_O) $(DSO_O)
-OBJ-arm-fpa-ld = $(ARM_O) $(DSO_O)
-OBJ-arm-vfp = $(ARM_O) $(DSO_O)
-OBJ-arm-eabi = $(ARM_O) $(DSO_O)
-OBJ-arm-eabihf = $(ARM_O) $(DSO_O)
-OBJ-arm-wince = $(ARM_O) $(WIN_O)
-OBJ-riscv64 = $(RISCV64_O) $(BCHECK_O) $(DSO_O)
-
-OBJ-extra = $(filter $(B_O),$(OBJ-$T))
-OBJ-libtcc1 = $(addprefix $(X),$(filter-out $(OBJ-extra),$(OBJ-$T)))
-
-ALL = $(addprefix $(TOP)/,$(X)libtcc1.a $(OBJ-extra))
-
-all: $(ALL)
-
-$(TOP)/$(X)libtcc1.a : $(OBJ-libtcc1)
- $S$(XAR) rcs $@ $^
-
-$(X)%.o : %.c
- $S$(XCC) -c $< -o $@ $(XFLAGS)
-
-$(X)%.o : %.S
- $S$(XCC) -c $< -o $@ $(XFLAGS)
-
-$(TOP)/%.o : %.c
- $S$(XCC) -c $< -o $@ $(XFLAGS)
-
-$(TOP)/bcheck.o : XFLAGS += -g $(if $(CONFIG_musl),-DTCC_MUSL)
-$(TOP)/bt-exe.o : $(TOP)/tccrun.c
-
-$(X)crt1w.o : crt1.c
-$(X)wincrt1w.o : wincrt1.c
-
-clean :
- rm -f *.a *.o $(ALL)
diff --git a/tinycc/lib/alloca-bt.S b/tinycc/lib/alloca-bt.S
deleted file mode 100644
index c161488..0000000
--- a/tinycc/lib/alloca-bt.S
+++ /dev/null
@@ -1,96 +0,0 @@
-/* ---------------------------------------------- */
-/* alloca-bt.S */
-
-#ifdef __leading_underscore
-# define _(s) _##s
-#else
-# define _(s) s
-#endif
-
-/* ---------------------------------------------- */
-#if defined __i386__
-
-.globl _(__bound_alloca)
-_(__bound_alloca):
- pop %edx
- pop %eax
- mov %eax, %ecx
- add $3+1,%eax
- and $-4,%eax
- jz p6
-
-#ifdef _WIN32
-p4:
- cmp $4096,%eax
- jbe p5
- test %eax,-4096(%esp)
- sub $4096,%esp
- sub $4096,%eax
- jmp p4
-
-p5:
-#endif
-
- sub %eax,%esp
- mov %esp,%eax
-
- push %edx
- push %eax
- push %ecx
- push %eax
- call _(__bound_new_region)
- add $8, %esp
- pop %eax
- pop %edx
-
-p6:
- push %edx
- push %edx
- ret
-
-/* ---------------------------------------------- */
-#elif defined __x86_64__
-
-.globl _(__bound_alloca)
-_(__bound_alloca):
-#ifdef _WIN32
- inc %rcx # add one extra to separate regions
- jmp _(alloca)
-.globl _(__bound_alloca_nr)
-_(__bound_alloca_nr):
- dec %rcx
- push %rax
- mov %rcx,%rdx
- mov %rax,%rcx
- sub $32,%rsp
- call _(__bound_new_region)
- add $32,%rsp
- pop %rax
- ret
-#else
- pop %rdx
- mov %rdi,%rax
- mov %rax,%rsi # size, a second parm to the __bound_new_region
-
- add $15 + 1,%rax # add one extra to separate regions
- and $-16,%rax
- jz p3
-
-
- sub %rax,%rsp
- mov %rsp,%rdi # pointer, a first parm to the __bound_new_region
- mov %rsp,%rax
-
- push %rdx
- push %rax
- call _(__bound_new_region)
- pop %rax
- pop %rdx
-
-p3:
- push %rdx
- ret
-#endif
-
-/* ---------------------------------------------- */
-#endif
diff --git a/tinycc/lib/alloca.S b/tinycc/lib/alloca.S
deleted file mode 100644
index 6ebafd7..0000000
--- a/tinycc/lib/alloca.S
+++ /dev/null
@@ -1,85 +0,0 @@
-/* ---------------------------------------------- */
-/* alloca.S */
-
-#ifdef __leading_underscore
-# define _(s) _##s
-#else
-# define _(s) s
-#endif
-
-/* ---------------------------------------------- */
-#if defined __i386__
-
-.globl _(alloca), _(__alloca)
-_(alloca):
-_(__alloca):
- push %ebp
- mov %esp,%ebp
- mov 8(%ebp),%eax
- add $3,%eax
- and $-4,%eax
-#ifdef _WIN32
- jmp .+16 #p2
-p1:
- sub $4096,%esp
- sub $4096,%eax
- test %eax,(%esp)
-p2:
- cmp $4096,%eax
- jae p1
-#endif
- sub %eax,%esp
- mov 4(%ebp),%eax
- mov 0(%ebp),%ebp
- add $8,%esp
- push %eax
- lea 8(%esp),%eax
- ret
-
-/* ---------------------------------------------- */
-#elif defined __x86_64__
-
-.globl _(alloca)
-_(alloca):
- pop %rdx
-#ifdef _WIN32
- mov %rcx,%rax
-#else
- mov %rdi,%rax
-#endif
- add $15,%rax
- and $-16,%rax
- jz p3
-
-#ifdef _WIN32
-p1:
- cmp $4096,%rax
- jbe p2
- test %rax,-4096(%rsp)
- sub $4096,%rsp
- sub $4096,%rax
- jmp p1
-p2:
-#endif
- sub %rax,%rsp
- mov %rsp,%rax
-p3:
- push %rdx
- ret
-
-/* ---------------------------------------------- */
-#elif defined __arm__
-
- .text
- .align 2
- .global alloca
- .type alloca, %function
-alloca:
- rsb sp, r0, sp
- bic sp, sp, #7
- mov r0, sp
- mov pc, lr
- .size alloca, .-alloca
-
-/* ---------------------------------------------- */
-#endif
diff --git a/tinycc/lib/armeabi.c b/tinycc/lib/armeabi.c
deleted file mode 100644
index 6ade65e..0000000
--- a/tinycc/lib/armeabi.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/* TCC ARM runtime EABI
- Copyright (C) 2013 Thomas Preud'homme
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.*/
-
-#ifdef __TINYC__
-#define INT_MIN (-2147483647 - 1)
-#define INT_MAX 2147483647
-#define UINT_MAX 0xffffffff
-#define LONG_MIN (-2147483647L - 1)
-#define LONG_MAX 2147483647L
-#define ULONG_MAX 0xffffffffUL
-#define LLONG_MAX 9223372036854775807LL
-#define LLONG_MIN (-9223372036854775807LL - 1)
-#define ULLONG_MAX 0xffffffffffffffffULL
-#else
-#include <limits.h>
-#endif
-
-/* We rely on the little endianness and EABI calling convention for this to
- work */
-
-typedef struct double_unsigned_struct {
- unsigned low;
- unsigned high;
-} double_unsigned_struct;
-
-typedef struct unsigned_int_struct {
- unsigned low;
- int high;
-} unsigned_int_struct;
-
-#define REGS_RETURN(name, type) \
- void name ## _return(type ret) {}
-
-
-/* Float helper functions */
-
-#define FLOAT_EXP_BITS 8
-#define FLOAT_FRAC_BITS 23
-
-#define DOUBLE_EXP_BITS 11
-#define DOUBLE_FRAC_BITS 52
-
-#define ONE_EXP(type) ((1 << (type ## _EXP_BITS - 1)) - 1)
-
-REGS_RETURN(unsigned_int_struct, unsigned_int_struct)
-REGS_RETURN(double_unsigned_struct, double_unsigned_struct)
-
-/* float -> integer: (sign) 1.fraction x 2^(exponent - exp_for_one) */
-
-
-/* float to [unsigned] long long conversion */
-#define DEFINE__AEABI_F2XLZ(name, with_sign) \
-void __aeabi_ ## name(unsigned val) \
-{ \
- int exp, high_shift, sign; \
- double_unsigned_struct ret; \
- \
- /* compute sign */ \
- sign = val >> 31; \
- \
- /* compute real exponent */ \
- exp = val >> FLOAT_FRAC_BITS; \
- exp &= (1 << FLOAT_EXP_BITS) - 1; \
- exp -= ONE_EXP(FLOAT); \
- \
- /* undefined behavior if truncated value cannot be represented */ \
- if (with_sign) { \
- if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
- return; \
- } else { \
- if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
- return; \
- } \
- \
- val &= (1 << FLOAT_FRAC_BITS) - 1; \
- if (exp >= 32) { \
- ret.high = 1 << (exp - 32); \
- if (exp - 32 >= FLOAT_FRAC_BITS) { \
- ret.high |= val << (exp - 32 - FLOAT_FRAC_BITS); \
- ret.low = 0; \
- } else { \
- high_shift = FLOAT_FRAC_BITS - (exp - 32); \
- ret.high |= val >> high_shift; \
- ret.low = val << (32 - high_shift); \
- } \
- } else { \
- ret.high = 0; \
- ret.low = 1 << exp; \
- if (exp > FLOAT_FRAC_BITS) \
- ret.low |= val << (exp - FLOAT_FRAC_BITS); \
- else \
- ret.low |= val >> (FLOAT_FRAC_BITS - exp); \
- } \
- \
- /* encode negative integer using 2's complement */ \
- if (with_sign && sign) { \
- ret.low = ~ret.low; \
- ret.high = ~ret.high; \
- if (ret.low == UINT_MAX) { \
- ret.low = 0; \
- ret.high++; \
- } else \
- ret.low++; \
- } \
- \
- double_unsigned_struct_return(ret); \
-}
-
-/* float to unsigned long long conversion */
-DEFINE__AEABI_F2XLZ(f2ulz, 0)
-
-/* float to long long conversion */
-DEFINE__AEABI_F2XLZ(f2lz, 1)
-
-/* double to [unsigned] long long conversion */
-#define DEFINE__AEABI_D2XLZ(name, with_sign) \
-void __aeabi_ ## name(double_unsigned_struct val) \
-{ \
- int exp, high_shift, sign; \
- double_unsigned_struct ret; \
- \
- if ((val.high & ~0x80000000) == 0 && val.low == 0) { \
- ret.low = ret.high = 0; \
- goto _ret_; \
- } \
- \
- /* compute sign */ \
- sign = val.high >> 31; \
- \
- /* compute real exponent */ \
- exp = (val.high >> (DOUBLE_FRAC_BITS - 32)); \
- exp &= (1 << DOUBLE_EXP_BITS) - 1; \
- exp -= ONE_EXP(DOUBLE); \
- \
- /* undefined behavior if truncated value cannot be represented */ \
- if (with_sign) { \
- if (exp > 62) /* |val| too big, double cannot represent LLONG_MAX */ \
- return; \
- } else { \
- if ((sign && exp >= 0) || exp > 63) /* if val < 0 || val too big */ \
- return; \
- } \
- \
- val.high &= (1 << (DOUBLE_FRAC_BITS - 32)) - 1; \
- if (exp >= 32) { \
- ret.high = 1 << (exp - 32); \
- if (exp >= DOUBLE_FRAC_BITS) { \
- high_shift = exp - DOUBLE_FRAC_BITS; \
- ret.high |= val.high << high_shift; \
- ret.high |= val.low >> (32 - high_shift); \
- ret.low = val.low << high_shift; \
- } else { \
- high_shift = DOUBLE_FRAC_BITS - exp; \
- ret.high |= val.high >> high_shift; \
- ret.low = val.high << (32 - high_shift); \
- ret.low |= val.low >> high_shift; \
- } \
- } else { \
- ret.high = 0; \
- ret.low = 1 << exp; \
- if (exp > DOUBLE_FRAC_BITS - 32) { \
- high_shift = exp - DOUBLE_FRAC_BITS - 32; \
- ret.low |= val.high << high_shift; \
- ret.low |= val.low >> (32 - high_shift); \
- } else \
- ret.low |= val.high >> (DOUBLE_FRAC_BITS - 32 - exp); \
- } \
- \
- /* encode negative integer using 2's complement */ \
- if (with_sign && sign) { \
- ret.low = ~ret.low; \
- ret.high = ~ret.high; \
- if (ret.low == UINT_MAX) { \
- ret.low = 0; \
- ret.high++; \
- } else \
- ret.low++; \
- } \
- \
-_ret_: \
- double_unsigned_struct_return(ret); \
-}
-
-/* double to unsigned long long conversion */
-DEFINE__AEABI_D2XLZ(d2ulz, 0)
-
-/* double to long long conversion */
-DEFINE__AEABI_D2XLZ(d2lz, 1)
-
-/* long long to float conversion */
-#define DEFINE__AEABI_XL2F(name, with_sign) \
-unsigned __aeabi_ ## name(unsigned long long v) \
-{ \
- int s /* shift */, flb /* first lost bit */, sign = 0; \
- unsigned p = 0 /* power */, ret; \
- double_unsigned_struct val; \
- \
- /* fraction in negative float is encoded in 1's complement */ \
- if (with_sign && (v & (1ULL << 63))) { \
- sign = 1; \
- v = ~v + 1; \
- } \
- val.low = v; \
- val.high = v >> 32; \
- /* fill fraction bits */ \
- for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
- if (p) { \
- ret = val.high & (p - 1); \
- if (s < FLOAT_FRAC_BITS) { \
- ret <<= FLOAT_FRAC_BITS - s; \
- ret |= val.low >> (32 - (FLOAT_FRAC_BITS - s)); \
- flb = (val.low >> (32 - (FLOAT_FRAC_BITS - s - 1))) & 1; \
- } else { \
- flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
- ret >>= s - FLOAT_FRAC_BITS; \
- } \
- s += 32; \
- } else { \
- for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
- if (p) { \
- ret = val.low & (p - 1); \
- if (s <= FLOAT_FRAC_BITS) { \
- ret <<= FLOAT_FRAC_BITS - s; \
- flb = 0; \
- } else { \
- flb = (ret >> (s - FLOAT_FRAC_BITS - 1)) & 1; \
- ret >>= s - FLOAT_FRAC_BITS; \
- } \
- } else \
- return 0; \
- } \
- if (flb) \
- ret++; \
- \
- /* fill exponent bits */ \
- ret |= (s + ONE_EXP(FLOAT)) << FLOAT_FRAC_BITS; \
- \
- /* fill sign bit */ \
- ret |= sign << 31; \
- \
- return ret; \
-}
-
-/* unsigned long long to float conversion */
-DEFINE__AEABI_XL2F(ul2f, 0)
-
-/* long long to float conversion */
-DEFINE__AEABI_XL2F(l2f, 1)
-
-/* long long to double conversion */
-#define __AEABI_XL2D(name, with_sign) \
-void __aeabi_ ## name(unsigned long long v) \
-{ \
- int s /* shift */, high_shift, sign = 0; \
- unsigned tmp, p = 0; \
- double_unsigned_struct val, ret; \
- \
- /* fraction in negative float is encoded in 1's complement */ \
- if (with_sign && (v & (1ULL << 63))) { \
- sign = 1; \
- v = ~v + 1; \
- } \
- val.low = v; \
- val.high = v >> 32; \
- \
- /* fill fraction bits */ \
- for (s = 31, p = 1 << 31; p && !(val.high & p); s--, p >>= 1); \
- if (p) { \
- tmp = val.high & (p - 1); \
- if (s < DOUBLE_FRAC_BITS - 32) { \
- high_shift = DOUBLE_FRAC_BITS - 32 - s; \
- ret.high = tmp << high_shift; \
- ret.high |= val.low >> (32 - high_shift); \
- ret.low = val.low << high_shift; \
- } else { \
- high_shift = s - (DOUBLE_FRAC_BITS - 32); \
- ret.high = tmp >> high_shift; \
- ret.low = tmp << (32 - high_shift); \
- ret.low |= val.low >> high_shift; \
- if ((val.low >> (high_shift - 1)) & 1) { \
- if (ret.low == UINT_MAX) { \
- ret.high++; \
- ret.low = 0; \
- } else \
- ret.low++; \
- } \
- } \
- s += 32; \
- } else { \
- for (s = 31, p = 1 << 31; p && !(val.low & p); s--, p >>= 1); \
- if (p) { \
- tmp = val.low & (p - 1); \
- if (s <= DOUBLE_FRAC_BITS - 32) { \
- high_shift = DOUBLE_FRAC_BITS - 32 - s; \
- ret.high = tmp << high_shift; \
- ret.low = 0; \
- } else { \
- high_shift = s - (DOUBLE_FRAC_BITS - 32); \
- ret.high = tmp >> high_shift; \
- ret.low = tmp << (32 - high_shift); \
- } \
- } else { \
- ret.high = ret.low = 0; \
- goto _ret_; \
- } \
- } \
- \
- /* fill exponent bits */ \
- ret.high |= (s + ONE_EXP(DOUBLE)) << (DOUBLE_FRAC_BITS - 32); \
- \
- /* fill sign bit */ \
- ret.high |= sign << 31; \
- \
-_ret_: \
- double_unsigned_struct_return(ret); \
-}
-
-/* unsigned long long to double conversion */
-__AEABI_XL2D(ul2d, 0)
-
-/* long long to double conversion */
-__AEABI_XL2D(l2d, 1)
-
-
-/* Long long helper functions */
-
-/* TODO: add error in case of den == 0 (see §4.3.1 and §4.3.2) */
-
-#define define_aeabi_xdivmod_signed_type(basetype, type) \
-typedef struct type { \
- basetype quot; \
- unsigned basetype rem; \
-} type
-
-#define define_aeabi_xdivmod_unsigned_type(basetype, type) \
-typedef struct type { \
- basetype quot; \
- basetype rem; \
-} type
-
-#define AEABI_UXDIVMOD(name,type, rettype, typemacro) \
-static inline rettype aeabi_ ## name (type num, type den) \
-{ \
- rettype ret; \
- type quot = 0; \
- \
- /* Increase quotient while it is less than numerator */ \
- while (num >= den) { \
- type q = 1; \
- \
- /* Find closest power of two */ \
- while ((q << 1) * den <= num && q * den <= typemacro ## _MAX / 2) \
- q <<= 1; \
- \
- /* Compute difference between current quotient and numerator */ \
- num -= q * den; \
- quot += q; \
- } \
- ret.quot = quot; \
- ret.rem = num; \
- return ret; \
-}
-
-#define __AEABI_XDIVMOD(name, type, uiname, rettype, urettype, typemacro) \
-void __aeabi_ ## name(type numerator, type denominator) \
-{ \
- unsigned type num, den; \
- urettype uxdiv_ret; \
- rettype ret; \
- \
- if (numerator >= 0) \
- num = numerator; \
- else \
- num = 0 - numerator; \
- if (denominator >= 0) \
- den = denominator; \
- else \
- den = 0 - denominator; \
- uxdiv_ret = aeabi_ ## uiname(num, den); \
- /* signs differ */ \
- if ((numerator & typemacro ## _MIN) != (denominator & typemacro ## _MIN)) \
- ret.quot = 0 - uxdiv_ret.quot; \
- else \
- ret.quot = uxdiv_ret.quot; \
- if (numerator < 0) \
- ret.rem = 0 - uxdiv_ret.rem; \
- else \
- ret.rem = uxdiv_ret.rem; \
- \
- rettype ## _return(ret); \
-}
-
-define_aeabi_xdivmod_signed_type(long long, lldiv_t);
-define_aeabi_xdivmod_unsigned_type(unsigned long long, ulldiv_t);
-define_aeabi_xdivmod_signed_type(int, idiv_t);
-define_aeabi_xdivmod_unsigned_type(unsigned, uidiv_t);
-
-REGS_RETURN(lldiv_t, lldiv_t)
-REGS_RETURN(ulldiv_t, ulldiv_t)
-REGS_RETURN(idiv_t, idiv_t)
-REGS_RETURN(uidiv_t, uidiv_t)
-
-AEABI_UXDIVMOD(uldivmod, unsigned long long, ulldiv_t, ULLONG)
-
-__AEABI_XDIVMOD(ldivmod, long long, uldivmod, lldiv_t, ulldiv_t, LLONG)
-
-void __aeabi_uldivmod(unsigned long long num, unsigned long long den)
-{
- ulldiv_t_return(aeabi_uldivmod(num, den));
-}
-
-void __aeabi_llsl(double_unsigned_struct val, int shift)
-{
- double_unsigned_struct ret;
-
- if (shift >= 32) {
- val.high = val.low;
- val.low = 0;
- shift -= 32;
- }
- if (shift > 0) {
- ret.low = val.low << shift;
- ret.high = (val.high << shift) | (val.low >> (32 - shift));
- double_unsigned_struct_return(ret);
- return;
- }
- double_unsigned_struct_return(val);
-}
-
-#define aeabi_lsr(val, shift, fill, type) \
- type ## _struct ret; \
- \
- if (shift >= 32) { \
- val.low = val.high; \
- val.high = fill; \
- shift -= 32; \
- } \
- if (shift > 0) { \
- ret.high = val.high >> shift; \
- ret.low = (val.high << (32 - shift)) | (val.low >> shift); \
- type ## _struct_return(ret); \
- return; \
- } \
- type ## _struct_return(val);
-
-void __aeabi_llsr(double_unsigned_struct val, int shift)
-{
- aeabi_lsr(val, shift, 0, double_unsigned);
-}
-
-void __aeabi_lasr(unsigned_int_struct val, int shift)
-{
- aeabi_lsr(val, shift, val.high >> 31, unsigned_int);
-}
-
-
-/* Integer division functions */
-
-AEABI_UXDIVMOD(uidivmod, unsigned, uidiv_t, UINT)
-
-int __aeabi_idiv(int numerator, int denominator)
-{
- unsigned num, den;
- uidiv_t ret;
-
- if (numerator >= 0)
- num = numerator;
- else
- num = 0 - numerator;
- if (denominator >= 0)
- den = denominator;
- else
- den = 0 - denominator;
- ret = aeabi_uidivmod(num, den);
- if ((numerator & INT_MIN) != (denominator & INT_MIN)) /* signs differ */
- ret.quot *= -1;
- return ret.quot;
-}
-
-unsigned __aeabi_uidiv(unsigned num, unsigned den)
-{
- return aeabi_uidivmod(num, den).quot;
-}
-
-__AEABI_XDIVMOD(idivmod, int, uidivmod, idiv_t, uidiv_t, INT)
-
-void __aeabi_uidivmod(unsigned num, unsigned den)
-{
- uidiv_t_return(aeabi_uidivmod(num, den));
-}
-
-/* Some targets do not have all eabi calls (OpenBSD) */
-typedef __SIZE_TYPE__ size_t;
-extern void *memcpy(void *dest, const void *src, size_t n);
-extern void *memmove(void *dest, const void *src, size_t n);
-extern void *memset(void *s, int c, size_t n);
-
-void *
-__aeabi_memcpy (void *dest, const void *src, size_t n)
-{
- return memcpy (dest, src, n);
-}
-
-void *
-__aeabi_memmove (void *dest, const void *src, size_t n)
-{
- return memmove (dest, src, n);
-}
-
-void *
-__aeabi_memmove4 (void *dest, const void *src, size_t n)
-{
- return memmove (dest, src, n);
-}
-
-void *
-__aeabi_memmove8 (void *dest, const void *src, size_t n)
-{
- return memmove (dest, src, n);
-}
-
-void *
-__aeabi_memset (void *s, size_t n, int c)
-{
- return memset (s, c, n);
-}
diff --git a/tinycc/lib/armflush.c b/tinycc/lib/armflush.c
deleted file mode 100644
index c379e43..0000000
--- a/tinycc/lib/armflush.c
+++ /dev/null
@@ -1,51 +0,0 @@
-/* armflush.c - flush the instruction cache
-
- __clear_cache is used in tccrun.c, It is a built-in
- intrinsic with gcc. However tcc in order to compile
- itself needs this function */
-
-#ifdef __TINYC__
-
-/* syscall wrapper */
-unsigned _tccsyscall(unsigned syscall_nr, ...);
-
-/* arm-tcc supports only fake asm currently */
-__asm__(
- ".global _tccsyscall\n"
- "_tccsyscall:\n"
- "push {r7, lr}\n\t"
- "mov r7, r0\n\t"
- "mov r0, r1\n\t"
- "mov r1, r2\n\t"
- "mov r2, r3\n\t"
- "svc #0\n\t"
- "pop {r7, pc}"
- );
-
-/* from unistd.h: */
-#if defined(__thumb__) || defined(__ARM_EABI__)
-# define __NR_SYSCALL_BASE 0x0
-#else
-# define __NR_SYSCALL_BASE 0x900000
-#endif
-#define __ARM_NR_BASE (__NR_SYSCALL_BASE+0x0f0000)
-#define __ARM_NR_cacheflush (__ARM_NR_BASE+2)
-
-#define syscall _tccsyscall
-
-#else
-
-#define _GNU_SOURCE
-#include <unistd.h>
-#include <sys/syscall.h>
-#include <stdio.h>
-
-#endif
-
-/* Flushing for tccrun */
-void __clear_cache(void *beginning, void *end)
-{
-/* __ARM_NR_cacheflush is kernel private and should not be used in user space.
- * However, there is no ARM asm parser in tcc so we use it for now */
- syscall(__ARM_NR_cacheflush, beginning, end, 0);
-}
diff --git a/tinycc/lib/atomic.S b/tinycc/lib/atomic.S
deleted file mode 100644
index 29fdbee..0000000
--- a/tinycc/lib/atomic.S
+++ /dev/null
@@ -1,858 +0,0 @@
-/* ---------------------------------------------- */
-/* This file implements for arm/arm64/riscv:
- * __atomic_compare_exchange_1
- * __atomic_compare_exchange_2
- * __atomic_compare_exchange_4
- * __atomic_compare_exchange_8
- */
-
-#ifdef __leading_underscore
-# define _(s) _##s
-#else
-# define _(s) s
-#endif
-
-#if defined __i386__
- .text
- .align 2
-
- .global _(__atomic_test_and_set)
- .type _(__atomic_test_and_set), %function
-_(__atomic_test_and_set):
- movl 4(%esp), %edx
- movl $1, %eax
- xchgb (%edx), %al
- ret
- .size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
-
- .global _(__atomic_clear)
- .type _(__atomic_clear), %function
-_(__atomic_clear):
- movl 4(%esp), %edx
- xorl %eax, %eax
- xchgb (%edx), %al
- ret
- .size _(__atomic_clear), .-_(__atomic_clear)
-
-#elif defined __x86_64__
- .text
- .align 2
-
- .global _(__atomic_test_and_set)
- .type _(__atomic_test_and_set), %function
-_(__atomic_test_and_set):
- movl $1, %eax
- xchgb (%rdi), %al
- ret
- .size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
-
- .global _(__atomic_clear)
- .type _(__atomic_clear), %function
-_(__atomic_clear):
- xorl %eax, %eax
- xchgb (%rdi), %al
- ret
- .size _(__atomic_clear), .-_(__atomic_clear)
-
-#elif defined __arm__
-
-#ifndef __TINYC__
- .arch armv6k
- .syntax unified
-#endif
- .text
- .align 2
-
- .global _(fetch_and_add_arm)
- .type _(fetch_and_add_arm), %function
-_(fetch_and_add_arm):
- mcr p15, #0, r0, c7, c10, #5
-.L0:
- ldrex r3, [r0]
- add r3, r3, r1
- strex r2, r3, [r0]
- cmp r2, #0
- bne .L0
- mcr p15, #0, r0, c7, c10, #5
- bx lr
- .size _(fetch_and_add_arm), .-_(fetch_and_add_arm)
-
- .global _(__atomic_test_and_set)
- .type _(__atomic_test_and_set), %function
-_(__atomic_test_and_set):
-#ifdef __TINYC__
- .int 0xe92d4030
- .int 0xee070fba
- .int 0xe5d03000
- .int 0xe24dd014
- .int 0xe1a05000
- .int 0xe2533000
- .int 0xe1a04001
- .int 0x13a03001
- .int 0xee070fba
- .int 0xe5cd300f
- .int 0xe3a03001
- .int 0xe1a02003
- .int 0xe28d100f
- .int 0xe1a00005
- .int 0xe58d4004
- .int 0xe58d4000
- .int 0xeb000009
- .int 0xe3500000
- .int 0x0afffff6
- .int 0xe5dd000f
- .int 0xe28dd014
- .int 0xe8bd8030
-#else
- push {r4, r5, lr}
- mcr p15, 0, r0, c7, c10, 5
- ldrb r3, [r0]
- sub sp, sp, #20
- mov r5, r0
- subs r3, r3, #0
- mov r4, r1
- movne r3, #1
- mcr p15, 0, r0, c7, c10, 5
- strb r3, [sp, #15]
-.L20:
- mov r3, #1
- mov r2, r3
- add r1, sp, #15
- mov r0, r5
- str r4, [sp, #4]
- str r4, [sp]
- bl __atomic_compare_exchange_1
- cmp r0, #0
- beq .L20
- ldrb r0, [sp, #15]
- add sp, sp, #20
- pop {r4, r5, pc}
-#endif
- .size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
-
- .global _(__atomic_clear)
- .type _(__atomic_clear), %function
-_(__atomic_clear):
-#ifdef __TINYC__
- .int 0xe3a03000
- .int 0xee070fba
- .int 0xe5c03000
- .int 0xee070fba
- .int 0xe12fff1e
-#else
- mov r3, #0
- mcr p15, 0, r0, c7, c10, 5
- strb r3, [r0]
- mcr p15, 0, r0, c7, c10, 5
- bx lr
-#endif
- .size _(__atomic_clear), .-_(__atomic_clear)
-
- .global _(__atomic_compare_exchange_1)
- .type _(__atomic_compare_exchange_1), %function
-_(__atomic_compare_exchange_1):
-#ifdef __TINYC__
- .int 0xe52de004
- .int 0xe5d13000
- .int 0xf57ff05b
- .int 0xe1d0cf9f
- .int 0xe15c0003
- .int 0x1a000002
- .int 0xe1c0ef92
- .int 0xe35e0000
- .int 0x1afffff9
- .int 0x03a00001
- .int 0x13a00000
- .int 0xf57ff05b
- .int 0x15c1c000
- .int 0xe49df004
-#else
- str lr, [sp, #-4]!
- ldrb r3, [r1]
- mcr p15, 0, r0, c7, c10, 5
-.L1:
- ldrexb ip, [r0]
- cmp ip, r3
- bne .L2
- strexb lr, r2, [r0]
- cmp lr, #0
- bne .L1
-.L2:
- mcr p15, 0, r0, c7, c10, 5
- moveq r0, #1
- movne r0, #0
- strbne ip, [r1]
- ldr pc, [sp], #4
-#endif
- .size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1)
-
- .global _(__atomic_compare_exchange_2)
- .type _(__atomic_compare_exchange_2), %function
-_(__atomic_compare_exchange_2):
-#ifdef __TINYC__
- .int 0xe52de004
- .int 0xe1d130b0
- .int 0xf57ff05b
- .int 0xe1f0cf9f
- .int 0xe15c0003
- .int 0x1a000002
- .int 0xe1e0ef92
- .int 0xe35e0000
- .int 0x1afffff9
- .int 0x03a00001
- .int 0x13a00000
- .int 0xf57ff05b
- .int 0x11c1c0b0
- .int 0xe49df004
-#else
- str lr, [sp, #-4]!
- ldrh r3, [r1]
- mcr p15, 0, r0, c7, c10, 5
-.L3:
- ldrexh ip, [r0]
- cmp ip, r3
- bne .L4
- strexh lr, r2, [r0]
- cmp lr, #0
- bne .L3
-.L4:
- mcr p15, 0, r0, c7, c10, 5
- moveq r0, #1
- movne r0, #0
- strhne ip, [r1]
- ldr pc, [sp], #4
-#endif
- .size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2)
-
- .global _(__atomic_compare_exchange_4)
- .type _(__atomic_compare_exchange_4), %function
-_(__atomic_compare_exchange_4):
-#ifdef __TINYC__
- .int 0xe52de004
- .int 0xe5913000
- .int 0xf57ff05b
- .int 0xe190cf9f
- .int 0xe15c0003
- .int 0x1a000002
- .int 0xe180ef92
- .int 0xe35e0000
- .int 0x1afffff9
- .int 0x03a00001
- .int 0x13a00000
- .int 0xf57ff05b
- .int 0x1581c000
- .int 0xe49df004
-#else
- str lr, [sp, #-4]!
- ldr r3, [r1]
- mcr p15, 0, r0, c7, c10, 5
-.L5:
- ldrex ip, [r0]
- cmp ip, r3
- bne .L6
- strex lr, r2, [r0]
- cmp lr, #0
- bne .L5
-.L6:
- mcr p15, 0, r0, c7, c10, 5
- moveq r0, #1
- movne r0, #0
- strne ip, [r1]
- ldr pc, [sp], #4
-#endif
- .size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4)
-
-/* ---------------------------------------------- */
-#elif defined __aarch64__
-
- .text
- .align 2
-
- .global _(fetch_and_add_arm64)
- .type _(fetch_and_add_arm64), %function
-_(fetch_and_add_arm64):
-#ifdef __TINYC__
- .int 0x885f7c02
- .int 0x0b010042
- .int 0x8803fc02
- .int 0x35ffffa3
- .int 0xd5033bbf
- .int 0xd65f03c0
-#else
- ldxr w2, [x0]
- add w2, w2, w1
- stlxr w3, w2, [x0]
- cbnz w3, _(fetch_and_add_arm64)
- dmb ish
- ret
-#endif
- .size _(fetch_and_add_arm64), .-_(fetch_and_add_arm64)
-
- .global _(__atomic_test_and_set)
- .type _(__atomic_test_and_set), %function
-_(__atomic_test_and_set):
-#ifdef __TINYC__
- .int 0xa9bf7bfd
- .int 0xaa0003e1
- .int 0x52800020
- .int 0x910003fd
- .int 0x2a0003f0
- .int 0x085ffc20
- .int 0x0811fc30
- .int 0x35ffffd1
- .int 0xa8c17bfd
- .int 0xd65f03c0
-#else
- stp x29, x30, [sp, -16]!
- mov x1, x0
- mov w0, 1
- mov x29, sp
- mov w16, w0
-.L20:
- ldaxrb w0, [x1]
- stlxrb w17, w16, [x1]
- cbnz w17, .L20
- ldp x29, x30, [sp], 16
- ret
-#endif
- .size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
-
- .global _(__atomic_clear)
- .type _(__atomic_clear), %function
-_(__atomic_clear):
-#ifdef __TINYC__
- .int 0x089ffc1f
- .int 0xd65f03c0
-#else
- stlrb wzr, [x0]
- ret
-#endif
- .size _(__atomic_clear), .-_(__atomic_clear)
-
- .global _(__atomic_compare_exchange_1)
- .type _(__atomic_compare_exchange_1), %function
-_(__atomic_compare_exchange_1):
-#ifdef __TINYC__
- .int 0xa9be7bfd
- .int 0x910003fd
- .int 0xa90153f3
- .int 0xaa0103f3
- .int 0x12001c41
- .int 0xaa0003e2
- .int 0x39400274
- .int 0x2a1403e0
- .int 0x53001c10
- .int 0x085ffc40
- .int 0x6b10001f
- .int 0x54000061
- .int 0x0811fc41
- .int 0x35ffff91
- .int 0x6b34001f
- .int 0x1a9f17e1
- .int 0x54000040
- .int 0x39000260
- .int 0x2a0103e0
- .int 0xa94153f3
- .int 0xa8c27bfd
- .int 0xd65f03c0
-#else
- stp x29, x30, [sp, -32]!
- mov x29, sp
- stp x19, x20, [sp, 16]
- mov x19, x1
- and w1, w2, 255
- mov x2, x0
- ldrb w20, [x19]
- mov w0, w20
- uxtb w16, w0
-.L1:
- ldaxrb w0, [x2]
- cmp w0, w16
- b.ne .L2
- stlxrb w17, w1, [x2]
- cbnz w17, .L1
-.L2:
- cmp w0, w20, uxtb
- cset w1, eq
- beq .L3
- strb w0, [x19]
-.L3:
- mov w0, w1
- ldp x19, x20, [sp, 16]
- ldp x29, x30, [sp], 32
- ret
-#endif
- .size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1)
-
- .global _(__atomic_compare_exchange_2)
- .type _(__atomic_compare_exchange_2), %function
-_(__atomic_compare_exchange_2):
-#ifdef __TINYC__
- .int 0xa9be7bfd
- .int 0x910003fd
- .int 0xa90153f3
- .int 0xaa0103f3
- .int 0x12003c41
- .int 0xaa0003e2
- .int 0x79400274
- .int 0x2a1403e0
- .int 0x53003c10
- .int 0x485ffc40
- .int 0x6b10001f
- .int 0x54000061
- .int 0x4811fc41
- .int 0x35ffff91
- .int 0x6b34201f
- .int 0x1a9f17e1
- .int 0x54000040
- .int 0x79000260
- .int 0x2a0103e0
- .int 0xa94153f3
- .int 0xa8c27bfd
- .int 0xd65f03c0
-#else
- stp x29, x30, [sp, -32]!
- mov x29, sp
- stp x19, x20, [sp, 16]
- mov x19, x1
- and w1, w2, 65535
- mov x2, x0
- ldrh w20, [x19]
- mov w0, w20
- uxth w16, w0
-.L4:
- ldaxrh w0, [x2]
- cmp w0, w16
- b.ne .L5
- stlxrh w17, w1, [x2]
- cbnz w17, .L4
-.L5:
- cmp w0, w20, uxth
- cset w1, eq
- beq .L6
- strh w0, [x19]
-.L6:
- mov w0, w1
- ldp x19, x20, [sp, 16]
- ldp x29, x30, [sp], 32
- ret
-#endif
- .size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2)
-
- .global _(__atomic_compare_exchange_4)
- .type _(__atomic_compare_exchange_4), %function
-_(__atomic_compare_exchange_4):
-#ifdef __TINYC__
- .int 0xa9be7bfd
- .int 0x910003fd
- .int 0xa90153f3
- .int 0xaa0103f3
- .int 0x2a0203e1
- .int 0xaa0003e2
- .int 0xb9400274
- .int 0x2a1403e0
- .int 0x2a0003f0
- .int 0x885ffc40
- .int 0x6b10001f
- .int 0x54000061
- .int 0x8811fc41
- .int 0x35ffff91
- .int 0x6b14001f
- .int 0x1a9f17e1
- .int 0x54000040
- .int 0xb9000260
- .int 0x2a0103e0
- .int 0xa94153f3
- .int 0xa8c27bfd
- .int 0xd65f03c0
-#else
- stp x29, x30, [sp, -32]!
- mov x29, sp
- stp x19, x20, [sp, 16]
- mov x19, x1
- mov w1, w2
- mov x2, x0
- ldr w20, [x19]
- mov w0, w20
- mov w16, w0
-.L7:
- ldaxr w0, [x2]
- cmp w0, w16
- b.ne .L8
- stlxr w17, w1, [x2]
- cbnz w17, .L7
-.L8:
- cmp w0, w20
- cset w1, eq
- beq .L9
- str w0, [x19]
-.L9:
- mov w0, w1
- ldp x19, x20, [sp, 16]
- ldp x29, x30, [sp], 32
- ret
-#endif
- .size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4)
-
- .global _(__atomic_compare_exchange_8)
- .type _(__atomic_compare_exchange_8), %function
-_(__atomic_compare_exchange_8):
-#ifdef __TINYC__
- .int 0xa9be7bfd
- .int 0x910003fd
- .int 0xa90153f3
- .int 0xaa0103f3
- .int 0xaa0203e1
- .int 0xaa0003e2
- .int 0xf9400274
- .int 0xaa1403e0
- .int 0xaa0003f0
- .int 0xc85ffc40
- .int 0xeb10001f
- .int 0x54000061
- .int 0xc811fc41
- .int 0x35ffff91
- .int 0xeb14001f
- .int 0x1a9f17e1
- .int 0x54000040
- .int 0xf9000260
- .int 0x2a0103e0
- .int 0xa94153f3
- .int 0xa8c27bfd
- .int 0xd65f03c0
-#else
- stp x29, x30, [sp, -32]!
- mov x29, sp
- stp x19, x20, [sp, 16]
- mov x19, x1
- mov x1, x2
- mov x2, x0
- ldr x20, [x19]
- mov x0, x20
- mov x16, x0
-.L10:
- ldaxr x0, [x2]
- cmp x0, x16
- b.ne .L11
- stlxr w17, x1, [x2]
- cbnz w17, .L10
-.L11:
- cmp x0, x20
- cset w1, eq
- beq .L12
- str x0, [x19]
-.L12:
- mov w0, w1
- ldp x19, x20, [sp, 16]
- ldp x29, x30, [sp], 32
- ret
-#endif
- .size _(__atomic_compare_exchange_8), .-_(__atomic_compare_exchange_8)
-
-/* ---------------------------------------------- */
-#elif defined __riscv
-
- .text
- .align 2
-
- .global _(fetch_and_add_riscv64)
- .type _(fetch_and_add_riscv64), %function
-_(fetch_and_add_riscv64):
-#ifdef __TINYC__
- .int 0x0f50000f
- .int 0x004b5202f
- .short 0x8082
-#else
- fence iorw,ow
- amoadd.w.aq zero,a1,0(a0)
- ret
-#endif
- .size _(fetch_and_add_riscv64), .-_(fetch_and_add_riscv64)
-
- .global _(__atomic_test_and_set)
- .type _(__atomic_test_and_set), %function
-_(__atomic_test_and_set):
-#ifdef __TINYC__
- .int 0x00357793
- .int 0x0037979b
- .short 0x4685
- .short 0x9971
- .int 0x00f696bb
- .int 0x0f50000f
- .int 0x44d5272f
- .int 0x00f7553b
- .int 0x0ff57513
- .short 0x8082
-#else
- andi a5,a0,3
- slliw a5,a5,3
- li a3,1
- andi a0,a0,-4
- sllw a3,a3,a5
- fence iorw,ow; amoor.w.aq a4,a3,0(a0)
- srlw a0,a4,a5
- andi a0,a0,0xff
- ret
-#endif
- .size _(__atomic_test_and_set), .-_(__atomic_test_and_set)
-
- .global _(__atomic_clear)
- .type _(__atomic_clear), %function
-_(__atomic_clear):
-#ifdef __TINYC__
- .int 0x0ff0000f
- .int 0x00050023
- .int 0x0ff0000f
- .short 0x8082
-#else
- fence iorw,iorw
- sb zero,0(a0)
- fence iorw,iorw
- ret
-#endif
- .size _(__atomic_clear), .-_(__atomic_clear)
-
- .global _(__atomic_compare_exchange_1)
- .type _(__atomic_compare_exchange_1), %function
-_(__atomic_compare_exchange_1):
-#ifdef __TINYC__
- .short 0x1141
- .short 0x86ba
- .short 0x873e
- .short 0xe406
- .int 0x0ff0000f
- .int 0x0005c803
- .int 0xff857893
- .int 0x0008b783
- .short 0x891d
- .short 0x050e
- .int 0x0ff00693
- .int 0x00a696b3
- .int 0x00a81833
- .int 0x00a61633
- .int 0xfff6c713
- .short 0x8f7d
- .int 0x00f6f333
- .short 0x8f51
- .int 0x03031263
- .int 0x1008b32f
- .int 0x00f31663
- .int 0x18e8be2f
- .int 0xfe0e1ae3
- .int 0x40f30733
- .short 0x879a
- .short 0xff69
- .int 0x0ff0000f
- .short 0x4505
- .short 0xa801
- .int 0x00a7d7b3
- .int 0x00f58023
- .int 0x0ff0000f
- .short 0x4501
- .short 0x60a2
- .short 0x0141
- .short 0x8082
-#else
- addi sp,sp,-16
- mv a3,a4
- mv a4,a5
- sd ra,8(sp)
- fence
- lbu a6,0(a1)
- andi a7,a0,-8
- ld a5,0(a7)
- andi a0,a0,7
- slli a0,a0,0x3
- li a3,255
- sll a3,a3,a0
- sll a6,a6,a0
- sll a2,a2,a0
-.L1:
- not a4,a3
- and a4,a4,a5
- and t1,a3,a5
- or a4,a4,a2
- bne t1,a6,.L4
-.L2:
- lr.d t1,(a7)
- bne t1,a5,.L3
- sc.d t3,a4,(a7)
- bnez t3,.L2
-.L3:
- sub a4,t1,a5
- mv a5,t1
- bnez a4,.L1
- fence
- li a0,1
- j .L5
-.L4:
- srl a5,a5,a0
- sb a5,0(a1)
- fence
- li a0,0
-.L5:
- ld ra,8(sp)
- addi sp,sp,16
- jr ra
-#endif
- .size _(__atomic_compare_exchange_1), .-_(__atomic_compare_exchange_1)
-
- .global _(__atomic_compare_exchange_2)
- .type _(__atomic_compare_exchange_2), %function
-_(__atomic_compare_exchange_2):
-#ifdef __TINYC__
- .short 0x1141
- .short 0x86ba
- .short 0x873e
- .short 0xe406
- .int 0x0ff0000f
- .int 0x0005d803
- .int 0xff857893
- .short 0x67c1
- .short 0x891d
- .int 0x0008b703
- .short 0x050e
- .short 0x17fd
- .int 0x00a797b3
- .int 0x00a81833
- .int 0x00a61633
- .int 0xfff7c693
- .short 0x8ef9
- .int 0x00e7f333
- .short 0x8ed1
- .int 0x03031263
- .int 0x1008b32f
- .int 0x00e31663
- .int 0x18d8be2f
- .int 0xfe0e1ae3
- .int 0x40e306b3
- .short 0x871a
- .short 0xfee9
- .int 0x0ff0000f
- .short 0x4505
- .short 0xa801
- .int 0x00a75733
- .int 0x00e59023
- .int 0x0ff0000f
- .short 0x4501
- .short 0x60a2
- .short 0x0141
- .short 0x8082
-#else
- addi sp,sp,-16
- mv a3,a4
- mv a4,a5
- sd ra,8(sp)
- fence
- lhu a6,0(a1)
- andi a7,a0,-8
- lui a5,0x10
- andi a0,a0,7
- ld a4,0(a7)
- slli a0,a0,0x3
- addi a5,a5,-1
- sll a5,a5,a0
- sll a6,a6,a0
- sll a2,a2,a0
-.L6:
- not a3,a5
- and a3,a3,a4
- and t1,a5,a4
- or a3,a3,a2
- bne t1,a6,.L9
-.L7:
- lr.d t1,(a7)
- bne t1,a4,.L8
- sc.d t3,a3,(a7)
- bnez t3,.L7
-.L8:
- sub a3,t1,a4
- mv a4,t1
- bnez a3,.L6
- fence
- li a0,1
- j .L10
-.L9:
- srl a4,a4,a0
- sh a4,0(a1)
- fence
- li a0,0
-.L10:
- ld ra,8(sp)
- addi sp,sp,16
- jr ra
-#endif
- .size _(__atomic_compare_exchange_2), .-_(__atomic_compare_exchange_2)
-
- .global _(__atomic_compare_exchange_4)
- .type _(__atomic_compare_exchange_4), %function
-_(__atomic_compare_exchange_4):
-#ifdef __TINYC__
- .short 0x419c
- .int 0x0f50000f
- .int 0x1405272f
- .int 0x00f71663
- .int 0x1cc5282f
- .int 0xfe081ae3
- .int 0x40f707bb
- .int 0x0017b513
- .short 0xc391
- .short 0xc198
- .short 0x8905
- .short 0x8082
-#else
- lw a5,0(a1)
- fence iorw,ow;
-.L11:
- lr.w.aq a4,0(a0)
- bne a4,a5,.L12
- sc.w.aq a6,a2,0(a0)
- bnez a6,.L11
-.L12:
- subw a5,a4,a5
- seqz a0,a5
- beq a5,zero,.L13
- sw a4,0(a1)
-.L13:
- andi a0,a0,1
- ret
-#endif
- .size _(__atomic_compare_exchange_4), .-_(__atomic_compare_exchange_4)
-
- .global _(__atomic_compare_exchange_8)
- .type _(__atomic_compare_exchange_8), %function
-_(__atomic_compare_exchange_8):
-#ifdef __TINYC__
- .short 0x619c
- .int 0x0f50000f
- .int 0x1405372f
- .int 0x00f71563
- .int 0x1cc536af
- .short 0xfaf5
- .int 0x40f707b3
- .int 0x0017b513
- .short 0xc391
- .short 0xe198
- .short 0x8905
- .short 0x8082
-#else
- ld a5,0(a1)
- fence iorw,ow;
-.L14:
- lr.d.aq a4,0(a0)
- bne a4,a5,.L15
- sc.d.aq a3,a2,0(a0)
- bnez a3,.L14
-.L15:
- sub a5,a4,a5
- seqz a0,a5
- beq a5,zero,.L16
- sd a4,0(a1)
-.L16:
- andi a0,a0,1
- ret
-#endif
- .size _(__atomic_compare_exchange_8), .-_(__atomic_compare_exchange_8)
-
-/* ---------------------------------------------- */
-#endif
diff --git a/tinycc/lib/bcheck.c b/tinycc/lib/bcheck.c
deleted file mode 100644
index b8dd1c5..0000000
--- a/tinycc/lib/bcheck.c
+++ /dev/null
@@ -1,2270 +0,0 @@
-/*
- * Tiny C Memory and bounds checker
- *
- * Copyright (c) 2002 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <setjmp.h>
-
-#if !defined(__FreeBSD__) \
- && !defined(__FreeBSD_kernel__) \
- && !defined(__DragonFly__) \
- && !defined(__OpenBSD__) \
- && !defined(__APPLE__) \
- && !defined(__NetBSD__)
-#include <malloc.h>
-#endif
-
-#if !defined(_WIN32)
-#include <unistd.h>
-#include <sys/syscall.h>
-#endif
-
-#define BOUND_DEBUG (1)
-#define BOUND_STATISTIC (1)
-
-#if BOUND_DEBUG
- #define dprintf(a...) if (print_calls) fprintf(a)
-#else
- #define dprintf(a...)
-#endif
-
-#ifdef __attribute__
- /* an __attribute__ macro is defined in the system headers */
- #undef __attribute__
-#endif
-#define FASTCALL __attribute__((regparm(3)))
-
-#ifdef _WIN32
-# define DLL_EXPORT __declspec(dllexport)
-#else
-# define DLL_EXPORT
-#endif
-
-#if defined(__FreeBSD__) \
- || defined(__FreeBSD_kernel__) \
- || defined(__DragonFly__) \
- || defined(__OpenBSD__) \
- || defined(__NetBSD__) \
- || defined(__dietlibc__)
-
-#include <sys/mman.h>
-#define INIT_SEM()
-#define EXIT_SEM()
-#define WAIT_SEM()
-#define POST_SEM()
-#define TRY_SEM()
-#define HAVE_MEMALIGN (0)
-#define MALLOC_REDIR (0)
-#define HAVE_PTHREAD_CREATE (0)
-#define HAVE_CTYPE (0)
-#define HAVE_ERRNO (0)
-#define HAVE_SIGNAL (0)
-#define HAVE_SIGACTION (0)
-#define HAVE_FORK (0)
-#define HAVE_TLS_FUNC (0)
-#define HAVE_TLS_VAR (0)
-
-#elif defined(_WIN32)
-
-#include <windows.h>
-#include <signal.h>
-static CRITICAL_SECTION bounds_sem;
-#define INIT_SEM() InitializeCriticalSection(&bounds_sem)
-#define EXIT_SEM() DeleteCriticalSection(&bounds_sem)
-#define WAIT_SEM() EnterCriticalSection(&bounds_sem)
-#define POST_SEM() LeaveCriticalSection(&bounds_sem)
-#define TRY_SEM() TryEnterCriticalSection(&bounds_sem)
-#define HAVE_MEMALIGN (0)
-#define MALLOC_REDIR (0)
-#define HAVE_PTHREAD_CREATE (0)
-#define HAVE_CTYPE (0)
-#define HAVE_ERRNO (0)
-#define HAVE_SIGNAL (1)
-#define HAVE_SIGACTION (0)
-#define HAVE_FORK (0)
-#define HAVE_TLS_FUNC (1)
-#define HAVE_TLS_VAR (0)
-
-#else
-
-#define __USE_GNU /* get RTLD_NEXT */
-#include <sys/mman.h>
-#include <ctype.h>
-#include <pthread.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <signal.h>
-#ifdef __APPLE__
-#include <dispatch/dispatch.h>
-static dispatch_semaphore_t bounds_sem;
-#define INIT_SEM() bounds_sem = dispatch_semaphore_create(1)
-#define EXIT_SEM() dispatch_release(*(dispatch_object_t*)&bounds_sem)
-#define WAIT_SEM() if (use_sem) dispatch_semaphore_wait(bounds_sem, DISPATCH_TIME_FOREVER)
-#define POST_SEM() if (use_sem) dispatch_semaphore_signal(bounds_sem)
-#define TRY_SEM() if (use_sem) dispatch_semaphore_wait(bounds_sem, DISPATCH_TIME_NOW)
-#elif 0
-#include <semaphore.h>
-static sem_t bounds_sem;
-#define INIT_SEM() sem_init (&bounds_sem, 0, 1)
-#define EXIT_SEM() sem_destroy (&bounds_sem)
-#define WAIT_SEM() if (use_sem) while (sem_wait (&bounds_sem) < 0 \
- && errno == EINTR)
-#define POST_SEM() if (use_sem) sem_post (&bounds_sem)
-#define TRY_SEM() if (use_sem) while (sem_trywait (&bounds_sem) < 0 \
- && errno == EINTR)
-#elif 0
-static pthread_mutex_t bounds_mtx;
-#define INIT_SEM() pthread_mutex_init (&bounds_mtx, NULL)
-#define EXIT_SEM() pthread_mutex_destroy (&bounds_mtx)
-#define WAIT_SEM() if (use_sem) pthread_mutex_lock (&bounds_mtx)
-#define POST_SEM() if (use_sem) pthread_mutex_unlock (&bounds_mtx)
-#define TRY_SEM() if (use_sem) pthread_mutex_trylock (&bounds_mtx)
-#else
-static pthread_spinlock_t bounds_spin;
-/* about 25% faster then semaphore. */
-#define INIT_SEM() pthread_spin_init (&bounds_spin, 0)
-#define EXIT_SEM() pthread_spin_destroy (&bounds_spin)
-#define WAIT_SEM() if (use_sem) pthread_spin_lock (&bounds_spin)
-#define POST_SEM() if (use_sem) pthread_spin_unlock (&bounds_spin)
-#define TRY_SEM() if (use_sem) pthread_spin_trylock (&bounds_spin)
-#endif
-#define HAVE_MEMALIGN (1)
-#define MALLOC_REDIR (1)
-#define HAVE_PTHREAD_CREATE (1)
-#define HAVE_CTYPE (1)
-#define HAVE_ERRNO (1)
-#define HAVE_SIGNAL (1)
-#define HAVE_SIGACTION (1)
-#define HAVE_FORK (1)
-#if !defined(__APPLE__) && defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-#define HAVE_TLS_FUNC (0)
-#define HAVE_TLS_VAR (1)
-#else
-#define HAVE_TLS_FUNC (1)
-#define HAVE_TLS_VAR (0)
-#endif
-#if defined TCC_MUSL || defined __ANDROID__
-# undef HAVE_CTYPE
-#endif
-#endif
-
-#if MALLOC_REDIR
-static void *(*malloc_redir) (size_t);
-static void *(*calloc_redir) (size_t, size_t);
-static void (*free_redir) (void *);
-static void *(*realloc_redir) (void *, size_t);
-static unsigned int pool_index;
-static unsigned char __attribute__((aligned(16))) initial_pool[256];
-#endif
-#if HAVE_MEMALIGN
-static void *(*memalign_redir) (size_t, size_t);
-#endif
-#if HAVE_PTHREAD_CREATE
-static int (*pthread_create_redir) (pthread_t *thread,
- const pthread_attr_t *attr,
- void *(*start_routine)(void *), void *arg);
-#endif
-#if HAVE_SIGNAL
-typedef void (*bound_sig)(int);
-static bound_sig (*signal_redir) (int signum, bound_sig handler);
-#endif
-#if HAVE_SIGACTION
-static int (*sigaction_redir) (int signum, const struct sigaction *act,
- struct sigaction *oldact);
-#endif
-#if HAVE_FORK
-static int (*fork_redir) (void);
-#endif
-
-#define TCC_TYPE_NONE (0)
-#define TCC_TYPE_MALLOC (1)
-#define TCC_TYPE_CALLOC (2)
-#define TCC_TYPE_REALLOC (3)
-#define TCC_TYPE_MEMALIGN (4)
-#define TCC_TYPE_STRDUP (5)
-
-/* this pointer is generated when bound check is incorrect */
-#define INVALID_POINTER ((void *)(-2))
-
-typedef struct tree_node Tree;
-struct tree_node {
- Tree * left, * right;
- size_t start;
- size_t size;
- unsigned char type;
- unsigned char is_invalid; /* true if pointers outside region are invalid */
-};
-
-typedef struct alloca_list_struct {
- size_t fp;
- void *p;
- size_t size;
- struct alloca_list_struct *next;
-} alloca_list_type;
-
-#if defined(_WIN32)
-#define BOUND_TID_TYPE DWORD
-#define BOUND_GET_TID(id) id = GetCurrentThreadId()
-#elif defined(__OpenBSD__)
-#define BOUND_TID_TYPE pid_t
-#define BOUND_GET_TID(id) id = getthrid()
-#elif defined(__FreeBSD__)
-#define BOUND_TID_TYPE pid_t
-#define BOUND_GET_TID(id) syscall (SYS_thr_self, &id)
-#elif defined(__NetBSD__)
-#define BOUND_TID_TYPE pid_t
-#define BOUND_GET_TID(id) id = syscall (SYS__lwp_self)
-#elif defined(__linux__)
-#define BOUND_TID_TYPE pid_t
-#define BOUND_GET_TID(id) id = syscall (SYS_gettid)
-#else
-#define BOUND_TID_TYPE int
-#define BOUND_GET_TID(id) id = 0
-#endif
-
-typedef struct jmp_list_struct {
- void *penv;
- size_t fp;
- size_t end_fp;
- BOUND_TID_TYPE tid;
- struct jmp_list_struct *next;
-} jmp_list_type;
-
-#define BOUND_STATISTIC_SPLAY (0)
-static Tree * splay (size_t addr, Tree *t);
-static Tree * splay_end (size_t addr, Tree *t);
-static Tree * splay_insert(size_t addr, size_t size, Tree * t);
-static Tree * splay_delete(size_t addr, Tree *t);
-void splay_printtree(Tree * t, int d);
-
-/* external interface */
-void __bounds_checking (int no_check);
-void __bound_checking_lock (void);
-void __bound_checking_unlock (void);
-void __bound_never_fatal (int no_check);
-DLL_EXPORT void * __bound_ptr_add(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir1(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir2(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir4(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir8(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir12(void *p, size_t offset);
-DLL_EXPORT void * __bound_ptr_indir16(void *p, size_t offset);
-DLL_EXPORT void FASTCALL __bound_local_new(void *p1);
-DLL_EXPORT void FASTCALL __bound_local_delete(void *p1);
-void __bound_init(size_t *, int);
-void __bound_main_arg(int argc, char **argv, char **envp);
-void __bound_exit(void);
-void __bound_exit_dll(size_t *);
-#if !defined(_WIN32)
-void *__bound_mmap (void *start, size_t size, int prot, int flags, int fd,
- off_t offset);
-int __bound_munmap (void *start, size_t size);
-DLL_EXPORT void __bound_siglongjmp(jmp_buf env, int val);
-#endif
-DLL_EXPORT void __bound_new_region(void *p, size_t size);
-DLL_EXPORT void __bound_setjmp(jmp_buf env);
-DLL_EXPORT void __bound_longjmp(jmp_buf env, int val);
-DLL_EXPORT void *__bound_memcpy(void *dst, const void *src, size_t size);
-DLL_EXPORT int __bound_memcmp(const void *s1, const void *s2, size_t size);
-DLL_EXPORT void *__bound_memmove(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__bound_memset(void *dst, int c, size_t size);
-DLL_EXPORT int __bound_strlen(const char *s);
-DLL_EXPORT char *__bound_strcpy(char *dst, const char *src);
-DLL_EXPORT char *__bound_strncpy(char *dst, const char *src, size_t n);
-DLL_EXPORT int __bound_strcmp(const char *s1, const char *s2);
-DLL_EXPORT int __bound_strncmp(const char *s1, const char *s2, size_t n);
-DLL_EXPORT char *__bound_strcat(char *dest, const char *src);
-DLL_EXPORT char *__bound_strncat(char *dest, const char *src, size_t n);
-DLL_EXPORT char *__bound_strchr(const char *string, int ch);
-DLL_EXPORT char *__bound_strrchr(const char *string, int ch);
-DLL_EXPORT char *__bound_strdup(const char *s);
-
-#if defined(__arm__) && defined(__ARM_EABI__)
-DLL_EXPORT void *__bound___aeabi_memcpy(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__bound___aeabi_memmove(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__bound___aeabi_memmove4(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__bound___aeabi_memmove8(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__bound___aeabi_memset(void *dst, int c, size_t size);
-DLL_EXPORT void *__aeabi_memcpy(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__aeabi_memmove(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__aeabi_memmove4(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__aeabi_memmove8(void *dst, const void *src, size_t size);
-DLL_EXPORT void *__aeabi_memset(void *dst, int c, size_t size);
-#endif
-
-#if MALLOC_REDIR
-#define BOUND_MALLOC(a) malloc_redir(a)
-#define BOUND_MEMALIGN(a,b) memalign_redir(a,b)
-#define BOUND_FREE(a) free_redir(a)
-#define BOUND_REALLOC(a,b) realloc_redir(a,b)
-#define BOUND_CALLOC(a,b) calloc_redir(a,b)
-#else
-#define BOUND_MALLOC(a) malloc(a)
-#define BOUND_MEMALIGN(a,b) memalign(a,b)
-#define BOUND_FREE(a) free(a)
-#define BOUND_REALLOC(a,b) realloc(a,b)
-#define BOUND_CALLOC(a,b) calloc(a,b)
-DLL_EXPORT void *__bound_malloc(size_t size, const void *caller);
-DLL_EXPORT void *__bound_memalign(size_t size, size_t align, const void *caller);
-DLL_EXPORT void __bound_free(void *ptr, const void *caller);
-DLL_EXPORT void *__bound_realloc(void *ptr, size_t size, const void *caller);
-DLL_EXPORT void *__bound_calloc(size_t nmemb, size_t size);
-#endif
-
-#define FREE_REUSE_SIZE (100)
-static unsigned int free_reuse_index;
-static void *free_reuse_list[FREE_REUSE_SIZE];
-
-static Tree *tree = NULL;
-#define TREE_REUSE (1)
-#if TREE_REUSE
-static Tree *tree_free_list;
-#endif
-static alloca_list_type *alloca_list;
-static jmp_list_type *jmp_list;
-
-static unsigned char inited;
-static unsigned char print_warn_ptr_add;
-static unsigned char print_calls;
-static unsigned char print_heap;
-static unsigned char print_statistic;
-static unsigned char no_strdup;
-static unsigned char use_sem;
-static int never_fatal;
-#if HAVE_TLS_FUNC
-#if defined(_WIN32)
-static int no_checking = 0;
-static DWORD no_checking_key;
-#define NO_CHECKING_CHECK() if (!p) { \
- p = (int *) LocalAlloc(LPTR, sizeof(int)); \
- if (!p) bound_alloc_error("tls malloc"); \
- *p = 0; \
- TlsSetValue(no_checking_key, p); \
- }
-#define NO_CHECKING_GET() ({ int *p = TlsGetValue(no_checking_key); \
- NO_CHECKING_CHECK(); \
- *p; \
- })
-#define NO_CHECKING_SET(v) { int *p = TlsGetValue(no_checking_key); \
- NO_CHECKING_CHECK(); \
- *p = v; \
- }
-#else
-static int no_checking = 0;
-static pthread_key_t no_checking_key;
-#define NO_CHECKING_CHECK() if (!p) { \
- p = (int *) BOUND_MALLOC(sizeof(int)); \
- if (!p) bound_alloc_error("tls malloc"); \
- *p = 0; \
- pthread_setspecific(no_checking_key, p); \
- }
-#define NO_CHECKING_GET() ({ int *p = pthread_getspecific(no_checking_key); \
- NO_CHECKING_CHECK(); \
- *p; \
- })
-#define NO_CHECKING_SET(v) { int *p = pthread_getspecific(no_checking_key); \
- NO_CHECKING_CHECK(); \
- *p = v; \
- }
-#endif
-#elif HAVE_TLS_VAR
-static __thread int no_checking = 0;
-#define NO_CHECKING_GET() no_checking
-#define NO_CHECKING_SET(v) no_checking = v
-#else
-static int no_checking = 0;
-#define NO_CHECKING_GET() no_checking
-#define NO_CHECKING_SET(v) no_checking = v
-#endif
-static char exec[100];
-
-#if BOUND_STATISTIC
-static unsigned long long bound_ptr_add_count;
-static unsigned long long bound_ptr_indir1_count;
-static unsigned long long bound_ptr_indir2_count;
-static unsigned long long bound_ptr_indir4_count;
-static unsigned long long bound_ptr_indir8_count;
-static unsigned long long bound_ptr_indir12_count;
-static unsigned long long bound_ptr_indir16_count;
-static unsigned long long bound_local_new_count;
-static unsigned long long bound_local_delete_count;
-static unsigned long long bound_malloc_count;
-static unsigned long long bound_calloc_count;
-static unsigned long long bound_realloc_count;
-static unsigned long long bound_free_count;
-static unsigned long long bound_memalign_count;
-static unsigned long long bound_mmap_count;
-static unsigned long long bound_munmap_count;
-static unsigned long long bound_alloca_count;
-static unsigned long long bound_setjmp_count;
-static unsigned long long bound_longjmp_count;
-static unsigned long long bound_mempcy_count;
-static unsigned long long bound_memcmp_count;
-static unsigned long long bound_memmove_count;
-static unsigned long long bound_memset_count;
-static unsigned long long bound_strlen_count;
-static unsigned long long bound_strcpy_count;
-static unsigned long long bound_strncpy_count;
-static unsigned long long bound_strcmp_count;
-static unsigned long long bound_strncmp_count;
-static unsigned long long bound_strcat_count;
-static unsigned long long bound_strncat_count;
-static unsigned long long bound_strchr_count;
-static unsigned long long bound_strrchr_count;
-static unsigned long long bound_strdup_count;
-static unsigned long long bound_not_found;
-#define INCR_COUNT(x) ++x
-#else
-#define INCR_COUNT(x)
-#endif
-#if BOUND_STATISTIC_SPLAY
-static unsigned long long bound_splay;
-static unsigned long long bound_splay_end;
-static unsigned long long bound_splay_insert;
-static unsigned long long bound_splay_delete;
-#define INCR_COUNT_SPLAY(x) ++x
-#else
-#define INCR_COUNT_SPLAY(x)
-#endif
-
-int tcc_backtrace(const char *fmt, ...);
-
-/* print a bound error message */
-#define bound_warning(...) \
- do { \
- WAIT_SEM (); \
- tcc_backtrace("^bcheck.c^BCHECK: " __VA_ARGS__); \
- POST_SEM (); \
- } while (0)
-
-#define bound_error(...) \
- do { \
- bound_warning(__VA_ARGS__); \
- if (never_fatal == 0) \
- exit(255); \
- } while (0)
-
-static void bound_alloc_error(const char *s)
-{
- fprintf(stderr,"FATAL: %s\n",s);
- exit (1);
-}
-
-static void bound_not_found_warning(const char *file, const char *function,
- void *ptr)
-{
- dprintf(stderr, "%s%s, %s(): Not found %p\n", exec, file, function, ptr);
-}
-
-static void fetch_and_add(int* variable, int value)
-{
-#if defined __i386__ || defined __x86_64__
- __asm__ volatile("lock; addl %0, %1"
- : "+r" (value), "+m" (*variable) // input+output
- : // No input-only
- : "memory"
- );
-#elif defined __arm__
- extern void fetch_and_add_arm(int* variable, int value);
- fetch_and_add_arm(variable, value);
-#elif defined __aarch64__
- extern void fetch_and_add_arm64(int* variable, int value);
- fetch_and_add_arm64(variable, value);
-#elif defined __riscv
- extern void fetch_and_add_riscv64(int* variable, int value);
- fetch_and_add_riscv64(variable, value);
-#else
- *variable += value;
-#endif
-}
-
-/* enable/disable checking. This can be used in signal handlers. */
-void __bounds_checking (int no_check)
-{
-#if HAVE_TLS_FUNC || HAVE_TLS_VAR
- NO_CHECKING_SET(NO_CHECKING_GET() + no_check);
-#else
- fetch_and_add (&no_checking, no_check);
-#endif
-}
-
-void __bound_checking_lock(void)
-{
- WAIT_SEM ();
-}
-
-void __bound_checking_unlock(void)
-{
- POST_SEM ();
-}
-
-/* enable/disable checking. This can be used in signal handlers. */
-void __bound_never_fatal (int neverfatal)
-{
- fetch_and_add (&never_fatal, neverfatal);
-}
-
-/* return '(p + offset)' for pointer arithmetic (a pointer can reach
- the end of a region in this case */
-void * __bound_ptr_add(void *p, size_t offset)
-{
- size_t addr = (size_t)p;
-
- if (NO_CHECKING_GET())
- return p + offset;
-
- dprintf(stderr, "%s, %s(): %p 0x%lx\n",
- __FILE__, __FUNCTION__, p, (unsigned long)offset);
-
- WAIT_SEM ();
- INCR_COUNT(bound_ptr_add_count);
- if (tree) {
- addr -= tree->start;
- if (addr >= tree->size) {
- addr = (size_t)p;
- tree = splay (addr, tree);
- addr -= tree->start;
- }
- if (addr >= tree->size) {
- addr = (size_t)p;
- tree = splay_end (addr, tree);
- addr -= tree->start;
- }
- if (addr <= tree->size) {
- if (tree->is_invalid || addr + offset > tree->size) {
- POST_SEM ();
- if (print_warn_ptr_add)
- bound_warning("%p is outside of the region", p + offset);
- if (never_fatal <= 0)
- return INVALID_POINTER; /* return an invalid pointer */
- return p + offset;
- }
- }
- else if (p) { /* Allow NULL + offset. offsetoff is using it. */
- INCR_COUNT(bound_not_found);
- POST_SEM ();
- bound_not_found_warning (__FILE__, __FUNCTION__, p);
- return p + offset;
- }
- }
- POST_SEM ();
- return p + offset;
-}
-
-/* return '(p + offset)' for pointer indirection (the resulting must
- be strictly inside the region */
-#define BOUND_PTR_INDIR(dsize) \
-void * __bound_ptr_indir ## dsize (void *p, size_t offset) \
-{ \
- size_t addr = (size_t)p; \
- \
- if (NO_CHECKING_GET()) \
- return p + offset; \
- \
- dprintf(stderr, "%s, %s(): %p 0x%lx\n", \
- __FILE__, __FUNCTION__, p, (unsigned long)offset); \
- WAIT_SEM (); \
- INCR_COUNT(bound_ptr_indir ## dsize ## _count); \
- if (tree) { \
- addr -= tree->start; \
- if (addr >= tree->size) { \
- addr = (size_t)p; \
- tree = splay (addr, tree); \
- addr -= tree->start; \
- } \
- if (addr >= tree->size) { \
- addr = (size_t)p; \
- tree = splay_end (addr, tree); \
- addr -= tree->start; \
- } \
- if (addr <= tree->size) { \
- if (tree->is_invalid || addr + offset + dsize > tree->size) { \
- POST_SEM (); \
- bound_warning("%p is outside of the region", p + offset); \
- if (never_fatal <= 0) \
- return INVALID_POINTER; /* return an invalid pointer */ \
- return p + offset; \
- } \
- } \
- else { \
- INCR_COUNT(bound_not_found); \
- POST_SEM (); \
- bound_not_found_warning (__FILE__, __FUNCTION__, p); \
- return p + offset; \
- } \
- } \
- POST_SEM (); \
- return p + offset; \
-}
-
-BOUND_PTR_INDIR(1)
-BOUND_PTR_INDIR(2)
-BOUND_PTR_INDIR(4)
-BOUND_PTR_INDIR(8)
-BOUND_PTR_INDIR(12)
-BOUND_PTR_INDIR(16)
-
-/* Needed when using ...libtcc1-usegcc=yes in lib/Makefile */
-#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
-/*
- * At least gcc 6.2 complains when __builtin_frame_address is used with
- * nonzero argument.
- */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wframe-address"
-#endif
-
-/* return the frame pointer of the caller */
-#define GET_CALLER_FP(fp)\
-{\
- fp = (size_t)__builtin_frame_address(1);\
-}
-
-/* called when entering a function to add all the local regions */
-void FASTCALL __bound_local_new(void *p1)
-{
- size_t addr, fp, *p = p1;
-
- if (NO_CHECKING_GET())
- return;
- GET_CALLER_FP(fp);
- dprintf(stderr, "%s, %s(): p1=%p fp=%p\n",
- __FILE__, __FUNCTION__, p, (void *)fp);
- WAIT_SEM ();
- while ((addr = p[0])) {
- INCR_COUNT(bound_local_new_count);
- tree = splay_insert(addr + fp, p[1], tree);
- p += 2;
- }
- POST_SEM ();
-#if BOUND_DEBUG
- if (print_calls) {
- p = p1;
- while ((addr = p[0])) {
- dprintf(stderr, "%s, %s(): %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- (void *) (addr + fp), (unsigned long) p[1]);
- p += 2;
- }
- }
-#endif
-}
-
-/* called when leaving a function to delete all the local regions */
-void FASTCALL __bound_local_delete(void *p1)
-{
- size_t addr, fp, *p = p1;
-
- if (NO_CHECKING_GET())
- return;
- GET_CALLER_FP(fp);
- dprintf(stderr, "%s, %s(): p1=%p fp=%p\n",
- __FILE__, __FUNCTION__, p, (void *)fp);
- WAIT_SEM ();
- while ((addr = p[0])) {
- INCR_COUNT(bound_local_delete_count);
- tree = splay_delete(addr + fp, tree);
- p += 2;
- }
- if (alloca_list) {
- alloca_list_type *last = NULL;
- alloca_list_type *cur = alloca_list;
-
- do {
- if (cur->fp == fp) {
- if (last)
- last->next = cur->next;
- else
- alloca_list = cur->next;
- tree = splay_delete ((size_t) cur->p, tree);
- dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
- __FILE__, __FUNCTION__, cur->p);
- BOUND_FREE (cur);
- cur = last ? last->next : alloca_list;
- }
- else {
- last = cur;
- cur = cur->next;
- }
- } while (cur);
- }
- if (jmp_list) {
- jmp_list_type *last = NULL;
- jmp_list_type *cur = jmp_list;
-
- do {
- if (cur->fp == fp) {
- if (last)
- last->next = cur->next;
- else
- jmp_list = cur->next;
- dprintf(stderr, "%s, %s(): remove setjmp %p\n",
- __FILE__, __FUNCTION__, cur->penv);
- BOUND_FREE (cur);
- cur = last ? last->next : jmp_list;
- }
- else {
- last = cur;
- cur = cur->next;
- }
- } while (cur);
- }
-
- POST_SEM ();
-#if BOUND_DEBUG
- if (print_calls) {
- p = p1;
- while ((addr = p[0])) {
- if (addr != 1) {
- dprintf(stderr, "%s, %s(): %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- (void *) (addr + fp), (unsigned long) p[1]);
- }
- p+= 2;
- }
- }
-#endif
-}
-
-/* used by alloca */
-void __bound_new_region(void *p, size_t size)
-{
- size_t fp;
- alloca_list_type *last;
- alloca_list_type *cur;
- alloca_list_type *new;
-
- if (NO_CHECKING_GET())
- return;
-
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, p, (unsigned long)size);
- GET_CALLER_FP (fp);
- new = BOUND_MALLOC (sizeof (alloca_list_type));
- WAIT_SEM ();
- INCR_COUNT(bound_alloca_count);
- last = NULL;
- cur = alloca_list;
- while (cur) {
-#if defined(__i386__) || (defined(__arm__) && !defined(__ARM_EABI__))
- int align = 4;
-#elif defined(__arm__)
- int align = 8;
-#else
- int align = 16;
-#endif
- void *cure = (void *)((char *)cur->p + ((cur->size + align) & -align));
- void *pe = (void *)((char *)p + ((size + align) & -align));
- if (cur->fp == fp && ((cur->p <= p && cure > p) ||
- (p <= cur->p && pe > cur->p))) {
- if (last)
- last->next = cur->next;
- else
- alloca_list = cur->next;
- tree = splay_delete((size_t)cur->p, tree);
- break;
- }
- last = cur;
- cur = cur->next;
- }
- tree = splay_insert((size_t)p, size, tree);
- if (new) {
- new->fp = fp;
- new->p = p;
- new->size = size;
- new->next = alloca_list;
- alloca_list = new;
- }
- POST_SEM ();
- if (cur) {
- dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
- __FILE__, __FUNCTION__, cur->p);
- BOUND_FREE (cur);
- }
-}
-
-void __bound_setjmp(jmp_buf env)
-{
- jmp_list_type *jl;
- void *e = (void *) env;
-
- if (NO_CHECKING_GET() == 0) {
- dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, e);
- WAIT_SEM ();
- INCR_COUNT(bound_setjmp_count);
- jl = jmp_list;
- while (jl) {
- if (jl->penv == e)
- break;
- jl = jl->next;
- }
- if (jl == NULL) {
- jl = BOUND_MALLOC (sizeof (jmp_list_type));
- if (jl) {
- jl->penv = e;
- jl->next = jmp_list;
- jmp_list = jl;
- }
- }
- if (jl) {
- size_t fp;
-
- GET_CALLER_FP (fp);
- jl->fp = fp;
- jl->end_fp = (size_t)__builtin_frame_address(0);
- BOUND_GET_TID(jl->tid);
- }
- POST_SEM ();
- }
-}
-
-static void __bound_long_jump(jmp_buf env, int val, int sig, const char *func)
-{
- jmp_list_type *jl;
- void *e;
- BOUND_TID_TYPE tid;
-
- if (NO_CHECKING_GET() == 0) {
- e = (void *)env;
- BOUND_GET_TID(tid);
- dprintf(stderr, "%s, %s(): %p\n", __FILE__, func, e);
- WAIT_SEM();
- INCR_COUNT(bound_longjmp_count);
- jl = jmp_list;
- while (jl) {
- if (jl->penv == e && jl->tid == tid) {
- size_t start_fp = (size_t)__builtin_frame_address(0);
- size_t end_fp = jl->end_fp;
- jmp_list_type *cur = jmp_list;
- jmp_list_type *last = NULL;
-
- while (cur->penv != e || cur->tid != tid) {
- if (cur->tid == tid) {
- dprintf(stderr, "%s, %s(): remove setjmp %p\n",
- __FILE__, func, cur->penv);
- if (last)
- last->next = cur->next;
- else
- jmp_list = cur->next;
- BOUND_FREE (cur);
- cur = last ? last->next : jmp_list;
- }
- else {
- last = cur;
- cur = cur->next;
- }
- }
- for (;;) {
- Tree *t = tree;
- alloca_list_type *last;
- alloca_list_type *cur;
-
- while (t && (t->start < start_fp || t->start > end_fp))
- if (t->start < start_fp)
- t = t->right;
- else
- t = t->left;
- if (t == NULL)
- break;
- last = NULL;
- cur = alloca_list;
- while (cur) {
- if ((size_t) cur->p == t->start) {
- dprintf(stderr, "%s, %s(): remove alloca/vla %p\n",
- __FILE__, func, cur->p);
- if (last)
- last->next = cur->next;
- else
- alloca_list = cur->next;
- BOUND_FREE (cur);
- break;
- }
- last = cur;
- cur = cur->next;
- }
- dprintf(stderr, "%s, %s(): delete %p\n",
- __FILE__, func, (void *) t->start);
- tree = splay_delete(t->start, tree);
- }
- break;
- }
- jl = jl->next;
- }
- POST_SEM();
- }
-#if !defined(_WIN32)
- sig ? siglongjmp(env, val) :
-#endif
- longjmp (env, val);
-}
-
-void __bound_longjmp(jmp_buf env, int val)
-{
- __bound_long_jump(env,val, 0, __FUNCTION__);
-}
-
-#if !defined(_WIN32)
-void __bound_siglongjmp(jmp_buf env, int val)
-{
- __bound_long_jump(env,val, 1, __FUNCTION__);
-}
-#endif
-
-#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
-
-void __bound_init(size_t *p, int mode)
-{
- dprintf(stderr, "%s, %s(): start %s\n", __FILE__, __FUNCTION__,
- mode < 0 ? "lazy" : mode == 0 ? "normal use" : "for -run");
-
- if (inited) {
- WAIT_SEM();
- goto add_bounds;
- }
- inited = 1;
-
-#if HAVE_TLS_FUNC
-#if defined(_WIN32)
- no_checking_key = TlsAlloc();
- TlsSetValue(no_checking_key, &no_checking);
-#else
- pthread_key_create(&no_checking_key, NULL);
- pthread_setspecific(no_checking_key, &no_checking);
-#endif
-#endif
- NO_CHECKING_SET(1);
-
- print_warn_ptr_add = getenv ("TCC_BOUNDS_WARN_POINTER_ADD") != NULL;
- print_calls = getenv ("TCC_BOUNDS_PRINT_CALLS") != NULL;
- print_heap = getenv ("TCC_BOUNDS_PRINT_HEAP") != NULL;
- print_statistic = getenv ("TCC_BOUNDS_PRINT_STATISTIC") != NULL;
- never_fatal = getenv ("TCC_BOUNDS_NEVER_FATAL") != NULL;
-
- INIT_SEM ();
-
-#if MALLOC_REDIR
- {
- void *addr = mode > 0 ? RTLD_DEFAULT : RTLD_NEXT;
-
- /* tcc -run required RTLD_DEFAULT. Normal usage requires RTLD_NEXT,
- but using RTLD_NEXT with -run segfaults on MacOS in dyld as the
- generated code segment isn't registered with dyld and hence the
- caller image of dlsym isn't known to it */
- *(void **) (&malloc_redir) = dlsym (addr, "malloc");
- if (malloc_redir == NULL) {
- dprintf(stderr, "%s, %s(): use RTLD_DEFAULT\n",
- __FILE__, __FUNCTION__);
- addr = RTLD_DEFAULT;
- *(void **) (&malloc_redir) = dlsym (addr, "malloc");
- }
- *(void **) (&calloc_redir) = dlsym (addr, "calloc");
- *(void **) (&free_redir) = dlsym (addr, "free");
- *(void **) (&realloc_redir) = dlsym (addr, "realloc");
- *(void **) (&memalign_redir) = dlsym (addr, "memalign");
- dprintf(stderr, "%s, %s(): malloc_redir %p\n",
- __FILE__, __FUNCTION__, malloc_redir);
- dprintf(stderr, "%s, %s(): free_redir %p\n",
- __FILE__, __FUNCTION__, free_redir);
- dprintf(stderr, "%s, %s(): realloc_redir %p\n",
- __FILE__, __FUNCTION__, realloc_redir);
- dprintf(stderr, "%s, %s(): memalign_redir %p\n",
- __FILE__, __FUNCTION__, memalign_redir);
- if (malloc_redir == NULL || free_redir == NULL)
- bound_alloc_error ("Cannot redirect malloc/free");
-#if HAVE_PTHREAD_CREATE
- *(void **) (&pthread_create_redir) = dlsym (addr, "pthread_create");
- dprintf(stderr, "%s, %s(): pthread_create_redir %p\n",
- __FILE__, __FUNCTION__, pthread_create_redir);
- if (pthread_create_redir == NULL)
- bound_alloc_error ("Cannot redirect pthread_create");
-#endif
-#if HAVE_SIGNAL
- *(void **) (&signal_redir) = dlsym (addr, "signal");
- dprintf(stderr, "%s, %s(): signal_redir %p\n",
- __FILE__, __FUNCTION__, signal_redir);
- if (signal_redir == NULL)
- bound_alloc_error ("Cannot redirect signal");
-#endif
-#if HAVE_SIGACTION
- *(void **) (&sigaction_redir) = dlsym (addr, "sigaction");
- dprintf(stderr, "%s, %s(): sigaction_redir %p\n",
- __FILE__, __FUNCTION__, sigaction_redir);
- if (sigaction_redir == NULL)
- bound_alloc_error ("Cannot redirect sigaction");
-#endif
-#if HAVE_FORK
- *(void **) (&fork_redir) = dlsym (addr, "fork");
- dprintf(stderr, "%s, %s(): fork_redir %p\n",
- __FILE__, __FUNCTION__, fork_redir);
- if (fork_redir == NULL)
- bound_alloc_error ("Cannot redirect fork");
-#endif
- }
-#endif
-
-#ifdef __linux__
- {
- FILE *fp;
- unsigned char found;
- unsigned long start;
- unsigned long end;
- unsigned long ad =
- (unsigned long) __builtin_return_address(0);
- char line[1000];
-
- /* Display exec name. Usefull when a lot of code is compiled with tcc */
- fp = fopen ("/proc/self/comm", "r");
- if (fp) {
- memset (exec, 0, sizeof(exec));
- fread (exec, 1, sizeof(exec) - 2, fp);
- if (strchr(exec,'\n'))
- *strchr(exec,'\n') = '\0';
- strcat (exec, ":");
- fclose (fp);
- }
- /* check if dlopen is used (is threre a better way?) */
- found = 0;
- fp = fopen ("/proc/self/maps", "r");
- if (fp) {
- while (fgets (line, sizeof(line), fp)) {
- if (sscanf (line, "%lx-%lx", &start, &end) == 2 &&
- ad >= start && ad < end) {
- found = 1;
- break;
- }
- if (strstr (line,"[heap]"))
- break;
- }
- fclose (fp);
- }
- if (found == 0) {
- use_sem = 1;
- no_strdup = 1;
- }
- }
-#endif
-
- WAIT_SEM ();
-
-#if HAVE_CTYPE
-#ifdef __APPLE__
- tree = splay_insert((size_t) &_DefaultRuneLocale,
- sizeof (_DefaultRuneLocale), tree);
-#else
- /* XXX: Does not work if locale is changed */
- tree = splay_insert((size_t) __ctype_b_loc(),
- sizeof (unsigned short *), tree);
- tree = splay_insert((size_t) (*__ctype_b_loc() - 128),
- 384 * sizeof (unsigned short), tree);
- tree = splay_insert((size_t) __ctype_tolower_loc(),
- sizeof (__int32_t *), tree);
- tree = splay_insert((size_t) (*__ctype_tolower_loc() - 128),
- 384 * sizeof (__int32_t), tree);
- tree = splay_insert((size_t) __ctype_toupper_loc(),
- sizeof (__int32_t *), tree);
- tree = splay_insert((size_t) (*__ctype_toupper_loc() - 128),
- 384 * sizeof (__int32_t), tree);
-#endif
-#endif
-#if HAVE_ERRNO
- tree = splay_insert((size_t) (&errno), sizeof (int), tree);
-#endif
-
-add_bounds:
- if (!p)
- goto no_bounds;
-
- /* add all static bound check values */
- while (p[0] != 0) {
- tree = splay_insert(p[0], p[1], tree);
-#if BOUND_DEBUG
- if (print_calls) {
- dprintf(stderr, "%s, %s(): static var %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- (void *) p[0], (unsigned long) p[1]);
- }
-#endif
- p += 2;
- }
-no_bounds:
-
- POST_SEM ();
- NO_CHECKING_SET(0);
- dprintf(stderr, "%s, %s(): end\n\n", __FILE__, __FUNCTION__);
-}
-
-void
-#if (defined(__GLIBC__) && (__GLIBC_MINOR__ >= 4)) || defined(_WIN32)
-__attribute__((constructor))
-#endif
-__bound_main_arg(int argc, char **argv, char **envp)
-{
- __bound_init (0, -1);
- if (argc && argv) {
- int i;
-
- WAIT_SEM ();
- for (i = 0; i < argc; i++)
- tree = splay_insert((size_t) argv[i], strlen (argv[i]) + 1, tree);
- tree = splay_insert((size_t) argv, (argc + 1) * sizeof(char *), tree);
- POST_SEM ();
-#if BOUND_DEBUG
- if (print_calls) {
- for (i = 0; i < argc; i++)
- dprintf(stderr, "%s, %s(): arg %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- argv[i], (unsigned long)(strlen (argv[i]) + 1));
- dprintf(stderr, "%s, %s(): argv %p %d\n",
- __FILE__, __FUNCTION__, argv,
- (int)((argc + 1) * sizeof(char *)));
- }
-#endif
- }
-
- if (envp && *envp) {
- char **p = envp;
-
- WAIT_SEM ();
- while (*p) {
- tree = splay_insert((size_t) *p, strlen (*p) + 1, tree);
- ++p;
- }
- tree = splay_insert((size_t) envp, (++p - envp) * sizeof(char *), tree);
- POST_SEM ();
-#if BOUND_DEBUG
- if (print_calls) {
- p = envp;
- while (*p) {
- dprintf(stderr, "%s, %s(): env %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- *p, (unsigned long)(strlen (*p) + 1));
- ++p;
- }
- dprintf(stderr, "%s, %s(): environ %p %d\n",
- __FILE__, __FUNCTION__, envp,
- (int)((++p - envp) * sizeof(char *)));
- }
-#endif
- }
-}
-
-void __attribute__((destructor)) __bound_exit(void)
-{
- int i;
- static const char * const alloc_type[] = {
- "", "malloc", "calloc", "realloc", "memalign", "strdup"
- };
-
- dprintf(stderr, "%s, %s():\n", __FILE__, __FUNCTION__);
-
- if (inited) {
-#if !defined(_WIN32) && !defined(__APPLE__) && !defined TCC_MUSL && \
- !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \
- !defined(__ANDROID__)
- if (print_heap) {
- extern void __libc_freeres (void);
- __libc_freeres ();
- }
-#endif
-
- NO_CHECKING_SET(1);
-
- TRY_SEM ();
- while (alloca_list) {
- alloca_list_type *next = alloca_list->next;
-
- tree = splay_delete ((size_t) alloca_list->p, tree);
- BOUND_FREE (alloca_list);
- alloca_list = next;
- }
- while (jmp_list) {
- jmp_list_type *next = jmp_list->next;
-
- BOUND_FREE (jmp_list);
- jmp_list = next;
- }
- for (i = 0; i < FREE_REUSE_SIZE; i++) {
- if (free_reuse_list[i]) {
- tree = splay_delete ((size_t) free_reuse_list[i], tree);
- BOUND_FREE (free_reuse_list[i]);
- }
- }
- while (tree) {
- if (print_heap && tree->type != 0)
- fprintf (stderr, "%s, %s(): %s found size %lu\n",
- __FILE__, __FUNCTION__, alloc_type[tree->type],
- (unsigned long) tree->size);
- tree = splay_delete (tree->start, tree);
- }
-#if TREE_REUSE
- while (tree_free_list) {
- Tree *next = tree_free_list->left;
- BOUND_FREE (tree_free_list);
- tree_free_list = next;
- }
-#endif
- POST_SEM ();
- EXIT_SEM ();
-#if HAVE_TLS_FUNC
-#if defined(_WIN32)
- TlsFree(no_checking_key);
-#else
- pthread_key_delete(no_checking_key);
-#endif
-#endif
- inited = 0;
- if (print_statistic) {
-#if BOUND_STATISTIC
- fprintf (stderr, "bound_ptr_add_count %llu\n", bound_ptr_add_count);
- fprintf (stderr, "bound_ptr_indir1_count %llu\n", bound_ptr_indir1_count);
- fprintf (stderr, "bound_ptr_indir2_count %llu\n", bound_ptr_indir2_count);
- fprintf (stderr, "bound_ptr_indir4_count %llu\n", bound_ptr_indir4_count);
- fprintf (stderr, "bound_ptr_indir8_count %llu\n", bound_ptr_indir8_count);
- fprintf (stderr, "bound_ptr_indir12_count %llu\n", bound_ptr_indir12_count);
- fprintf (stderr, "bound_ptr_indir16_count %llu\n", bound_ptr_indir16_count);
- fprintf (stderr, "bound_local_new_count %llu\n", bound_local_new_count);
- fprintf (stderr, "bound_local_delete_count %llu\n", bound_local_delete_count);
- fprintf (stderr, "bound_malloc_count %llu\n", bound_malloc_count);
- fprintf (stderr, "bound_calloc_count %llu\n", bound_calloc_count);
- fprintf (stderr, "bound_realloc_count %llu\n", bound_realloc_count);
- fprintf (stderr, "bound_free_count %llu\n", bound_free_count);
- fprintf (stderr, "bound_memalign_count %llu\n", bound_memalign_count);
- fprintf (stderr, "bound_mmap_count %llu\n", bound_mmap_count);
- fprintf (stderr, "bound_munmap_count %llu\n", bound_munmap_count);
- fprintf (stderr, "bound_alloca_count %llu\n", bound_alloca_count);
- fprintf (stderr, "bound_setjmp_count %llu\n", bound_setjmp_count);
- fprintf (stderr, "bound_longjmp_count %llu\n", bound_longjmp_count);
- fprintf (stderr, "bound_mempcy_count %llu\n", bound_mempcy_count);
- fprintf (stderr, "bound_memcmp_count %llu\n", bound_memcmp_count);
- fprintf (stderr, "bound_memmove_count %llu\n", bound_memmove_count);
- fprintf (stderr, "bound_memset_count %llu\n", bound_memset_count);
- fprintf (stderr, "bound_strlen_count %llu\n", bound_strlen_count);
- fprintf (stderr, "bound_strcpy_count %llu\n", bound_strcpy_count);
- fprintf (stderr, "bound_strncpy_count %llu\n", bound_strncpy_count);
- fprintf (stderr, "bound_strcmp_count %llu\n", bound_strcmp_count);
- fprintf (stderr, "bound_strncmp_count %llu\n", bound_strncmp_count);
- fprintf (stderr, "bound_strcat_count %llu\n", bound_strcat_count);
- fprintf (stderr, "bound_strncat_count %llu\n", bound_strncat_count);
- fprintf (stderr, "bound_strchr_count %llu\n", bound_strchr_count);
- fprintf (stderr, "bound_strrchr_count %llu\n", bound_strrchr_count);
- fprintf (stderr, "bound_strdup_count %llu\n", bound_strdup_count);
- fprintf (stderr, "bound_not_found %llu\n", bound_not_found);
-#endif
-#if BOUND_STATISTIC_SPLAY
- fprintf (stderr, "bound_splay %llu\n", bound_splay);
- fprintf (stderr, "bound_splay_end %llu\n", bound_splay_end);
- fprintf (stderr, "bound_splay_insert %llu\n", bound_splay_insert);
- fprintf (stderr, "bound_splay_delete %llu\n", bound_splay_delete);
-#endif
- }
- }
-}
-
-void __bound_exit_dll(size_t *p)
-{
- dprintf(stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
-
- if (p) {
- WAIT_SEM ();
- while (p[0] != 0) {
- tree = splay_delete(p[0], tree);
-#if BOUND_DEBUG
- if (print_calls) {
- dprintf(stderr, "%s, %s(): remove static var %p 0x%lx\n",
- __FILE__, __FUNCTION__,
- (void *) p[0], (unsigned long) p[1]);
- }
-#endif
- p += 2;
- }
- POST_SEM ();
- }
-}
-
-#if HAVE_PTHREAD_CREATE
-typedef struct {
- void *(*start_routine) (void *);
- void *arg;
- sigset_t old_mask;
-} bound_thread_create_type;
-
-static void *bound_thread_create(void *bdata)
-{
- bound_thread_create_type *data = (bound_thread_create_type *) bdata;
- void *retval;
-#if HAVE_TLS_FUNC
- int *p = (int *) BOUND_MALLOC(sizeof(int));
-
- if (!p) bound_alloc_error("bound_thread_create malloc");
- *p = 0;
- pthread_setspecific(no_checking_key, p);
-#endif
- pthread_sigmask(SIG_SETMASK, &data->old_mask, NULL);
- retval = data->start_routine(data->arg);
-#if HAVE_TLS_FUNC
- pthread_setspecific(no_checking_key, NULL);
- BOUND_FREE (p);
-#endif
- BOUND_FREE (data);
- return retval;
-}
-
-int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
- void *(*start_routine) (void *), void *arg)
-{
- int retval;
- bound_thread_create_type *data;
- sigset_t mask;
- sigset_t old_mask;
-
- use_sem = 1;
- dprintf (stderr, "%s, %s()\n", __FILE__, __FUNCTION__);
- sigfillset(&mask);
- pthread_sigmask(SIG_SETMASK, &mask, &old_mask);
- data = (bound_thread_create_type *) BOUND_MALLOC(sizeof(bound_thread_create_type));
- if (!data) bound_alloc_error("bound_thread_create malloc");
- data->start_routine = start_routine;
- data->arg = arg;
- data->old_mask = old_mask;
- retval = pthread_create_redir(thread, attr, bound_thread_create, data);
- pthread_sigmask(SIG_SETMASK, &old_mask, NULL);
- return retval;
-}
-#endif
-
-#if HAVE_SIGNAL || HAVE_SIGACTION
-typedef union {
-#if HAVE_SIGNAL
- bound_sig signal_handler;
-#endif
-#if HAVE_SIGACTION
- void (*sig_handler)(int);
- void (*sig_sigaction)(int, siginfo_t *, void *);
-#endif
-} bound_sig_type;
-
-static unsigned char bound_sig_used[NSIG];
-static bound_sig_type bound_sig_data[NSIG];
-#endif
-
-#if HAVE_SIGNAL
-static void signal_handler(int sig)
-{
- __bounds_checking(1);
- bound_sig_data[sig].signal_handler(sig);
- __bounds_checking(-1);
-}
-
-bound_sig signal(int signum, bound_sig handler)
-{
- bound_sig retval;
-
- dprintf (stderr, "%s, %s() %d %p\n", __FILE__, __FUNCTION__,
- signum, handler);
- retval = signal_redir(signum, handler ? signal_handler : handler);
- if (retval != SIG_ERR) {
- if (bound_sig_used[signum])
- retval = bound_sig_data[signum].signal_handler;
- if (handler) {
- bound_sig_used[signum] = 1;
- bound_sig_data[signum].signal_handler = handler;
- }
- }
- return retval;
-}
-#endif
-
-#if HAVE_SIGACTION
-static void sig_handler(int sig)
-{
- __bounds_checking(1);
- bound_sig_data[sig].sig_handler(sig);
- __bounds_checking(-1);
-}
-
-static void sig_sigaction(int sig, siginfo_t *info, void *ucontext)
-{
- __bounds_checking(1);
- bound_sig_data[sig].sig_sigaction(sig, info, ucontext);
- __bounds_checking(-1);
-}
-
-int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
-{
- int retval;
- struct sigaction nact, oact;
-
- dprintf (stderr, "%s, %s() %d %p %p\n", __FILE__, __FUNCTION__,
- signum, act, oldact);
-
- if (sigaction_redir == NULL)
- __bound_init(0,-1);
-
- if (act) {
- nact = *act;
- if (nact.sa_flags & SA_SIGINFO)
- nact.sa_sigaction = sig_sigaction;
- else
- nact.sa_handler = sig_handler;
- retval = sigaction_redir(signum, &nact, &oact);
- }
- else
- retval = sigaction_redir(signum, act, &oact);
- if (retval >= 0) {
- if (bound_sig_used[signum]) {
- if (oact.sa_flags & SA_SIGINFO)
- oact.sa_sigaction = bound_sig_data[signum].sig_sigaction;
- else
- oact.sa_handler = bound_sig_data[signum].sig_handler;
- }
- if (oldact) {
- *oldact = oact;
- }
- if (act) {
- bound_sig_used[signum] = 1;
- if (act->sa_flags & SA_SIGINFO)
- bound_sig_data[signum].sig_sigaction = act->sa_sigaction;
- else
- bound_sig_data[signum].sig_handler = act->sa_handler;
- }
- }
- return retval;
-}
-#endif
-
-#if HAVE_FORK
-pid_t fork(void)
-{
- pid_t retval;
-
- WAIT_SEM();
- retval = (*fork_redir)();
- if (retval == 0)
- INIT_SEM();
- else
- POST_SEM();
- return retval;
-}
-#endif
-
-#if MALLOC_REDIR
-void *malloc(size_t size)
-#else
-void *__bound_malloc(size_t size, const void *caller)
-#endif
-{
- void *ptr;
-
-#if MALLOC_REDIR
- /* This will catch the first dlsym call from __bound_init */
- if (malloc_redir == NULL) {
- __bound_init (0, -1);
- if (malloc_redir == NULL) {
- ptr = &initial_pool[pool_index];
- pool_index = (pool_index + size + 15) & ~15;
- if (pool_index >= sizeof (initial_pool))
- bound_alloc_error ("initial memory pool too small");
- dprintf (stderr, "%s, %s(): initial %p, 0x%lx\n",
- __FILE__, __FUNCTION__, ptr, (unsigned long)size);
- return ptr;
- }
- }
-#endif
- /* we allocate one more byte to ensure the regions will be
- separated by at least one byte. With the glibc malloc, it may
- be in fact not necessary */
- ptr = BOUND_MALLOC (size + 1);
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, ptr, (unsigned long)size);
-
- if (inited && NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_malloc_count);
-
- if (ptr) {
- tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
- if (tree && tree->start == (size_t) ptr)
- tree->type = TCC_TYPE_MALLOC;
- }
- POST_SEM ();
- }
- return ptr;
-}
-
-#if MALLOC_REDIR
-void *memalign(size_t size, size_t align)
-#else
-void *__bound_memalign(size_t size, size_t align, const void *caller)
-#endif
-{
- void *ptr;
-
-#if HAVE_MEMALIGN
- /* we allocate one more byte to ensure the regions will be
- separated by at least one byte. With the glibc malloc, it may
- be in fact not necessary */
- ptr = BOUND_MEMALIGN(size + 1, align);
-#else
- if (align > 4) {
- /* XXX: handle it ? */
- ptr = NULL;
- } else {
- /* we suppose that malloc aligns to at least four bytes */
- ptr = BOUND_MALLOC(size + 1);
- }
-#endif
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, ptr, (unsigned long)size);
-
- if (NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_memalign_count);
-
- if (ptr) {
- tree = splay_insert((size_t) ptr, size ? size : size + 1, tree);
- if (tree && tree->start == (size_t) ptr)
- tree->type = TCC_TYPE_MEMALIGN;
- }
- POST_SEM ();
- }
- return ptr;
-}
-
-#if MALLOC_REDIR
-void free(void *ptr)
-#else
-void __bound_free(void *ptr, const void *caller)
-#endif
-{
- size_t addr = (size_t) ptr;
- void *p;
-
- if (ptr == NULL || tree == NULL
-#if MALLOC_REDIR
- || ((unsigned char *) ptr >= &initial_pool[0] &&
- (unsigned char *) ptr < &initial_pool[sizeof(initial_pool)])
-#endif
- )
- return;
-
- dprintf(stderr, "%s, %s(): %p\n", __FILE__, __FUNCTION__, ptr);
-
- if (inited && NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_free_count);
- tree = splay (addr, tree);
- if (tree->start == addr) {
- if (tree->is_invalid) {
- POST_SEM ();
- bound_error("freeing invalid region");
- return;
- }
- tree->is_invalid = 1;
- memset (ptr, 0x5a, tree->size);
- p = free_reuse_list[free_reuse_index];
- free_reuse_list[free_reuse_index] = ptr;
- free_reuse_index = (free_reuse_index + 1) % FREE_REUSE_SIZE;
- if (p)
- tree = splay_delete((size_t)p, tree);
- ptr = p;
- }
- POST_SEM ();
- }
- BOUND_FREE (ptr);
-}
-
-#if MALLOC_REDIR
-void *realloc(void *ptr, size_t size)
-#else
-void *__bound_realloc(void *ptr, size_t size, const void *caller)
-#endif
-{
- void *new_ptr;
-
- if (size == 0) {
-#if MALLOC_REDIR
- free(ptr);
-#else
- __bound_free(ptr, caller);
-#endif
- return NULL;
- }
-
- new_ptr = BOUND_REALLOC (ptr, size + 1);
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, new_ptr, (unsigned long)size);
-
- if (NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_realloc_count);
-
- if (ptr)
- tree = splay_delete ((size_t) ptr, tree);
- if (new_ptr) {
- tree = splay_insert ((size_t) new_ptr, size ? size : size + 1, tree);
- if (tree && tree->start == (size_t) new_ptr)
- tree->type = TCC_TYPE_REALLOC;
- }
- POST_SEM ();
- }
- return new_ptr;
-}
-
-#if MALLOC_REDIR
-void *calloc(size_t nmemb, size_t size)
-#else
-void *__bound_calloc(size_t nmemb, size_t size)
-#endif
-{
- void *ptr;
-
- size *= nmemb;
-#if MALLOC_REDIR
- /* This will catch the first dlsym call from __bound_init */
- if (malloc_redir == NULL) {
- __bound_init (0, -1);
- if (malloc_redir == NULL) {
- ptr = &initial_pool[pool_index];
- pool_index = (pool_index + size + 15) & ~15;
- if (pool_index >= sizeof (initial_pool))
- bound_alloc_error ("initial memory pool too small");
- dprintf (stderr, "%s, %s(): initial %p, 0x%lx\n",
- __FILE__, __FUNCTION__, ptr, (unsigned long)size);
- memset (ptr, 0, size);
- return ptr;
- }
- }
-#endif
- ptr = BOUND_MALLOC(size + 1);
- dprintf (stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, ptr, (unsigned long)size);
-
- if (ptr) {
- memset (ptr, 0, size);
- if (NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_calloc_count);
- tree = splay_insert ((size_t) ptr, size ? size : size + 1, tree);
- if (tree && tree->start == (size_t) ptr)
- tree->type = TCC_TYPE_CALLOC;
- POST_SEM ();
- }
- }
- return ptr;
-}
-
-#if !defined(_WIN32)
-void *__bound_mmap (void *start, size_t size, int prot,
- int flags, int fd, off_t offset)
-{
- void *result;
-
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, start, (unsigned long)size);
- result = mmap (start, size, prot, flags, fd, offset);
- if (result && NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_mmap_count);
- tree = splay_insert((size_t)result, size, tree);
- POST_SEM ();
- }
- return result;
-}
-
-int __bound_munmap (void *start, size_t size)
-{
- int result;
-
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, start, (unsigned long)size);
- if (start && NO_CHECKING_GET() == 0) {
- WAIT_SEM ();
- INCR_COUNT(bound_munmap_count);
- tree = splay_delete ((size_t) start, tree);
- POST_SEM ();
- }
- result = munmap (start, size);
- return result;
-}
-#endif
-
-/* some useful checked functions */
-
-/* check that (p ... p + size - 1) lies inside 'p' region, if any */
-static void __bound_check(const void *p, size_t size, const char *function)
-{
- if (size != 0 && __bound_ptr_add((void *)p, size) == INVALID_POINTER) {
- bound_error("invalid pointer %p, size 0x%lx in %s",
- p, (unsigned long)size, function);
- }
-}
-
-static int check_overlap (const void *p1, size_t n1,
- const void *p2, size_t n2,
- const char *function)
-{
- const void *p1e = (const void *) ((const char *) p1 + n1);
- const void *p2e = (const void *) ((const char *) p2 + n2);
-
- if (NO_CHECKING_GET() == 0 && n1 != 0 && n2 !=0 &&
- ((p1 <= p2 && p1e > p2) || /* p1----p2====p1e----p2e */
- (p2 <= p1 && p2e > p1))) { /* p2----p1====p2e----p1e */
- bound_error("overlapping regions %p(0x%lx), %p(0x%lx) in %s",
- p1, (unsigned long)n1, p2, (unsigned long)n2, function);
- return never_fatal < 0;
- }
- return 0;
-}
-
-void *__bound_memcpy(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_mempcy_count);
- __bound_check(dest, n, "memcpy dest");
- __bound_check(src, n, "memcpy src");
- if (check_overlap(dest, n, src, n, "memcpy"))
- return dest;
- return memcpy(dest, src, n);
-}
-
-int __bound_memcmp(const void *s1, const void *s2, size_t n)
-{
- const unsigned char *u1 = (const unsigned char *) s1;
- const unsigned char *u2 = (const unsigned char *) s2;
- int retval = 0;
-
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, s1, s2, (unsigned long)n);
- INCR_COUNT(bound_memcmp_count);
- for (;;) {
- if ((ssize_t) --n == -1)
- break;
- else if (*u1 != *u2) {
- retval = *u1++ - *u2++;
- break;
- }
- ++u1;
- ++u2;
- }
- __bound_check(s1, (const void *)u1 - s1, "memcmp s1");
- __bound_check(s2, (const void *)u2 - s2, "memcmp s2");
- return retval;
-}
-
-void *__bound_memmove(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_memmove_count);
- __bound_check(dest, n, "memmove dest");
- __bound_check(src, n, "memmove src");
- return memmove(dest, src, n);
-}
-
-void *__bound_memset(void *s, int c, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n",
- __FILE__, __FUNCTION__, s, c, (unsigned long)n);
- INCR_COUNT(bound_memset_count);
- __bound_check(s, n, "memset");
- return memset(s, c, n);
-}
-
-#if defined(__arm__) && defined(__ARM_EABI__)
-void *__bound___aeabi_memcpy(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_mempcy_count);
- __bound_check(dest, n, "memcpy dest");
- __bound_check(src, n, "memcpy src");
- if (check_overlap(dest, n, src, n, "memcpy"))
- return dest;
- return __aeabi_memcpy(dest, src, n);
-}
-
-void *__bound___aeabi_memmove(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_memmove_count);
- __bound_check(dest, n, "memmove dest");
- __bound_check(src, n, "memmove src");
- return __aeabi_memmove(dest, src, n);
-}
-
-void *__bound___aeabi_memmove4(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_memmove_count);
- __bound_check(dest, n, "memmove dest");
- __bound_check(src, n, "memmove src");
- return __aeabi_memmove4(dest, src, n);
-}
-
-void *__bound___aeabi_memmove8(void *dest, const void *src, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_memmove_count);
- __bound_check(dest, n, "memmove dest");
- __bound_check(src, n, "memmove src");
- return __aeabi_memmove8(dest, src, n);
-}
-
-void *__bound___aeabi_memset(void *s, int c, size_t n)
-{
- dprintf(stderr, "%s, %s(): %p, %d, 0x%lx\n",
- __FILE__, __FUNCTION__, s, c, (unsigned long)n);
- INCR_COUNT(bound_memset_count);
- __bound_check(s, n, "memset");
- return __aeabi_memset(s, c, n);
-}
-#endif
-
-int __bound_strlen(const char *s)
-{
- const char *p = s;
-
- dprintf(stderr, "%s, %s(): %p\n",
- __FILE__, __FUNCTION__, s);
- INCR_COUNT(bound_strlen_count);
- while (*p++);
- __bound_check(s, p - s, "strlen");
- return (p - s) - 1;
-}
-
-char *__bound_strcpy(char *dest, const char *src)
-{
- size_t len;
- const char *p = src;
-
- dprintf(stderr, "%s, %s(): %p, %p\n",
- __FILE__, __FUNCTION__, dest, src);
- INCR_COUNT(bound_strcpy_count);
- while (*p++);
- len = p - src;
- __bound_check(dest, len, "strcpy dest");
- __bound_check(src, len, "strcpy src");
- if (check_overlap(dest, len, src, len, "strcpy"))
- return dest;
- return strcpy (dest, src);
-}
-
-char *__bound_strncpy(char *dest, const char *src, size_t n)
-{
- size_t len = n;
- const char *p = src;
-
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_strncpy_count);
- while (len-- && *p++);
- len = p - src;
- __bound_check(dest, len, "strncpy dest");
- __bound_check(src, len, "strncpy src");
- if (check_overlap(dest, len, src, len, "strncpy"))
- return dest;
- return strncpy(dest, src, n);
-}
-
-int __bound_strcmp(const char *s1, const char *s2)
-{
- const unsigned char *u1 = (const unsigned char *) s1;
- const unsigned char *u2 = (const unsigned char *) s2;
-
- dprintf(stderr, "%s, %s(): %p, %p\n",
- __FILE__, __FUNCTION__, s1, s2);
- INCR_COUNT(bound_strcmp_count);
- while (*u1 && *u1 == *u2) {
- ++u1;
- ++u2;
- }
- __bound_check(s1, ((const char *)u1 - s1) + 1, "strcmp s1");
- __bound_check(s2, ((const char *)u2 - s2) + 1, "strcmp s2");
- return *u1 - *u2;
-}
-
-int __bound_strncmp(const char *s1, const char *s2, size_t n)
-{
- const unsigned char *u1 = (const unsigned char *) s1;
- const unsigned char *u2 = (const unsigned char *) s2;
- int retval = 0;
-
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, s1, s2, (unsigned long)n);
- INCR_COUNT(bound_strncmp_count);
- do {
- if ((ssize_t) --n == -1)
- break;
- else if (*u1 != *u2) {
- retval = *u1++ - *u2++;
- break;
- }
- ++u2;
- } while (*u1++);
- __bound_check(s1, (const char *)u1 - s1, "strncmp s1");
- __bound_check(s2, (const char *)u2 - s2, "strncmp s2");
- return retval;
-}
-
-char *__bound_strcat(char *dest, const char *src)
-{
- char *r = dest;
- const char *s = src;
-
- dprintf(stderr, "%s, %s(): %p, %p\n",
- __FILE__, __FUNCTION__, dest, src);
- INCR_COUNT(bound_strcat_count);
- while (*dest++);
- while (*src++);
- __bound_check(r, (dest - r) + (src - s) - 1, "strcat dest");
- __bound_check(s, src - s, "strcat src");
- if (check_overlap(r, (dest - r) + (src - s) - 1, s, src - s, "strcat"))
- return dest;
- return strcat(r, s);
-}
-
-char *__bound_strncat(char *dest, const char *src, size_t n)
-{
- char *r = dest;
- const char *s = src;
- size_t len = n;
-
- dprintf(stderr, "%s, %s(): %p, %p, 0x%lx\n",
- __FILE__, __FUNCTION__, dest, src, (unsigned long)n);
- INCR_COUNT(bound_strncat_count);
- while (*dest++);
- while (len-- && *src++);
- __bound_check(r, (dest - r) + (src - s) - 1, "strncat dest");
- __bound_check(s, src - s, "strncat src");
- if (check_overlap(r, (dest - r) + (src - s) - 1, s, src - s, "strncat"))
- return dest;
- return strncat(r, s, n);
-}
-
-char *__bound_strchr(const char *s, int c)
-{
- const unsigned char *str = (const unsigned char *) s;
- unsigned char ch = c;
-
- dprintf(stderr, "%s, %s(): %p, %d\n",
- __FILE__, __FUNCTION__, s, ch);
- INCR_COUNT(bound_strchr_count);
- while (*str) {
- if (*str == ch)
- break;
- ++str;
- }
- __bound_check(s, ((const char *)str - s) + 1, "strchr");
- return *str == ch ? (char *) str : NULL;
-}
-
-char *__bound_strrchr(const char *s, int c)
-{
- const unsigned char *str = (const unsigned char *) s;
- unsigned char ch = c;
-
- dprintf(stderr, "%s, %s(): %p, %d\n",
- __FILE__, __FUNCTION__, s, ch);
- INCR_COUNT(bound_strrchr_count);
- while (*str++);
- __bound_check(s, (const char *)str - s, "strrchr");
- while (str != (const unsigned char *)s) {
- if (*--str == ch)
- break;
- }
- __bound_check(s, (const char *)str - s, "strrchr");
- return *str == ch ? (char *) str : NULL;
-}
-
-char *__bound_strdup(const char *s)
-{
- const char *p = s;
- char *new;
-
- INCR_COUNT(bound_strdup_count);
- while (*p++);
- __bound_check(s, p - s, "strdup");
- new = BOUND_MALLOC ((p - s) + 1);
- dprintf(stderr, "%s, %s(): %p, 0x%lx\n",
- __FILE__, __FUNCTION__, new, (unsigned long)(p -s));
- if (new) {
- if (NO_CHECKING_GET() == 0 && no_strdup == 0) {
- WAIT_SEM ();
- tree = splay_insert((size_t)new, p - s, tree);
- if (tree && tree->start == (size_t) new)
- tree->type = TCC_TYPE_STRDUP;
- POST_SEM ();
- }
- memcpy (new, s, p - s);
- }
- return new;
-}
-
-/*
- An implementation of top-down splaying with sizes
- D. Sleator <sleator@cs.cmu.edu>, January 1994.
-
- This extends top-down-splay.c to maintain a size field in each node.
- This is the number of nodes in the subtree rooted there. This makes
- it possible to efficiently compute the rank of a key. (The rank is
- the number of nodes to the left of the given key.) It it also
- possible to quickly find the node of a given rank. Both of these
- operations are illustrated in the code below. The remainder of this
- introduction is taken from top-down-splay.c.
-
- "Splay trees", or "self-adjusting search trees" are a simple and
- efficient data structure for storing an ordered set. The data
- structure consists of a binary tree, with no additional fields. It
- allows searching, insertion, deletion, deletemin, deletemax,
- splitting, joining, and many other operations, all with amortized
- logarithmic performance. Since the trees adapt to the sequence of
- requests, their performance on real access patterns is typically even
- better. Splay trees are described in a number of texts and papers
- [1,2,3,4].
-
- The code here is adapted from simple top-down splay, at the bottom of
- page 669 of [2]. It can be obtained via anonymous ftp from
- spade.pc.cs.cmu.edu in directory /usr/sleator/public.
-
- The chief modification here is that the splay operation works even if the
- item being splayed is not in the tree, and even if the tree root of the
- tree is NULL. So the line:
-
- t = splay(i, t);
-
- causes it to search for item with key i in the tree rooted at t. If it's
- there, it is splayed to the root. If it isn't there, then the node put
- at the root is the last one before NULL that would have been reached in a
- normal binary search for i. (It's a neighbor of i in the tree.) This
- allows many other operations to be easily implemented, as shown below.
-
- [1] "Data Structures and Their Algorithms", Lewis and Denenberg,
- Harper Collins, 1991, pp 243-251.
- [2] "Self-adjusting Binary Search Trees" Sleator and Tarjan,
- JACM Volume 32, No 3, July 1985, pp 652-686.
- [3] "Data Structure and Algorithm Analysis", Mark Weiss,
- Benjamin Cummins, 1992, pp 119-130.
- [4] "Data Structures, Algorithms, and Performance", Derick Wood,
- Addison-Wesley, 1993, pp 367-375
-*/
-
-/* Code adapted for tcc */
-
-#define compare(start,tstart,tsize) (start < tstart ? -1 : \
- start >= tstart+tsize ? 1 : 0)
-
-static Tree * splay (size_t addr, Tree *t)
-/* Splay using the key start (which may or may not be in the tree.) */
-/* The starting root is t, and the tree used is defined by rat */
-{
- Tree N, *l, *r, *y;
- int comp;
-
- INCR_COUNT_SPLAY(bound_splay);
- if (t == NULL) return t;
- N.left = N.right = NULL;
- l = r = &N;
-
- for (;;) {
- comp = compare(addr, t->start, t->size);
- if (comp < 0) {
- y = t->left;
- if (y == NULL) break;
- if (compare(addr, y->start, y->size) < 0) {
- t->left = y->right; /* rotate right */
- y->right = t;
- t = y;
- if (t->left == NULL) break;
- }
- r->left = t; /* link right */
- r = t;
- t = t->left;
- } else if (comp > 0) {
- y = t->right;
- if (y == NULL) break;
- if (compare(addr, y->start, y->size) > 0) {
- t->right = y->left; /* rotate left */
- y->left = t;
- t = y;
- if (t->right == NULL) break;
- }
- l->right = t; /* link left */
- l = t;
- t = t->right;
- } else {
- break;
- }
- }
- l->right = t->left; /* assemble */
- r->left = t->right;
- t->left = N.right;
- t->right = N.left;
-
- return t;
-}
-
-#define compare_end(start,tend) (start < tend ? -1 : \
- start > tend ? 1 : 0)
-
-static Tree * splay_end (size_t addr, Tree *t)
-/* Splay using the key start (which may or may not be in the tree.) */
-/* The starting root is t, and the tree used is defined by rat */
-{
- Tree N, *l, *r, *y;
- int comp;
-
- INCR_COUNT_SPLAY(bound_splay_end);
- if (t == NULL) return t;
- N.left = N.right = NULL;
- l = r = &N;
-
- for (;;) {
- comp = compare_end(addr, t->start + t->size);
- if (comp < 0) {
- y = t->left;
- if (y == NULL) break;
- if (compare_end(addr, y->start + y->size) < 0) {
- t->left = y->right; /* rotate right */
- y->right = t;
- t = y;
- if (t->left == NULL) break;
- }
- r->left = t; /* link right */
- r = t;
- t = t->left;
- } else if (comp > 0) {
- y = t->right;
- if (y == NULL) break;
- if (compare_end(addr, y->start + y->size) > 0) {
- t->right = y->left; /* rotate left */
- y->left = t;
- t = y;
- if (t->right == NULL) break;
- }
- l->right = t; /* link left */
- l = t;
- t = t->right;
- } else {
- break;
- }
- }
- l->right = t->left; /* assemble */
- r->left = t->right;
- t->left = N.right;
- t->right = N.left;
-
- return t;
-}
-
-static Tree * splay_insert(size_t addr, size_t size, Tree * t)
-/* Insert key start into the tree t, if it is not already there. */
-/* Return a pointer to the resulting tree. */
-{
- Tree * new;
-
- INCR_COUNT_SPLAY(bound_splay_insert);
- if (t != NULL) {
- t = splay(addr,t);
- if (compare(addr, t->start, t->size)==0) {
- return t; /* it's already there */
- }
- }
-#if TREE_REUSE
- if (tree_free_list) {
- new = tree_free_list;
- tree_free_list = new->left;
- }
- else
-#endif
- {
- new = (Tree *) BOUND_MALLOC (sizeof (Tree));
- }
- if (new == NULL) {
- bound_alloc_error("not enough memory for bound checking code");
- }
- else {
- if (t == NULL) {
- new->left = new->right = NULL;
- } else if (compare(addr, t->start, t->size) < 0) {
- new->left = t->left;
- new->right = t;
- t->left = NULL;
- } else {
- new->right = t->right;
- new->left = t;
- t->right = NULL;
- }
- new->start = addr;
- new->size = size;
- new->type = TCC_TYPE_NONE;
- new->is_invalid = 0;
- }
- return new;
-}
-
-#define compare_destroy(start,tstart) (start < tstart ? -1 : \
- start > tstart ? 1 : 0)
-
-static Tree * splay_delete(size_t addr, Tree *t)
-/* Deletes addr from the tree if it's there. */
-/* Return a pointer to the resulting tree. */
-{
- Tree * x;
-
- INCR_COUNT_SPLAY(bound_splay_delete);
- if (t==NULL) return NULL;
- t = splay(addr,t);
- if (compare_destroy(addr, t->start) == 0) { /* found it */
- if (t->left == NULL) {
- x = t->right;
- } else {
- x = splay(addr, t->left);
- x->right = t->right;
- }
-#if TREE_REUSE
- t->left = tree_free_list;
- tree_free_list = t;
-#else
- BOUND_FREE(t);
-#endif
- return x;
- } else {
- return t; /* It wasn't there */
- }
-}
-
-void splay_printtree(Tree * t, int d)
-{
- int i;
- if (t == NULL) return;
- splay_printtree(t->right, d+1);
- for (i=0; i<d; i++) fprintf(stderr," ");
- fprintf(stderr,"%p(0x%lx:%u:%u)\n",
- (void *) t->start, (unsigned long) t->size,
- (unsigned)t->type, (unsigned)t->is_invalid);
- splay_printtree(t->left, d+1);
-}
diff --git a/tinycc/lib/bt-dll.c b/tinycc/lib/bt-dll.c
deleted file mode 100644
index 7c62cef..0000000
--- a/tinycc/lib/bt-dll.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* ------------------------------------------------------------- */
-/* stubs for calling bcheck functions from a dll. */
-
-#include <windows.h>
-#include <stdio.h>
-
-#define REDIR_ALL \
- REDIR(__bt_init) \
- REDIR(__bt_exit) \
- REDIR(tcc_backtrace) \
- \
- REDIR(__bound_ptr_add) \
- REDIR(__bound_ptr_indir1) \
- REDIR(__bound_ptr_indir2) \
- REDIR(__bound_ptr_indir4) \
- REDIR(__bound_ptr_indir8) \
- REDIR(__bound_ptr_indir12) \
- REDIR(__bound_ptr_indir16) \
- REDIR(__bound_local_new) \
- REDIR(__bound_local_delete) \
- REDIR(__bound_new_region) \
- \
- REDIR(__bound_free) \
- REDIR(__bound_malloc) \
- REDIR(__bound_realloc) \
- REDIR(__bound_memcpy) \
- REDIR(__bound_memcmp) \
- REDIR(__bound_memmove) \
- REDIR(__bound_memset) \
- REDIR(__bound_strlen) \
- REDIR(__bound_strcpy) \
- REDIR(__bound_strncpy) \
- REDIR(__bound_strcmp) \
- REDIR(__bound_strncmp) \
- REDIR(__bound_strcat) \
- REDIR(__bound_strchr) \
- REDIR(__bound_strdup)
-
-#ifdef __leading_underscore
-#define _(s) "_"#s
-#else
-#define _(s) #s
-#endif
-
-#define REDIR(s) void *s;
-static struct { REDIR_ALL } all_ptrs;
-#undef REDIR
-#define REDIR(s) #s"\0"
-static const char all_names[] = REDIR_ALL;
-#undef REDIR
-#define REDIR(s) __asm__(".global " _(s) ";" _(s) ": jmp *%0" : : "m" (all_ptrs.s) );
-static void all_jmps() { REDIR_ALL }
-#undef REDIR
-
-void __bt_init_dll(int bcheck)
-{
- const char *s = all_names;
- void **p = (void**)&all_ptrs;
- do {
- *p = (void*)GetProcAddress(GetModuleHandle(NULL), (char*)s);
- if (NULL == *p) {
- char buf[100];
- sprintf(buf,
- "Error: function '%s()' not found in executable. "
- "(Need -bt or -b for linking the exe.)", s);
- if (GetStdHandle(STD_ERROR_HANDLE))
- fprintf(stderr, "TCC/BCHECK: %s\n", buf), fflush(stderr);
- else
- MessageBox(NULL, buf, "TCC/BCHECK", MB_ICONERROR);
- ExitProcess(1);
- }
- s = strchr(s,'\0') + 1, ++p;
- } while (*s && (bcheck || p < &all_ptrs.__bound_ptr_add));
-}
diff --git a/tinycc/lib/bt-exe.c b/tinycc/lib/bt-exe.c
deleted file mode 100644
index 3a2d02e..0000000
--- a/tinycc/lib/bt-exe.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* ------------------------------------------------------------- */
-/* for linking rt_printline and the signal/exception handler
- from tccrun.c into executables. */
-
-#define CONFIG_TCC_BACKTRACE_ONLY
-#define ONE_SOURCE 1
-#define pstrcpy tcc_pstrcpy
-#include "../tccrun.c"
-
-int (*__rt_error)(void*, void*, const char *, va_list);
-__attribute__((weak)) void __bound_checking_lock(void);
-__attribute__((weak)) void __bound_checking_unlock(void);
-
-#ifndef _WIN32
-# define __declspec(n)
-#endif
-
-__declspec(dllexport)
-void __bt_init(rt_context *p, int num_callers)
-{
- __attribute__((weak)) int main();
- __attribute__((weak)) void __bound_init(void*, int);
- struct rt_context *rc = &g_rtctxt;
- //fprintf(stderr, "__bt_init %d %p %p\n", num_callers, p->stab_sym, p->bounds_start), fflush(stderr);
- /* call __bound_init here due to redirection of sigaction */
- /* needed to add global symbols */
- if (p->bounds_start) {
- __bound_init(p->bounds_start, -1);
- __bound_checking_lock();
- }
- if (num_callers) {
- memcpy(rc, p, offsetof(rt_context, next));
- rc->num_callers = num_callers - 1;
- rc->top_func = main;
- __rt_error = _rt_error;
- set_exception_handler();
- } else {
- p->next = rc->next, rc->next = p;
- }
- if (p->bounds_start)
- __bound_checking_unlock();
-}
-
-__declspec(dllexport)
-void __bt_exit(rt_context *p)
-{
- __attribute__((weak)) void __bound_exit_dll(void*);
- struct rt_context *rc = &g_rtctxt;
-
- if (p->bounds_start) {
- __bound_exit_dll(p->bounds_start);
- __bound_checking_lock();
- }
- while (rc) {
- if (rc->next == p) {
- rc->next = rc->next->next;
- break;
- }
- rc = rc->next;
- }
- if (p->bounds_start)
- __bound_checking_unlock();
-}
-
-/* copy a string and truncate it. */
-ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s)
-{
- int l = strlen(s);
- if (l >= buf_size)
- l = buf_size - 1;
- memcpy(buf, s, l);
- buf[l] = 0;
- return buf;
-}
diff --git a/tinycc/lib/bt-log.c b/tinycc/lib/bt-log.c
deleted file mode 100644
index 8f7a4db..0000000
--- a/tinycc/lib/bt-log.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/* ------------------------------------------------------------- */
-/* function to get a stack backtrace on demand with a message */
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-int (*__rt_error)(void*, void*, const char *, va_list);
-
-#ifdef _WIN32
-# define DLL_EXPORT __declspec(dllexport)
-#else
-# define DLL_EXPORT
-#endif
-
-/* Needed when using ...libtcc1-usegcc=yes in lib/Makefile */
-#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wframe-address"
-#endif
-
-DLL_EXPORT int tcc_backtrace(const char *fmt, ...)
-{
- va_list ap;
- int ret;
-
- if (__rt_error) {
- void *fp = __builtin_frame_address(1);
- void *ip = __builtin_return_address(0);
- va_start(ap, fmt);
- ret = __rt_error(fp, ip, fmt, ap);
- va_end(ap);
- } else {
- const char *p;
- if (fmt[0] == '^' && (p = strchr(fmt + 1, fmt[0])))
- fmt = p + 1;
- va_start(ap, fmt);
- ret = vfprintf(stderr, fmt, ap);
- va_end(ap);
- fprintf(stderr, "\n"), fflush(stderr);
- }
- return ret;
-}
-
-#if (defined(__GNUC__) && (__GNUC__ >= 6)) || defined(__clang__)
-#pragma GCC diagnostic pop
-#endif
diff --git a/tinycc/lib/builtin.c b/tinycc/lib/builtin.c
deleted file mode 100644
index e40a003..0000000
--- a/tinycc/lib/builtin.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/* uses alias to allow building with gcc/clang */
-#ifdef __TINYC__
-#define BUILTIN(x) __builtin_##x
-#define BUILTINN(x) "__builtin_" # x
-#else
-#define BUILTIN(x) __tcc_builtin_##x
-#define BUILTINN(x) "__tcc_builtin_" # x
-#endif
-
-/* ---------------------------------------------- */
-/* This file implements:
- * __builtin_ffs
- * __builtin_clz
- * __builtin_ctz
- * __builtin_clrsb
- * __builtin_popcount
- * __builtin_parity
- * for int, long and long long
- */
-
-static const unsigned char table_1_32[] = {
- 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
- 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
-};
-static const unsigned char table_2_32[32] = {
- 31, 22, 30, 21, 18, 10, 29, 2, 20, 17, 15, 13, 9, 6, 28, 1,
- 23, 19, 11, 3, 16, 14, 7, 24, 12, 4, 8, 25, 5, 26, 27, 0
-};
-static const unsigned char table_1_64[] = {
- 0, 1, 2, 53, 3, 7, 54, 27, 4, 38, 41, 8, 34, 55, 48, 28,
- 62, 5, 39, 46, 44, 42, 22, 9, 24, 35, 59, 56, 49, 18, 29, 11,
- 63, 52, 6, 26, 37, 40, 33, 47, 61, 45, 43, 21, 23, 58, 17, 10,
- 51, 25, 36, 32, 60, 20, 57, 16, 50, 31, 19, 15, 30, 14, 13, 12
-};
-static const unsigned char table_2_64[] = {
- 63, 16, 62, 7, 15, 36, 61, 3, 6, 14, 22, 26, 35, 47, 60, 2,
- 9, 5, 28, 11, 13, 21, 42, 19, 25, 31, 34, 40, 46, 52, 59, 1,
- 17, 8, 37, 4, 23, 27, 48, 10, 29, 12, 43, 20, 32, 41, 53, 18,
- 38, 24, 49, 30, 44, 33, 54, 39, 50, 45, 55, 51, 56, 57, 58, 0
-};
-
-#define FFSI(x) \
- return table_1_32[((x & -x) * 0x077cb531u) >> 27] + (x != 0);
-#define FFSL(x) \
- return table_1_64[((x & -x) * 0x022fdd63cc95386dull) >> 58] + (x != 0);
-#define CTZI(x) \
- return table_1_32[((x & -x) * 0x077cb531u) >> 27];
-#define CTZL(x) \
- return table_1_64[((x & -x) * 0x022fdd63cc95386dull) >> 58];
-#define CLZI(x) \
- x |= x >> 1; \
- x |= x >> 2; \
- x |= x >> 4; \
- x |= x >> 8; \
- x |= x >> 16; \
- return table_2_32[(x * 0x07c4acddu) >> 27];
-#define CLZL(x) \
- x |= x >> 1; \
- x |= x >> 2; \
- x |= x >> 4; \
- x |= x >> 8; \
- x |= x >> 16; \
- x |= x >> 32; \
- return table_2_64[x * 0x03f79d71b4cb0a89ull >> 58];
-#define POPCOUNTI(x, m) \
- x = x - ((x >> 1) & 0x55555555); \
- x = (x & 0x33333333) + ((x >> 2) & 0x33333333); \
- x = (x + (x >> 4)) & 0xf0f0f0f; \
- return ((x * 0x01010101) >> 24) & m;
-#define POPCOUNTL(x, m) \
- x = x - ((x >> 1) & 0x5555555555555555ull); \
- x = (x & 0x3333333333333333ull) + ((x >> 2) & 0x3333333333333333ull); \
- x = (x + (x >> 4)) & 0xf0f0f0f0f0f0f0full; \
- return ((x * 0x0101010101010101ull) >> 56) & m;
-
-/* Returns one plus the index of the least significant 1-bit of x,
- or if x is zero, returns zero. */
-int BUILTIN(ffs) (int x) { FFSI(x) }
-int BUILTIN(ffsll) (long long x) { FFSL(x) }
-#if __SIZEOF_LONG__ == 4
-int BUILTIN(ffsl) (long x) __attribute__((alias(BUILTINN(ffs))));
-#else
-int BUILTIN(ffsl) (long x) __attribute__((alias(BUILTINN(ffsll))));
-#endif
-
-/* Returns the number of leading 0-bits in x, starting at the most significant
- bit position. If x is 0, the result is undefined. */
-int BUILTIN(clz) (unsigned int x) { CLZI(x) }
-int BUILTIN(clzll) (unsigned long long x) { CLZL(x) }
-#if __SIZEOF_LONG__ == 4
-int BUILTIN(clzl) (unsigned long x) __attribute__((alias(BUILTINN(clz))));
-#else
-int BUILTIN(clzl) (unsigned long x) __attribute__((alias(BUILTINN(clzll))));
-#endif
-
-/* Returns the number of trailing 0-bits in x, starting at the least
- significant bit position. If x is 0, the result is undefined. */
-int BUILTIN(ctz) (unsigned int x) { CTZI(x) }
-int BUILTIN(ctzll) (unsigned long long x) { CTZL(x) }
-#if __SIZEOF_LONG__ == 4
-int BUILTIN(ctzl) (unsigned long x) __attribute__((alias(BUILTINN(ctz))));
-#else
-int BUILTIN(ctzl) (unsigned long x) __attribute__((alias(BUILTINN(ctzll))));
-#endif
-
-/* Returns the number of leading redundant sign bits in x, i.e. the number
- of bits following the most significant bit that are identical to it.
- There are no special cases for 0 or other values. */
-int BUILTIN(clrsb) (int x) { if (x < 0) x = ~x; x <<= 1; CLZI(x) }
-int BUILTIN(clrsbll) (long long x) { if (x < 0) x = ~x; x <<= 1; CLZL(x) }
-#if __SIZEOF_LONG__ == 4
-int BUILTIN(clrsbl) (long x) __attribute__((alias(BUILTINN(clrsb))));
-#else
-int BUILTIN(clrsbl) (long x) __attribute__((alias(BUILTINN(clrsbll))));
-#endif
-
-/* Returns the number of 1-bits in x.*/
-int BUILTIN(popcount) (unsigned int x) { POPCOUNTI(x, 0x3f) }
-int BUILTIN(popcountll) (unsigned long long x) { POPCOUNTL(x, 0x7f) }
-#if __SIZEOF_LONG__ == 4
-int BUILTIN(popcountl) (unsigned long x) __attribute__((alias(BUILTINN(popcount))));
-#else
-int BUILTIN(popcountl ) (unsigned long x) __attribute__((alias(BUILTINN(popcountll))));
-#endif
-
-/* Returns the parity of x, i.e. the number of 1-bits in x modulo 2. */
-int BUILTIN(parity) (unsigned int x) { POPCOUNTI(x, 0x01) }
-int BUILTIN(parityll) (unsigned long long x) { POPCOUNTL(x, 0x01) }
-#if __SIZEOF_LONG__ == 4
-int BUILTIN(parityl) (unsigned long x) __attribute__((alias(BUILTINN(parity))));
-#else
-int BUILTIN(parityl) (unsigned long x) __attribute__((alias(BUILTINN(parityll))));
-#endif
-
-#ifndef __TINYC__
-#if defined(__GNUC__) && (__GNUC__ >= 6)
-/* gcc overrides alias from __builtin_ffs... to ffs.. so use assembly code */
-__asm__(".globl __builtin_ffs");
-__asm__(".set __builtin_ffs,__tcc_builtin_ffs");
-__asm__(".globl __builtin_ffsl");
-__asm__(".set __builtin_ffsl,__tcc_builtin_ffsl");
-__asm__(".globl __builtin_ffsll");
-__asm__(".set __builtin_ffsll,__tcc_builtin_ffsll");
-#else
-int __builtin_ffs(int x) __attribute__((alias("__tcc_builtin_ffs")));
-int __builtin_ffsl(long x) __attribute__((alias("__tcc_builtin_ffsl")));
-int __builtin_ffsll(long long x) __attribute__((alias("__tcc_builtin_ffsll")));
-#endif
-int __builtin_clz(unsigned int x) __attribute__((alias("__tcc_builtin_clz")));
-int __builtin_clzl(unsigned long x) __attribute__((alias("__tcc_builtin_clzl")));
-int __builtin_clzll(unsigned long long x) __attribute__((alias("__tcc_builtin_clzll")));
-int __builtin_ctz(unsigned int x) __attribute__((alias("__tcc_builtin_ctz")));
-int __builtin_ctzl(unsigned long x) __attribute__((alias("__tcc_builtin_ctzl")));
-int __builtin_ctzll(unsigned long long x) __attribute__((alias("__tcc_builtin_ctzll")));
-int __builtin_clrsb(int x) __attribute__((alias("__tcc_builtin_clrsb")));
-int __builtin_clrsbl(long x) __attribute__((alias("__tcc_builtin_clrsbl")));
-int __builtin_clrsbll(long long x) __attribute__((alias("__tcc_builtin_clrsbll")));
-int __builtin_popcount(unsigned int x) __attribute__((alias("__tcc_builtin_popcount")));
-int __builtin_popcountl(unsigned long x) __attribute__((alias("__tcc_builtin_popcountl")));
-int __builtin_popcountll(unsigned long long x) __attribute__((alias("__tcc_builtin_popcountll")));
-int __builtin_parity(unsigned int x) __attribute__((alias("__tcc_builtin_parity")));
-int __builtin_parityl(unsigned long x) __attribute__((alias("__tcc_builtin_parityl")));
-int __builtin_parityll(unsigned long long x) __attribute__((alias("__tcc_builtin_parityll")));
-#endif
diff --git a/tinycc/lib/dsohandle.c b/tinycc/lib/dsohandle.c
deleted file mode 100644
index 0993dbc..0000000
--- a/tinycc/lib/dsohandle.c
+++ /dev/null
@@ -1 +0,0 @@
-void * __dso_handle __attribute((visibility("hidden"))) = &__dso_handle;
diff --git a/tinycc/lib/lib-arm64.c b/tinycc/lib/lib-arm64.c
deleted file mode 100644
index 226827e..0000000
--- a/tinycc/lib/lib-arm64.c
+++ /dev/null
@@ -1,677 +0,0 @@
-/*
- * TCC runtime library for arm64.
- *
- * Copyright (c) 2015 Edmund Grimley Evans
- *
- * Copying and distribution of this file, with or without modification,
- * are permitted in any medium without royalty provided the copyright
- * notice and this notice are preserved. This file is offered as-is,
- * without any warranty.
- */
-
-#ifdef __TINYC__
-typedef signed char int8_t;
-typedef unsigned char uint8_t;
-typedef short int16_t;
-typedef unsigned short uint16_t;
-typedef int int32_t;
-typedef unsigned uint32_t;
-typedef long long int64_t;
-typedef unsigned long long uint64_t;
-void *memcpy(void*,void*,__SIZE_TYPE__);
-#else
-#include <stdint.h>
-#include <string.h>
-#endif
-
-#if !defined __riscv && !defined __APPLE__
-void __clear_cache(void *beg, void *end)
-{
- __arm64_clear_cache(beg, end);
-}
-#endif
-
-typedef struct {
- uint64_t x0, x1;
-} u128_t;
-
-static long double f3_zero(int sgn)
-{
- long double f;
- u128_t x = { 0, (uint64_t)sgn << 63 };
- memcpy(&f, &x, 16);
- return f;
-}
-
-static long double f3_infinity(int sgn)
-{
- long double f;
- u128_t x = { 0, (uint64_t)sgn << 63 | 0x7fff000000000000 };
- memcpy(&f, &x, 16);
- return f;
-}
-
-static long double f3_NaN(void)
-{
- long double f;
-#if 0
- // ARM's default NaN usually has just the top fraction bit set:
- u128_t x = { 0, 0x7fff800000000000 };
-#else
- // GCC's library sets all fraction bits:
- u128_t x = { -1, 0x7fffffffffffffff };
-#endif
- memcpy(&f, &x, 16);
- return f;
-}
-
-static int fp3_convert_NaN(long double *f, int sgn, u128_t mnt)
-{
- u128_t x = { mnt.x0,
- mnt.x1 | 0x7fff800000000000 | (uint64_t)sgn << 63 };
- memcpy(f, &x, 16);
- return 1;
-}
-
-static int fp3_detect_NaNs(long double *f,
- int a_sgn, int a_exp, u128_t a,
- int b_sgn, int b_exp, u128_t b)
-{
- // Detect signalling NaNs:
- if (a_exp == 32767 && (a.x0 | a.x1 << 16) && !(a.x1 >> 47 & 1))
- return fp3_convert_NaN(f, a_sgn, a);
- if (b_exp == 32767 && (b.x0 | b.x1 << 16) && !(b.x1 >> 47 & 1))
- return fp3_convert_NaN(f, b_sgn, b);
-
- // Detect quiet NaNs:
- if (a_exp == 32767 && (a.x0 | a.x1 << 16))
- return fp3_convert_NaN(f, a_sgn, a);
- if (b_exp == 32767 && (b.x0 | b.x1 << 16))
- return fp3_convert_NaN(f, b_sgn, b);
-
- return 0;
-}
-
-static void f3_unpack(int *sgn, int32_t *exp, u128_t *mnt, long double f)
-{
- u128_t x;
- memcpy(&x, &f, 16);
- *sgn = x.x1 >> 63;
- *exp = x.x1 >> 48 & 32767;
- x.x1 = x.x1 << 16 >> 16;
- if (*exp)
- x.x1 |= (uint64_t)1 << 48;
- else
- *exp = 1;
- *mnt = x;
-}
-
-static u128_t f3_normalise(int32_t *exp, u128_t mnt)
-{
- int sh;
- if (!(mnt.x0 | mnt.x1))
- return mnt;
- if (!mnt.x1) {
- mnt.x1 = mnt.x0;
- mnt.x0 = 0;
- *exp -= 64;
- }
- for (sh = 32; sh; sh >>= 1) {
- if (!(mnt.x1 >> (64 - sh))) {
- mnt.x1 = mnt.x1 << sh | mnt.x0 >> (64 - sh);
- mnt.x0 = mnt.x0 << sh;
- *exp -= sh;
- }
- }
- return mnt;
-}
-
-static u128_t f3_sticky_shift(int32_t sh, u128_t x)
-{
- if (sh >= 128) {
- x.x0 = !!(x.x0 | x.x1);
- x.x1 = 0;
- return x;
- }
- if (sh >= 64) {
- x.x0 = x.x1 | !!x.x0;
- x.x1 = 0;
- sh -= 64;
- }
- if (sh > 0) {
- x.x0 = x.x0 >> sh | x.x1 << (64 - sh) | !!(x.x0 << (64 - sh));
- x.x1 = x.x1 >> sh;
- }
- return x;
-}
-
-static long double f3_round(int sgn, int32_t exp, u128_t x)
-{
- long double f;
- int error;
-
- if (exp > 0) {
- x = f3_sticky_shift(13, x);
- }
- else {
- x = f3_sticky_shift(14 - exp, x);
- exp = 0;
- }
-
- error = x.x0 & 3;
- x.x0 = x.x0 >> 2 | x.x1 << 62;
- x.x1 = x.x1 >> 2;
-
- if (error == 3 || ((error == 2) & (x.x0 & 1))) {
- if (!++x.x0) {
- ++x.x1;
- if (x.x1 == (uint64_t)1 << 48)
- exp = 1;
- else if (x.x1 == (uint64_t)1 << 49) {
- ++exp;
- x.x0 = x.x0 >> 1 | x.x1 << 63;
- x.x1 = x.x1 >> 1;
- }
- }
- }
-
- if (exp >= 32767)
- return f3_infinity(sgn);
-
- x.x1 = x.x1 << 16 >> 16 | (uint64_t)exp << 48 | (uint64_t)sgn << 63;
- memcpy(&f, &x, 16);
- return f;
-}
-
-static long double f3_add(long double fa, long double fb, int neg)
-{
- u128_t a, b, x;
- int32_t a_exp, b_exp, x_exp;
- int a_sgn, b_sgn, x_sgn;
- long double fx;
-
- f3_unpack(&a_sgn, &a_exp, &a, fa);
- f3_unpack(&b_sgn, &b_exp, &b, fb);
-
- if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
- return fx;
-
- b_sgn ^= neg;
-
- // Handle infinities and zeroes:
- if (a_exp == 32767 && b_exp == 32767 && a_sgn != b_sgn)
- return f3_NaN();
- if (a_exp == 32767)
- return f3_infinity(a_sgn);
- if (b_exp == 32767)
- return f3_infinity(b_sgn);
- if (!(a.x0 | a.x1 | b.x0 | b.x1))
- return f3_zero(a_sgn & b_sgn);
-
- a.x1 = a.x1 << 3 | a.x0 >> 61;
- a.x0 = a.x0 << 3;
- b.x1 = b.x1 << 3 | b.x0 >> 61;
- b.x0 = b.x0 << 3;
-
- if (a_exp <= b_exp) {
- a = f3_sticky_shift(b_exp - a_exp, a);
- a_exp = b_exp;
- }
- else {
- b = f3_sticky_shift(a_exp - b_exp, b);
- b_exp = a_exp;
- }
-
- x_sgn = a_sgn;
- x_exp = a_exp;
- if (a_sgn == b_sgn) {
- x.x0 = a.x0 + b.x0;
- x.x1 = a.x1 + b.x1 + (x.x0 < a.x0);
- }
- else {
- x.x0 = a.x0 - b.x0;
- x.x1 = a.x1 - b.x1 - (x.x0 > a.x0);
- if (x.x1 >> 63) {
- x_sgn ^= 1;
- x.x0 = -x.x0;
- x.x1 = -x.x1 - !!x.x0;
- }
- }
-
- if (!(x.x0 | x.x1))
- return f3_zero(0);
-
- x = f3_normalise(&x_exp, x);
-
- return f3_round(x_sgn, x_exp + 12, x);
-}
-
-long double __addtf3(long double a, long double b)
-{
- return f3_add(a, b, 0);
-}
-
-long double __subtf3(long double a, long double b)
-{
- return f3_add(a, b, 1);
-}
-
-long double __multf3(long double fa, long double fb)
-{
- u128_t a, b, x;
- int32_t a_exp, b_exp, x_exp;
- int a_sgn, b_sgn, x_sgn;
- long double fx;
-
- f3_unpack(&a_sgn, &a_exp, &a, fa);
- f3_unpack(&b_sgn, &b_exp, &b, fb);
-
- if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
- return fx;
-
- // Handle infinities and zeroes:
- if ((a_exp == 32767 && !(b.x0 | b.x1)) ||
- (b_exp == 32767 && !(a.x0 | a.x1)))
- return f3_NaN();
- if (a_exp == 32767 || b_exp == 32767)
- return f3_infinity(a_sgn ^ b_sgn);
- if (!(a.x0 | a.x1) || !(b.x0 | b.x1))
- return f3_zero(a_sgn ^ b_sgn);
-
- a = f3_normalise(&a_exp, a);
- b = f3_normalise(&b_exp, b);
-
- x_sgn = a_sgn ^ b_sgn;
- x_exp = a_exp + b_exp - 16352;
-
- {
- // Convert to base (1 << 30), discarding bottom 6 bits, which are zero,
- // so there are (32, 30, 30, 30) bits in (a3, a2, a1, a0):
- uint64_t a0 = a.x0 << 28 >> 34;
- uint64_t b0 = b.x0 << 28 >> 34;
- uint64_t a1 = a.x0 >> 36 | a.x1 << 62 >> 34;
- uint64_t b1 = b.x0 >> 36 | b.x1 << 62 >> 34;
- uint64_t a2 = a.x1 << 32 >> 34;
- uint64_t b2 = b.x1 << 32 >> 34;
- uint64_t a3 = a.x1 >> 32;
- uint64_t b3 = b.x1 >> 32;
- // Use 16 small multiplications and additions that do not overflow:
- uint64_t x0 = a0 * b0;
- uint64_t x1 = (x0 >> 30) + a0 * b1 + a1 * b0;
- uint64_t x2 = (x1 >> 30) + a0 * b2 + a1 * b1 + a2 * b0;
- uint64_t x3 = (x2 >> 30) + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
- uint64_t x4 = (x3 >> 30) + a1 * b3 + a2 * b2 + a3 * b1;
- uint64_t x5 = (x4 >> 30) + a2 * b3 + a3 * b2;
- uint64_t x6 = (x5 >> 30) + a3 * b3;
- // We now have (64, 30, 30, ...) bits in (x6, x5, x4, ...).
- // Take the top 128 bits, setting bottom bit if any lower bits were set:
- uint64_t y0 = (x5 << 34 | x4 << 34 >> 30 | x3 << 34 >> 60 |
- !!(x3 << 38 | (x2 | x1 | x0) << 34));
- uint64_t y1 = x6;
- // Top bit may be zero. Renormalise:
- if (!(y1 >> 63)) {
- y1 = y1 << 1 | y0 >> 63;
- y0 = y0 << 1;
- --x_exp;
- }
- x.x0 = y0;
- x.x1 = y1;
- }
-
- return f3_round(x_sgn, x_exp, x);
-}
-
-long double __divtf3(long double fa, long double fb)
-{
- u128_t a, b, x;
- int32_t a_exp, b_exp, x_exp;
- int a_sgn, b_sgn, x_sgn, i;
- long double fx;
-
- f3_unpack(&a_sgn, &a_exp, &a, fa);
- f3_unpack(&b_sgn, &b_exp, &b, fb);
-
- if (fp3_detect_NaNs(&fx, a_sgn, a_exp, a, b_sgn, b_exp, b))
- return fx;
-
- // Handle infinities and zeroes:
- if ((a_exp == 32767 && b_exp == 32767) ||
- (!(a.x0 | a.x1) && !(b.x0 | b.x1)))
- return f3_NaN();
- if (a_exp == 32767 || !(b.x0 | b.x1))
- return f3_infinity(a_sgn ^ b_sgn);
- if (!(a.x0 | a.x1) || b_exp == 32767)
- return f3_zero(a_sgn ^ b_sgn);
-
- a = f3_normalise(&a_exp, a);
- b = f3_normalise(&b_exp, b);
-
- x_sgn = a_sgn ^ b_sgn;
- x_exp = a_exp - b_exp + 16395;
-
- a.x0 = a.x0 >> 1 | a.x1 << 63;
- a.x1 = a.x1 >> 1;
- b.x0 = b.x0 >> 1 | b.x1 << 63;
- b.x1 = b.x1 >> 1;
- x.x0 = 0;
- x.x1 = 0;
- for (i = 0; i < 116; i++) {
- x.x1 = x.x1 << 1 | x.x0 >> 63;
- x.x0 = x.x0 << 1;
- if (a.x1 > b.x1 || (a.x1 == b.x1 && a.x0 >= b.x0)) {
- a.x1 = a.x1 - b.x1 - (a.x0 < b.x0);
- a.x0 = a.x0 - b.x0;
- x.x0 |= 1;
- }
- a.x1 = a.x1 << 1 | a.x0 >> 63;
- a.x0 = a.x0 << 1;
- }
- x.x0 |= !!(a.x0 | a.x1);
-
- x = f3_normalise(&x_exp, x);
-
- return f3_round(x_sgn, x_exp, x);
-}
-
-long double __extendsftf2(float f)
-{
- long double fx;
- u128_t x;
- uint32_t a;
- uint64_t aa;
- memcpy(&a, &f, 4);
- aa = a;
- x.x0 = 0;
- if (!(a << 1))
- x.x1 = aa << 32;
- else if (a << 1 >> 24 == 255)
- x.x1 = (0x7fff000000000000 | aa >> 31 << 63 | aa << 41 >> 16 |
- (uint64_t)!!(a << 9) << 47);
- else if (a << 1 >> 24 == 0) {
- uint64_t adj = 0;
- while (!(a << 1 >> 1 >> (23 - adj)))
- adj++;
- x.x1 = aa >> 31 << 63 | (16256 - adj + 1) << 48 | aa << adj << 41 >> 16;
- } else
- x.x1 = (aa >> 31 << 63 | ((aa >> 23 & 255) + 16256) << 48 |
- aa << 41 >> 16);
- memcpy(&fx, &x, 16);
- return fx;
-}
-
-long double __extenddftf2(double f)
-{
- long double fx;
- u128_t x;
- uint64_t a;
- memcpy(&a, &f, 8);
- x.x0 = a << 60;
- if (!(a << 1))
- x.x1 = a;
- else if (a << 1 >> 53 == 2047)
- x.x1 = (0x7fff000000000000 | a >> 63 << 63 | a << 12 >> 16 |
- (uint64_t)!!(a << 12) << 47);
- else if (a << 1 >> 53 == 0) {
- uint64_t adj = 0;
- while (!(a << 1 >> 1 >> (52 - adj)))
- adj++;
- x.x0 <<= adj;
- x.x1 = a >> 63 << 63 | (15360 - adj + 1) << 48 | a << adj << 12 >> 16;
- } else
- x.x1 = a >> 63 << 63 | ((a >> 52 & 2047) + 15360) << 48 | a << 12 >> 16;
- memcpy(&fx, &x, 16);
- return fx;
-}
-
-float __trunctfsf2(long double f)
-{
- u128_t mnt;
- int32_t exp;
- int sgn;
- uint32_t x;
- float fx;
-
- f3_unpack(&sgn, &exp, &mnt, f);
-
- if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
- x = 0x7fc00000 | (uint32_t)sgn << 31 | (mnt.x1 >> 25 & 0x007fffff);
- else if (exp > 16510)
- x = 0x7f800000 | (uint32_t)sgn << 31;
- else if (exp < 16233)
- x = (uint32_t)sgn << 31;
- else {
- exp -= 16257;
- x = mnt.x1 >> 23 | !!(mnt.x0 | mnt.x1 << 41);
- if (exp < 0) {
- x = x >> -exp | !!(x << (32 + exp));
- exp = 0;
- }
- if ((x & 3) == 3 || (x & 7) == 6)
- x += 4;
- x = ((x >> 2) + (exp << 23)) | (uint32_t)sgn << 31;
- }
- memcpy(&fx, &x, 4);
- return fx;
-}
-
-double __trunctfdf2(long double f)
-{
- u128_t mnt;
- int32_t exp;
- int sgn;
- uint64_t x;
- double fx;
-
- f3_unpack(&sgn, &exp, &mnt, f);
-
- if (exp == 32767 && (mnt.x0 | mnt.x1 << 16))
- x = (0x7ff8000000000000 | (uint64_t)sgn << 63 |
- mnt.x1 << 16 >> 12 | mnt.x0 >> 60);
- else if (exp > 17406)
- x = 0x7ff0000000000000 | (uint64_t)sgn << 63;
- else if (exp < 15308)
- x = (uint64_t)sgn << 63;
- else {
- exp -= 15361;
- x = mnt.x1 << 6 | mnt.x0 >> 58 | !!(mnt.x0 << 6);
- if (exp < 0) {
- x = x >> -exp | !!(x << (64 + exp));
- exp = 0;
- }
- if ((x & 3) == 3 || (x & 7) == 6)
- x += 4;
- x = ((x >> 2) + ((uint64_t)exp << 52)) | (uint64_t)sgn << 63;
- }
- memcpy(&fx, &x, 8);
- return fx;
-}
-
-int32_t __fixtfsi(long double fa)
-{
- u128_t a;
- int32_t a_exp;
- int a_sgn;
- int32_t x;
- f3_unpack(&a_sgn, &a_exp, &a, fa);
- if (a_exp < 16369)
- return 0;
- if (a_exp > 16413)
- return a_sgn ? -0x80000000 : 0x7fffffff;
- x = a.x1 >> (16431 - a_exp);
- return a_sgn ? -x : x;
-}
-
-int64_t __fixtfdi(long double fa)
-{
- u128_t a;
- int32_t a_exp;
- int a_sgn;
- int64_t x;
- f3_unpack(&a_sgn, &a_exp, &a, fa);
- if (a_exp < 16383)
- return 0;
- if (a_exp > 16445)
- return a_sgn ? -0x8000000000000000 : 0x7fffffffffffffff;
- x = (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp);
- return a_sgn ? -x : x;
-}
-
-uint32_t __fixunstfsi(long double fa)
-{
- u128_t a;
- int32_t a_exp;
- int a_sgn;
- f3_unpack(&a_sgn, &a_exp, &a, fa);
- if (a_sgn || a_exp < 16369)
- return 0;
- if (a_exp > 16414)
- return -1;
- return a.x1 >> (16431 - a_exp);
-}
-
-uint64_t __fixunstfdi(long double fa)
-{
- u128_t a;
- int32_t a_exp;
- int a_sgn;
- f3_unpack(&a_sgn, &a_exp, &a, fa);
- if (a_sgn || a_exp < 16383)
- return 0;
- if (a_exp > 16446)
- return -1;
- return (a.x1 << 15 | a.x0 >> 49) >> (16446 - a_exp);
-}
-
-long double __floatsitf(int32_t a)
-{
- int sgn = 0;
- int exp = 16414;
- uint32_t mnt = a;
- u128_t x = { 0, 0 };
- long double f;
- int i;
- if (a) {
- if (a < 0) {
- sgn = 1;
- mnt = -mnt;
- }
- for (i = 16; i; i >>= 1)
- if (!(mnt >> (32 - i))) {
- mnt <<= i;
- exp -= i;
- }
- x.x1 = ((uint64_t)sgn << 63 | (uint64_t)exp << 48 |
- (uint64_t)(mnt << 1) << 16);
- }
- memcpy(&f, &x, 16);
- return f;
-}
-
-long double __floatditf(int64_t a)
-{
- int sgn = 0;
- int exp = 16446;
- uint64_t mnt = a;
- u128_t x = { 0, 0 };
- long double f;
- int i;
- if (a) {
- if (a < 0) {
- sgn = 1;
- mnt = -mnt;
- }
- for (i = 32; i; i >>= 1)
- if (!(mnt >> (64 - i))) {
- mnt <<= i;
- exp -= i;
- }
- x.x0 = mnt << 49;
- x.x1 = (uint64_t)sgn << 63 | (uint64_t)exp << 48 | mnt << 1 >> 16;
- }
- memcpy(&f, &x, 16);
- return f;
-}
-
-long double __floatunsitf(uint32_t a)
-{
- int exp = 16414;
- uint32_t mnt = a;
- u128_t x = { 0, 0 };
- long double f;
- int i;
- if (a) {
- for (i = 16; i; i >>= 1)
- if (!(mnt >> (32 - i))) {
- mnt <<= i;
- exp -= i;
- }
- x.x1 = (uint64_t)exp << 48 | (uint64_t)(mnt << 1) << 16;
- }
- memcpy(&f, &x, 16);
- return f;
-}
-
-long double __floatunditf(uint64_t a)
-{
- int exp = 16446;
- uint64_t mnt = a;
- u128_t x = { 0, 0 };
- long double f;
- int i;
- if (a) {
- for (i = 32; i; i >>= 1)
- if (!(mnt >> (64 - i))) {
- mnt <<= i;
- exp -= i;
- }
- x.x0 = mnt << 49;
- x.x1 = (uint64_t)exp << 48 | mnt << 1 >> 16;
- }
- memcpy(&f, &x, 16);
- return f;
-}
-
-static int f3_cmp(long double fa, long double fb)
-{
- u128_t a, b;
- memcpy(&a, &fa, 16);
- memcpy(&b, &fb, 16);
- return (!(a.x0 | a.x1 << 1 | b.x0 | b.x1 << 1) ? 0 :
- ((a.x1 << 1 >> 49 == 0x7fff && (a.x0 | a.x1 << 16)) ||
- (b.x1 << 1 >> 49 == 0x7fff && (b.x0 | b.x1 << 16))) ? 2 :
- a.x1 >> 63 != b.x1 >> 63 ? (int)(b.x1 >> 63) - (int)(a.x1 >> 63) :
- a.x1 < b.x1 ? (int)(a.x1 >> 63 << 1) - 1 :
- a.x1 > b.x1 ? 1 - (int)(a.x1 >> 63 << 1) :
- a.x0 < b.x0 ? (int)(a.x1 >> 63 << 1) - 1 :
- b.x0 < a.x0 ? 1 - (int)(a.x1 >> 63 << 1) : 0);
-}
-
-int __eqtf2(long double a, long double b)
-{
- return !!f3_cmp(a, b);
-}
-
-int __netf2(long double a, long double b)
-{
- return !!f3_cmp(a, b);
-}
-
-int __lttf2(long double a, long double b)
-{
- return f3_cmp(a, b);
-}
-
-int __letf2(long double a, long double b)
-{
- return f3_cmp(a, b);
-}
-
-int __gttf2(long double a, long double b)
-{
- return -f3_cmp(b, a);
-}
-
-int __getf2(long double a, long double b)
-{
- return -f3_cmp(b, a);
-}
diff --git a/tinycc/lib/libtcc1.c b/tinycc/lib/libtcc1.c
deleted file mode 100644
index ae94af1..0000000
--- a/tinycc/lib/libtcc1.c
+++ /dev/null
@@ -1,641 +0,0 @@
-/* TCC runtime library.
- Parts of this code are (c) 2002 Fabrice Bellard
-
- Copyright (C) 1987, 1988, 1992, 1994, 1995 Free Software Foundation, Inc.
-
-This file is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file into combinations with other programs,
-and to distribute those combinations without any restriction coming
-from the use of this file. (The General Public License restrictions
-do apply in other respects; for example, they cover modification of
-the file, and distribution when not linked into a combine
-executable.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
-*/
-
-#define W_TYPE_SIZE 32
-#define BITS_PER_UNIT 8
-
-typedef int Wtype;
-typedef unsigned int UWtype;
-typedef unsigned int USItype;
-typedef long long DWtype;
-typedef unsigned long long UDWtype;
-
-struct DWstruct {
- Wtype low, high;
-};
-
-typedef union
-{
- struct DWstruct s;
- DWtype ll;
-} DWunion;
-
-typedef long double XFtype;
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
-/* the following deal with IEEE single-precision numbers */
-#define EXCESS 126
-#define SIGNBIT 0x80000000
-#define HIDDEN (1 << 23)
-#define SIGN(fp) ((fp) & SIGNBIT)
-#define EXP(fp) (((fp) >> 23) & 0xFF)
-#define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN)
-#define PACK(s,e,m) ((s) | ((e) << 23) | (m))
-
-/* the following deal with IEEE double-precision numbers */
-#define EXCESSD 1022
-#define HIDDEND (1 << 20)
-#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
-#define SIGND(fp) ((fp.l.upper) & SIGNBIT)
-#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \
- (fp.l.lower >> 22))
-#define HIDDEND_LL ((long long)1 << 52)
-#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
-#define PACKD_LL(s,e,m) (((long long)((s)+((e)<<20))<<32)|(m))
-
-/* the following deal with x86 long double-precision numbers */
-#define EXCESSLD 16382
-#define EXPLD(fp) (fp.l.upper & 0x7fff)
-#define SIGNLD(fp) ((fp.l.upper) & 0x8000)
-
-/* only for x86 */
-union ldouble_long {
- long double ld;
- struct {
- unsigned long long lower;
- unsigned short upper;
- } l;
-};
-
-union double_long {
- double d;
-#if 1
- struct {
- unsigned int lower;
- int upper;
- } l;
-#else
- struct {
- int upper;
- unsigned int lower;
- } l;
-#endif
- long long ll;
-};
-
-union float_long {
- float f;
- unsigned int l;
-};
-
-/* XXX: we don't support several builtin supports for now */
-#if !defined __x86_64__ && !defined __arm__
-
-/* XXX: use gcc/tcc intrinsic ? */
-#if defined __i386__
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
- __asm__ ("subl %5,%1\n\tsbbl %3,%0" \
- : "=r" ((USItype) (sh)), \
- "=&r" ((USItype) (sl)) \
- : "0" ((USItype) (ah)), \
- "g" ((USItype) (bh)), \
- "1" ((USItype) (al)), \
- "g" ((USItype) (bl)))
-#define umul_ppmm(w1, w0, u, v) \
- __asm__ ("mull %3" \
- : "=a" ((USItype) (w0)), \
- "=d" ((USItype) (w1)) \
- : "%0" ((USItype) (u)), \
- "rm" ((USItype) (v)))
-#define udiv_qrnnd(q, r, n1, n0, dv) \
- __asm__ ("divl %4" \
- : "=a" ((USItype) (q)), \
- "=d" ((USItype) (r)) \
- : "0" ((USItype) (n0)), \
- "1" ((USItype) (n1)), \
- "rm" ((USItype) (dv)))
-#define count_leading_zeros(count, x) \
- do { \
- USItype __cbtmp; \
- __asm__ ("bsrl %1,%0" \
- : "=r" (__cbtmp) : "rm" ((USItype) (x))); \
- (count) = __cbtmp ^ 31; \
- } while (0)
-#else
-#error unsupported CPU type
-#endif
-
-/* most of this code is taken from libgcc2.c from gcc */
-
-static UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
-{
- DWunion ww;
- DWunion nn, dd;
- DWunion rr;
- UWtype d0, d1, n0, n1, n2;
- UWtype q0, q1;
- UWtype b, bm;
-
- nn.ll = n;
- dd.ll = d;
-
- d0 = dd.s.low;
- d1 = dd.s.high;
- n0 = nn.s.low;
- n1 = nn.s.high;
-
-#if !defined(UDIV_NEEDS_NORMALIZATION)
- if (d1 == 0)
- {
- if (d0 > n1)
- {
- /* 0q = nn / 0D */
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
- q1 = 0;
-
- /* Remainder in n0. */
- }
- else
- {
- /* qq = NN / 0d */
-
- if (d0 == 0)
- d0 = 1 / d0; /* Divide intentionally by zero. */
-
- udiv_qrnnd (q1, n1, 0, n1, d0);
- udiv_qrnnd (q0, n0, n1, n0, d0);
-
- /* Remainder in n0. */
- }
-
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = 0;
- *rp = rr.ll;
- }
- }
-
-#else /* UDIV_NEEDS_NORMALIZATION */
-
- if (d1 == 0)
- {
- if (d0 > n1)
- {
- /* 0q = nn / 0D */
-
- count_leading_zeros (bm, d0);
-
- if (bm != 0)
- {
- /* Normalize, i.e. make the most significant bit of the
- denominator set. */
-
- d0 = d0 << bm;
- n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
- n0 = n0 << bm;
- }
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
- q1 = 0;
-
- /* Remainder in n0 >> bm. */
- }
- else
- {
- /* qq = NN / 0d */
-
- if (d0 == 0)
- d0 = 1 / d0; /* Divide intentionally by zero. */
-
- count_leading_zeros (bm, d0);
-
- if (bm == 0)
- {
- /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
- conclude (the most significant bit of n1 is set) /\ (the
- leading quotient digit q1 = 1).
-
- This special case is necessary, not an optimization.
- (Shifts counts of W_TYPE_SIZE are undefined.) */
-
- n1 -= d0;
- q1 = 1;
- }
- else
- {
- /* Normalize. */
-
- b = W_TYPE_SIZE - bm;
-
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- udiv_qrnnd (q1, n1, n2, n1, d0);
- }
-
- /* n1 != d0... */
-
- udiv_qrnnd (q0, n0, n1, n0, d0);
-
- /* Remainder in n0 >> bm. */
- }
-
- if (rp != 0)
- {
- rr.s.low = n0 >> bm;
- rr.s.high = 0;
- *rp = rr.ll;
- }
- }
-#endif /* UDIV_NEEDS_NORMALIZATION */
-
- else
- {
- if (d1 > n1)
- {
- /* 00 = nn / DD */
-
- q0 = 0;
- q1 = 0;
-
- /* Remainder in n1n0. */
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = n1;
- *rp = rr.ll;
- }
- }
- else
- {
- /* 0q = NN / dd */
-
- count_leading_zeros (bm, d1);
- if (bm == 0)
- {
- /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
- conclude (the most significant bit of n1 is set) /\ (the
- quotient digit q0 = 0 or 1).
-
- This special case is necessary, not an optimization. */
-
- /* The condition on the next line takes advantage of that
- n1 >= d1 (true due to program flow). */
- if (n1 > d1 || n0 >= d0)
- {
- q0 = 1;
- sub_ddmmss (n1, n0, n1, n0, d1, d0);
- }
- else
- q0 = 0;
-
- q1 = 0;
-
- if (rp != 0)
- {
- rr.s.low = n0;
- rr.s.high = n1;
- *rp = rr.ll;
- }
- }
- else
- {
- UWtype m1, m0;
- /* Normalize. */
-
- b = W_TYPE_SIZE - bm;
-
- d1 = (d1 << bm) | (d0 >> b);
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- udiv_qrnnd (q0, n1, n2, n1, d1);
- umul_ppmm (m1, m0, q0, d0);
-
- if (m1 > n1 || (m1 == n1 && m0 > n0))
- {
- q0--;
- sub_ddmmss (m1, m0, m1, m0, d1, d0);
- }
-
- q1 = 0;
-
- /* Remainder in (n1n0 - m1m0) >> bm. */
- if (rp != 0)
- {
- sub_ddmmss (n1, n0, n1, n0, m1, m0);
- rr.s.low = (n1 << b) | (n0 >> bm);
- rr.s.high = n1 >> bm;
- *rp = rr.ll;
- }
- }
- }
- }
-
- ww.s.low = q0;
- ww.s.high = q1;
- return ww.ll;
-}
-
-#define __negdi2(a) (-(a))
-
-long long __divdi3(long long u, long long v)
-{
- int c = 0;
- DWunion uu, vv;
- DWtype w;
-
- uu.ll = u;
- vv.ll = v;
-
- if (uu.s.high < 0) {
- c = ~c;
- uu.ll = __negdi2 (uu.ll);
- }
- if (vv.s.high < 0) {
- c = ~c;
- vv.ll = __negdi2 (vv.ll);
- }
- w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
- if (c)
- w = __negdi2 (w);
- return w;
-}
-
-long long __moddi3(long long u, long long v)
-{
- int c = 0;
- DWunion uu, vv;
- DWtype w;
-
- uu.ll = u;
- vv.ll = v;
-
- if (uu.s.high < 0) {
- c = ~c;
- uu.ll = __negdi2 (uu.ll);
- }
- if (vv.s.high < 0)
- vv.ll = __negdi2 (vv.ll);
-
- __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) &w);
- if (c)
- w = __negdi2 (w);
- return w;
-}
-
-unsigned long long __udivdi3(unsigned long long u, unsigned long long v)
-{
- return __udivmoddi4 (u, v, (UDWtype *) 0);
-}
-
-unsigned long long __umoddi3(unsigned long long u, unsigned long long v)
-{
- UDWtype w;
-
- __udivmoddi4 (u, v, &w);
- return w;
-}
-
-/* XXX: fix tcc's code generator to do this instead */
-long long __ashrdi3(long long a, int b)
-{
-#ifdef __TINYC__
- DWunion u;
- u.ll = a;
- if (b >= 32) {
- u.s.low = u.s.high >> (b - 32);
- u.s.high = u.s.high >> 31;
- } else if (b != 0) {
- u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b));
- u.s.high = u.s.high >> b;
- }
- return u.ll;
-#else
- return a >> b;
-#endif
-}
-
-/* XXX: fix tcc's code generator to do this instead */
-unsigned long long __lshrdi3(unsigned long long a, int b)
-{
-#ifdef __TINYC__
- DWunion u;
- u.ll = a;
- if (b >= 32) {
- u.s.low = (unsigned)u.s.high >> (b - 32);
- u.s.high = 0;
- } else if (b != 0) {
- u.s.low = ((unsigned)u.s.low >> b) | (u.s.high << (32 - b));
- u.s.high = (unsigned)u.s.high >> b;
- }
- return u.ll;
-#else
- return a >> b;
-#endif
-}
-
-/* XXX: fix tcc's code generator to do this instead */
-long long __ashldi3(long long a, int b)
-{
-#ifdef __TINYC__
- DWunion u;
- u.ll = a;
- if (b >= 32) {
- u.s.high = (unsigned)u.s.low << (b - 32);
- u.s.low = 0;
- } else if (b != 0) {
- u.s.high = ((unsigned)u.s.high << b) | ((unsigned)u.s.low >> (32 - b));
- u.s.low = (unsigned)u.s.low << b;
- }
- return u.ll;
-#else
- return a << b;
-#endif
-}
-
-#endif /* !__x86_64__ */
-
-/* XXX: fix tcc's code generator to do this instead */
-float __floatundisf(unsigned long long a)
-{
- DWunion uu;
- XFtype r;
-
- uu.ll = a;
- if (uu.s.high >= 0) {
- return (float)uu.ll;
- } else {
- r = (XFtype)uu.ll;
- r += 18446744073709551616.0;
- return (float)r;
- }
-}
-
-double __floatundidf(unsigned long long a)
-{
- DWunion uu;
- XFtype r;
-
- uu.ll = a;
- if (uu.s.high >= 0) {
- return (double)uu.ll;
- } else {
- r = (XFtype)uu.ll;
- r += 18446744073709551616.0;
- return (double)r;
- }
-}
-
-long double __floatundixf(unsigned long long a)
-{
- DWunion uu;
- XFtype r;
-
- uu.ll = a;
- if (uu.s.high >= 0) {
- return (long double)uu.ll;
- } else {
- r = (XFtype)uu.ll;
- r += 18446744073709551616.0;
- return (long double)r;
- }
-}
-
-unsigned long long __fixunssfdi (float a1)
-{
- register union float_long fl1;
- register int exp;
- register unsigned long long l;
-
- fl1.f = a1;
-
- if (fl1.l == 0)
- return (0);
-
- exp = EXP (fl1.l) - EXCESS - 24;
- l = MANT(fl1.l);
-
- if (exp >= 41)
- return 1ULL << 63;
- else if (exp >= 0)
- l <<= exp;
- else if (exp >= -23)
- l >>= -exp;
- else
- return 0;
- if (SIGN(fl1.l))
- l = (unsigned long long)-l;
- return l;
-}
-
-long long __fixsfdi (float a1)
-{
- long long ret; int s;
- ret = __fixunssfdi((s = a1 >= 0) ? a1 : -a1);
- return s ? ret : -ret;
-}
-
-unsigned long long __fixunsdfdi (double a1)
-{
- register union double_long dl1;
- register int exp;
- register unsigned long long l;
-
- dl1.d = a1;
-
- if (dl1.ll == 0)
- return (0);
-
- exp = EXPD (dl1) - EXCESSD - 53;
- l = MANTD_LL(dl1);
-
- if (exp >= 12)
- return 1ULL << 63; /* overflow result (like gcc, somewhat) */
- else if (exp >= 0)
- l <<= exp;
- else if (exp >= -52)
- l >>= -exp;
- else
- return 0;
- if (SIGND(dl1))
- l = (unsigned long long)-l;
- return l;
-}
-
-long long __fixdfdi (double a1)
-{
- long long ret; int s;
- ret = __fixunsdfdi((s = a1 >= 0) ? a1 : -a1);
- return s ? ret : -ret;
-}
-
-#ifndef __arm__
-unsigned long long __fixunsxfdi (long double a1)
-{
- register union ldouble_long dl1;
- register int exp;
- register unsigned long long l;
-
- dl1.ld = a1;
-
- if (dl1.l.lower == 0 && dl1.l.upper == 0)
- return (0);
-
- exp = EXPLD (dl1) - EXCESSLD - 64;
- l = dl1.l.lower;
- if (exp > 0)
- return 1ULL << 63;
- if (exp < -63)
- return 0;
- l >>= -exp;
- if (SIGNLD(dl1))
- l = (unsigned long long)-l;
- return l;
-}
-
-long long __fixxfdi (long double a1)
-{
- long long ret; int s;
- ret = __fixunsxfdi((s = a1 >= 0) ? a1 : -a1);
- return s ? ret : -ret;
-}
-#endif /* !ARM */
-
-#if defined __x86_64__
-/* float constants used for unary minus operation */
-const float __mzerosf = -0.0;
-const double __mzerodf = -0.0;
-#endif
-
-#if defined _WIN64
-/* MSVC x64 intrinsic */
-void __faststorefence(void)
-{
- __asm__("lock; orl $0,(%rsp)");
-}
-#endif
diff --git a/tinycc/lib/stdatomic.c b/tinycc/lib/stdatomic.c
deleted file mode 100644
index bd8c0ce..0000000
--- a/tinycc/lib/stdatomic.c
+++ /dev/null
@@ -1,166 +0,0 @@
-// for libtcc1, avoid including files that are not part of tcc
-// #include <stdint.h>
-#define uint8_t unsigned char
-#define uint16_t unsigned short
-#define uint32_t unsigned int
-#define uint64_t unsigned long long
-#define bool _Bool
-#define false 0
-#define true 1
-#define __ATOMIC_RELAXED 0
-#define __ATOMIC_CONSUME 1
-#define __ATOMIC_ACQUIRE 2
-#define __ATOMIC_RELEASE 3
-#define __ATOMIC_ACQ_REL 4
-#define __ATOMIC_SEQ_CST 5
-typedef __SIZE_TYPE__ size_t;
-
-#if defined __i386__ || defined __x86_64__
-#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
- bool __atomic_compare_exchange_##MODE \
- (volatile void *atom, void *ref, TYPE xchg, \
- bool weak, int success_memorder, int failure_memorder) \
- { \
- TYPE rv; \
- TYPE cmp = *(TYPE *)ref; \
- __asm__ volatile( \
- "lock cmpxchg" SUFFIX " %2,%1\n" \
- : "=a" (rv), "+m" (*(TYPE *)atom) \
- : "q" (xchg), "0" (cmp) \
- : "memory" \
- ); \
- *(TYPE *)ref = rv; \
- return (rv == cmp); \
- }
-#else
-#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
- extern bool __atomic_compare_exchange_##MODE \
- (volatile void *atom, void *ref, TYPE xchg, \
- bool weak, int success_memorder, int failure_memorder);
-#endif
-
-#define ATOMIC_LOAD(TYPE, MODE) \
- TYPE __atomic_load_##MODE(const volatile void *atom, int memorder) \
- { \
- return *(volatile TYPE *)atom; \
- }
-
-#define ATOMIC_STORE(TYPE, MODE) \
- void __atomic_store_##MODE(volatile void *atom, TYPE value, int memorder) \
- { \
- *(volatile TYPE *)atom = value; \
- }
-
-#define ATOMIC_GEN_OP(TYPE, MODE, NAME, OP, RET) \
- TYPE __atomic_##NAME##_##MODE(volatile void *atom, TYPE value, int memorder) \
- { \
- TYPE xchg, cmp; \
- __atomic_load((TYPE *)atom, (TYPE *)&cmp, __ATOMIC_RELAXED); \
- do { \
- xchg = (OP); \
- } while (!__atomic_compare_exchange((TYPE *)atom, &cmp, &xchg, true, \
- __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)); \
- return RET; \
- }
-
-#define ATOMIC_EXCHANGE(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, exchange, value, cmp)
-#define ATOMIC_ADD_FETCH(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, add_fetch, (cmp + value), xchg)
-#define ATOMIC_SUB_FETCH(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, sub_fetch, (cmp - value), xchg)
-#define ATOMIC_AND_FETCH(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, and_fetch, (cmp & value), xchg)
-#define ATOMIC_OR_FETCH(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, or_fetch, (cmp | value), xchg)
-#define ATOMIC_XOR_FETCH(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, xor_fetch, (cmp ^ value), xchg)
-#define ATOMIC_NAND_FETCH(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, nand_fetch, ~(cmp & value), xchg)
-#define ATOMIC_FETCH_ADD(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, fetch_add, (cmp + value), cmp)
-#define ATOMIC_FETCH_SUB(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, fetch_sub, (cmp - value), cmp)
-#define ATOMIC_FETCH_AND(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, fetch_and, (cmp & value), cmp)
-#define ATOMIC_FETCH_OR(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, fetch_or, (cmp | value), cmp)
-#define ATOMIC_FETCH_XOR(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, fetch_xor, (cmp ^ value), cmp)
-#define ATOMIC_FETCH_NAND(TYPE, MODE) \
- ATOMIC_GEN_OP(TYPE, MODE, fetch_nand, ~(cmp & value), cmp)
-
-#define ATOMIC_GEN(TYPE, SIZE, SUFFIX) \
- ATOMIC_STORE(TYPE, SIZE) \
- ATOMIC_LOAD(TYPE, SIZE) \
- ATOMIC_COMPARE_EXCHANGE(TYPE, SIZE, SUFFIX) \
- ATOMIC_EXCHANGE(TYPE, SIZE) \
- ATOMIC_ADD_FETCH(TYPE, SIZE) \
- ATOMIC_SUB_FETCH(TYPE, SIZE) \
- ATOMIC_AND_FETCH(TYPE, SIZE) \
- ATOMIC_OR_FETCH(TYPE, SIZE) \
- ATOMIC_XOR_FETCH(TYPE, SIZE) \
- ATOMIC_NAND_FETCH(TYPE, SIZE) \
- ATOMIC_FETCH_ADD(TYPE, SIZE) \
- ATOMIC_FETCH_SUB(TYPE, SIZE) \
- ATOMIC_FETCH_AND(TYPE, SIZE) \
- ATOMIC_FETCH_OR(TYPE, SIZE) \
- ATOMIC_FETCH_XOR(TYPE, SIZE) \
- ATOMIC_FETCH_NAND(TYPE, SIZE)
-
-ATOMIC_GEN(uint8_t, 1, "b")
-ATOMIC_GEN(uint16_t, 2, "w")
-ATOMIC_GEN(uint32_t, 4, "l")
-#if defined __x86_64__ || defined __aarch64__ || defined __riscv
-ATOMIC_GEN(uint64_t, 8, "q")
-#endif
-
-/* uses alias to allow building with gcc/clang */
-#ifdef __TINYC__
-#define ATOMIC(x) __atomic_##x
-#else
-#define ATOMIC(x) __tcc_atomic_##x
-#endif
-
-void ATOMIC(signal_fence) (int memorder)
-{
-}
-
-void ATOMIC(thread_fence) (int memorder)
-{
-#if defined __i386__
- __asm__ volatile("lock orl $0, (%esp)");
-#elif defined __x86_64__
- __asm__ volatile("lock orq $0, (%rsp)");
-#elif defined __arm__
- __asm__ volatile(".int 0xee070fba"); // mcr p15, 0, r0, c7, c10, 5
-#elif defined __aarch64__
- __asm__ volatile(".int 0xd5033bbf"); // dmb ish
-#elif defined __riscv
- __asm__ volatile(".int 0x0ff0000f"); // fence iorw,iorw
-#endif
-}
-
-bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr)
-{
- bool ret;
-
- switch (size) {
- case 1: ret = true; break;
- case 2: ret = true; break;
- case 4: ret = true; break;
-#if defined __x86_64__ || defined __aarch64__ || defined __riscv
- case 8: ret = true; break;
-#else
- case 8: ret = false; break;
-#endif
- default: ret = false; break;
- }
- return ret;
-}
-
-#ifndef __TINYC__
-void __atomic_signal_fence(int memorder) __attribute__((alias("__tcc_atomic_signal_fence")));
-void __atomic_thread_fence(int memorder) __attribute__((alias("__tcc_atomic_thread_fence")));
-bool __atomic_is_lock_free(unsigned long size, const volatile void *ptr) __attribute__((alias("__tcc_atomic_is_lock_free")));
-#endif
diff --git a/tinycc/lib/tcov.c b/tinycc/lib/tcov.c
deleted file mode 100644
index 32b7d18..0000000
--- a/tinycc/lib/tcov.c
+++ /dev/null
@@ -1,428 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#ifndef _WIN32
-#include <unistd.h>
-#include <errno.h>
-#else
-#include <windows.h>
-#include <io.h>
-#endif
-
-/* section layout (all little endian):
- 32bit offset to executable/so file name
- filename \0
- function name \0
- align to 64 bits
- 64bit function start line
- 64bits end_line(28bits) / start_line(28bits) / flag=0xff(8bits)
- 64bits counter
- \0
- \0
- \0
- executable/so file name \0
- */
-
-typedef struct tcov_line {
- unsigned int fline;
- unsigned int lline;
- unsigned long long count;
-} tcov_line;
-
-typedef struct tcov_function {
- char *function;
- unsigned int first_line;
- unsigned int n_line;
- unsigned int m_line;
- tcov_line *line;
-} tcov_function;
-
-typedef struct tcov_file {
- char *filename;
- unsigned int n_func;
- unsigned int m_func;
- tcov_function *func;
- struct tcov_file *next;
-} tcov_file;
-
-static FILE *open_tcov_file (char *cov_filename)
-{
- int fd;
-#ifndef _WIN32
- struct flock lock;
-
- lock.l_type = F_WRLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0; /* Until EOF. */
- lock.l_pid = getpid ();
-#endif
- fd = open (cov_filename, O_RDWR | O_CREAT, 0666);
- if (fd < 0)
- return NULL;
-
-#ifndef _WIN32
- while (fcntl (fd, F_SETLKW, &lock) && errno == EINTR)
- continue;
-#else
- {
- OVERLAPPED overlapped = { 0 };
- LockFileEx((HANDLE)_get_osfhandle(fd), LOCKFILE_EXCLUSIVE_LOCK,
- 0, 1, 0, &overlapped);
- }
-#endif
-
- return fdopen (fd, "r+");
-}
-
-static unsigned long long get_value(unsigned char *p, int size)
-{
- unsigned long long value = 0;
-
- p += size;
- while (size--)
- value = (value << 8) | *--p;
- return value;
-}
-
-static int sort_func (const void *p, const void *q)
-{
- const tcov_function *pp = (const tcov_function *) p;
- const tcov_function *pq = (const tcov_function *) q;
-
- return pp->first_line > pq->first_line ? 1 :
- pp->first_line < pq->first_line ? -1 : 0;
-}
-
-static int sort_line (const void *p, const void *q)
-{
- const tcov_line *pp = (const tcov_line *) p;
- const tcov_line *pq = (const tcov_line *) q;
-
- return pp->fline > pq->fline ? 1 :
- pp->fline < pq->fline ? -1 :
- pp->count < pq->count ? 1 :
- pp->count > pq->count ? -1 : 0;
-}
-
-/* sort to let inline functions work */
-static tcov_file *sort_test_coverage (unsigned char *p)
-{
- int i, j, k;
- unsigned char *start = p;
- tcov_file *file = NULL;
- tcov_file *nfile;
-
- p += 4;
- while (*p) {
- char *filename = (char *)p;
- size_t len = strlen (filename);
-
- nfile = file;
- while (nfile) {
- if (strcmp (nfile->filename, filename) == 0)
- break;
- nfile = nfile->next;
- }
- if (nfile == NULL) {
- nfile = malloc (sizeof(tcov_file));
- if (nfile == NULL) {
- fprintf (stderr, "Malloc error test_coverage\n");
- return file;
- }
- nfile->filename = filename;
- nfile->n_func = 0;
- nfile->m_func = 0;
- nfile->func = NULL;
- nfile->next = NULL;
- if (file == NULL)
- file = nfile;
- else {
- tcov_file *lfile = file;
-
- while (lfile->next)
- lfile = lfile->next;
- lfile->next = nfile;
- }
- }
- p += len + 1;
- while (*p) {
- int i;
- char *function = (char *)p;
- tcov_function *func;
-
- p += strlen (function) + 1;
- p += -(p - start) & 7;
- for (i = 0; i < nfile->n_func; i++) {
- func = &nfile->func[i];
- if (strcmp (func->function, function) == 0)
- break;
- }
- if (i == nfile->n_func) {
- if (nfile->n_func >= nfile->m_func) {
- nfile->m_func = nfile->m_func == 0 ? 4 : nfile->m_func * 2;
- nfile->func = realloc (nfile->func,
- nfile->m_func *
- sizeof (tcov_function));
- if (nfile->func == NULL) {
- fprintf (stderr, "Realloc error test_coverage\n");
- return file;
- }
- }
- func = &nfile->func[nfile->n_func++];
- func->function = function;
- func->first_line = get_value (p, 8);
- func->n_line = 0;
- func->m_line = 0;
- func->line = NULL;
- }
- p += 8;
- while (*p) {
- tcov_line *line;
- unsigned long long val;
-
- if (func->n_line >= func->m_line) {
- func->m_line = func->m_line == 0 ? 4 : func->m_line * 2;
- func->line = realloc (func->line,
- func->m_line * sizeof (tcov_line));
- if (func->line == NULL) {
- fprintf (stderr, "Realloc error test_coverage\n");
- return file;
- }
- }
- line = &func->line[func->n_line++];
- val = get_value (p, 8);
- line->fline = (val >> 8) & 0xfffffffULL;
- line->lline = val >> 36;
- line->count = get_value (p + 8, 8);
- p += 16;
- }
- p++;
- }
- p++;
- }
- nfile = file;
- while (nfile) {
- qsort (nfile->func, nfile->n_func, sizeof (tcov_function), sort_func);
- for (i = 0; i < nfile->n_func; i++) {
- tcov_function *func = &nfile->func[i];
- qsort (func->line, func->n_line, sizeof (tcov_line), sort_line);
- }
- nfile = nfile->next;
- }
- return file;
-}
-
-/* merge with previous tcov file */
-static void merge_test_coverage (tcov_file *file, FILE *fp,
- unsigned int *pruns)
-{
- unsigned int runs;
- char *p;
- char str[10000];
-
- *pruns = 1;
- if (fp == NULL)
- return;
- if (fgets(str, sizeof(str), fp) &&
- (p = strrchr (str, ':')) &&
- (sscanf (p + 1, "%u", &runs) == 1))
- *pruns = runs + 1;
- while (file) {
- int i;
- size_t len = strlen (file->filename);
-
- while (fgets(str, sizeof(str), fp) &&
- (p = strstr(str, "0:File:")) == NULL) {}
- if ((p = strstr(str, "0:File:")) == NULL ||
- strncmp (p + strlen("0:File:"), file->filename, len) != 0 ||
- p[strlen("0:File:") + len] != ' ')
- break;
- for (i = 0; i < file->n_func; i++) {
- int j;
- tcov_function *func = &file->func[i];
- unsigned int next_zero = 0;
- unsigned int curline = 0;
-
- for (j = 0; j < func->n_line; j++) {
- tcov_line *line = &func->line[j];
- unsigned int fline = line->fline;
- unsigned long long count;
- unsigned int tmp;
- char c;
-
- while (curline < fline &&
- fgets(str, sizeof(str), fp))
- if ((p = strchr(str, ':')) &&
- sscanf (p + 1, "%u", &tmp) == 1)
- curline = tmp;
- if (sscanf (str, "%llu%c\n", &count, &c) == 2) {
- if (next_zero == 0)
- line->count += count;
- next_zero = c == '*';
- }
- }
- }
- file = file->next;
- }
-}
-
-/* store tcov data in file */
-void __store_test_coverage (unsigned char * p)
-{
- int i, j;
- unsigned int files;
- unsigned int funcs;
- unsigned int blocks;
- unsigned int blocks_run;
- unsigned int runs;
- char *cov_filename = (char *)p + get_value (p, 4);
- FILE *fp;
- char *q;
- tcov_file *file;
- tcov_file *nfile;
- tcov_function *func;
-
- fp = open_tcov_file (cov_filename);
- if (fp == NULL) {
- fprintf (stderr, "Cannot create coverage file: %s\n", cov_filename);
- return;
- }
- file = sort_test_coverage (p);
- merge_test_coverage (file, fp, &runs);
- fseek (fp, 0, SEEK_SET);
- fprintf (fp, " -: 0:Runs:%u\n", runs);
- files = 0;
- funcs = 0;
- blocks = 0;
- blocks_run = 0;
- nfile = file;
- while (nfile) {
- files++;
- for (i = 0; i < nfile->n_func; i++) {
- func = &nfile->func[i];
- funcs++;
- for (j = 0; j < func->n_line; j++) {
- blocks++;
- blocks_run += func->line[j].count != 0;
- }
- }
- nfile = nfile->next;
- }
- if (blocks == 0)
- blocks = 1;
- fprintf (fp, " -: 0:All:%s Files:%u Functions:%u %.02f%%\n",
- cov_filename, files, funcs, 100.0 * (double) blocks_run / blocks);
- nfile = file;
- while (nfile) {
- FILE *src = fopen (nfile->filename, "r");
- unsigned int curline = 1;
- char str[10000];
-
- if (src == NULL)
- goto next;
- funcs = 0;
- blocks = 0;
- blocks_run = 0;
- for (i = 0; i < nfile->n_func; i++) {
- func = &nfile->func[i];
- funcs++;
- for (j = 0; j < func->n_line; j++) {
- blocks++;
- blocks_run += func->line[j].count != 0;
- }
- }
- if (blocks == 0)
- blocks = 1;
- fprintf (fp, " -: 0:File:%s Functions:%u %.02f%%\n",
- nfile->filename, funcs, 100.0 * (double) blocks_run / blocks);
- for (i = 0; i < nfile->n_func; i++) {
- func = &nfile->func[i];
-
- while (curline < func->first_line)
- if (fgets(str, sizeof(str), src))
- fprintf (fp, " -:%5u:%s", curline++, str);
- blocks = 0;
- blocks_run = 0;
- for (j = 0; j < func->n_line; j++) {
- blocks++;
- blocks_run += func->line[j].count != 0;
- }
- if (blocks == 0)
- blocks = 1;
- fprintf (fp, " -: 0:Function:%s %.02f%%\n",
- func->function, 100.0 * (double) blocks_run / blocks);
-#if 0
- for (j = 0; j < func->n_line; j++) {
- unsigned int fline = func->line[j].fline;
- unsigned int lline = func->line[j].lline;
- unsigned long long count = func->line[j].count;
-
- fprintf (fp, "%u %u %llu\n", fline, lline, count);
- }
-#endif
- for (j = 0; j < func->n_line;) {
- unsigned int fline = func->line[j].fline;
- unsigned int lline = func->line[j].lline;
- unsigned long long count = func->line[j].count;
- unsigned int has_zero = 0;
- unsigned int same_line = fline == lline;
-
- j++;
- while (j < func->n_line) {
- unsigned int nfline = func->line[j].fline;
- unsigned int nlline = func->line[j].lline;
- unsigned long long ncount = func->line[j].count;
-
- if (fline == nfline) {
- if (ncount == 0)
- has_zero = 1;
- else if (ncount > count)
- count = ncount;
- same_line = nfline == nlline;
- lline = nlline;
- j++;
- }
- else
- break;
- }
- if (same_line)
- lline++;
-
- while (curline < fline)
- if (fgets(str, sizeof(str), src))
- fprintf (fp, " -:%5u:%s", curline++, str);
- while (curline < lline &&
- fgets(str, sizeof(str), src)) {
- if (count == 0)
- fprintf (fp, " #####:%5u:%s",
- curline, str);
- else if (has_zero)
- fprintf (fp, "%8llu*:%5u:%s",
- count, curline, str);
- else
- fprintf (fp, "%9llu:%5u:%s",
- count, curline, str);
- curline++;
- }
- }
- }
- while (fgets(str, sizeof(str), src))
- fprintf (fp, " -:%5u:%s", curline++, str);
- fclose (src);
-next:
- nfile = nfile->next;
- }
- while (file) {
- for (i = 0; i < file->n_func; i++) {
- func = &file->func[i];
- free (func->line);
- }
- free (file->func);
- nfile = file;
- file = file->next;
- free (nfile);
- }
- fclose (fp);
-}
diff --git a/tinycc/lib/va_list.c b/tinycc/lib/va_list.c
deleted file mode 100644
index 1fb5512..0000000
--- a/tinycc/lib/va_list.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* va_list.c - tinycc support for va_list on X86_64 */
-
-#if defined __x86_64__
-
-/* Avoid include files, they may not be available when cross compiling */
-extern void abort(void);
-
-/* This should be in sync with our include/stdarg.h */
-enum __va_arg_type {
- __va_gen_reg, __va_float_reg, __va_stack
-};
-
-/* GCC compatible definition of va_list. */
-/*predefined by TCC (tcc_predefs.h):
-typedef struct {
- unsigned int gp_offset;
- unsigned int fp_offset;
- union {
- unsigned int overflow_offset;
- char *overflow_arg_area;
- };
- char *reg_save_area;
-} __builtin_va_list[1];
-*/
-
-extern void *memcpy(void *dest, const void *src, unsigned long n);
-
-void *__va_arg(__builtin_va_list ap,
- int arg_type,
- int size, int align)
-{
- size = (size + 7) & ~7;
- align = (align + 7) & ~7;
- switch ((enum __va_arg_type)arg_type) {
- case __va_gen_reg:
- if (ap->gp_offset + size <= 48) {
- ap->gp_offset += size;
- return ap->reg_save_area + ap->gp_offset - size;
- }
- goto use_overflow_area;
-
- case __va_float_reg:
- if (ap->fp_offset < 128 + 48) {
- ap->fp_offset += 16;
- if (size == 8)
- return ap->reg_save_area + ap->fp_offset - 16;
- if (ap->fp_offset < 128 + 48) {
- memcpy(ap->reg_save_area + ap->fp_offset - 8,
- ap->reg_save_area + ap->fp_offset, 8);
- ap->fp_offset += 16;
- return ap->reg_save_area + ap->fp_offset - 32;
- }
- }
- goto use_overflow_area;
-
- case __va_stack:
- use_overflow_area:
- ap->overflow_arg_area += size;
- ap->overflow_arg_area = (char*)((long long)(ap->overflow_arg_area + align - 1) & -align);
- return ap->overflow_arg_area - size;
-
- default: /* should never happen */
- abort();
- return 0;
- }
-}
-#endif
diff --git a/tinycc/libtcc.c b/tinycc/libtcc.c
deleted file mode 100644
index 0f6ebe5..0000000
--- a/tinycc/libtcc.c
+++ /dev/null
@@ -1,2248 +0,0 @@
-/*
- * TCC - Tiny C Compiler
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#if !defined ONE_SOURCE || ONE_SOURCE
-#include "tccpp.c"
-#include "tccgen.c"
-#include "tccdbg.c"
-#include "tccasm.c"
-#include "tccelf.c"
-#include "tccrun.c"
-#ifdef TCC_TARGET_I386
-#include "i386-gen.c"
-#include "i386-link.c"
-#include "i386-asm.c"
-#elif defined(TCC_TARGET_ARM)
-#include "arm-gen.c"
-#include "arm-link.c"
-#include "arm-asm.c"
-#elif defined(TCC_TARGET_ARM64)
-#include "arm64-gen.c"
-#include "arm64-link.c"
-#include "arm-asm.c"
-#elif defined(TCC_TARGET_C67)
-#include "c67-gen.c"
-#include "c67-link.c"
-#include "tcccoff.c"
-#elif defined(TCC_TARGET_X86_64)
-#include "x86_64-gen.c"
-#include "x86_64-link.c"
-#include "i386-asm.c"
-#elif defined(TCC_TARGET_RISCV64)
-#include "riscv64-gen.c"
-#include "riscv64-link.c"
-#include "riscv64-asm.c"
-#else
-#error unknown target
-#endif
-#ifdef TCC_TARGET_PE
-#include "tccpe.c"
-#endif
-#ifdef TCC_TARGET_MACHO
-#include "tccmacho.c"
-#endif
-#endif /* ONE_SOURCE */
-
-#include "tcc.h"
-
-/********************************************************/
-/* global variables */
-
-/* XXX: get rid of this ASAP (or maybe not) */
-ST_DATA struct TCCState *tcc_state;
-TCC_SEM(static tcc_compile_sem);
-/* an array of pointers to memory to be free'd after errors */
-ST_DATA void** stk_data;
-ST_DATA int nb_stk_data;
-
-/********************************************************/
-#ifdef _WIN32
-ST_FUNC char *normalize_slashes(char *path)
-{
- char *p;
- for (p = path; *p; ++p)
- if (*p == '\\')
- *p = '/';
- return path;
-}
-
-#if defined LIBTCC_AS_DLL && !defined CONFIG_TCCDIR
-static HMODULE tcc_module;
-BOOL WINAPI DllMain (HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved)
-{
- if (DLL_PROCESS_ATTACH == dwReason)
- tcc_module = hDll;
- return TRUE;
-}
-#else
-#define tcc_module NULL /* NULL means executable itself */
-#endif
-
-#ifndef CONFIG_TCCDIR
-/* on win32, we suppose the lib and includes are at the location of 'tcc.exe' */
-static inline char *config_tccdir_w32(char *path)
-{
- char temp[1024];
- char try[1024];
- char *p;
- int c;
- GetModuleFileName(tcc_module, path, MAX_PATH);
- p = tcc_basename(normalize_slashes(strlwr(path)));
- if (p > path)
- --p;
-
- *p = 0;
-
- /*
- * See if we are perhaps in a "bin/" subfolder of the
- * installation path, in which case the real root of
- * the installation is one level up. We can test this
- * by looking for the 'include' folder.
- */
- strncpy(temp, path, sizeof(temp)-1);
- strcat(temp, "/include");
-
- if (_access(temp, 0) != 0) {
- /* No 'include' folder found, so go up one level. */
- strncpy(temp, path, sizeof(temp)-1);
-
- /* Try this for several "levels" up. */
- for (c = 0; c < 4; c++) {
- p = tcc_basename(temp);
- if (p > temp) {
- --p;
- *p = '\0';
- }
-
- strncpy(try, temp, sizeof(try)-1);
- strcat(try, "/include");
-
- if (_access(try, 0) == 0) {
- if (p != NULL)
- p = '\0';
- strcpy(path, temp);
- break;
- }
- }
- }
-
- return path;
-}
-#define CONFIG_TCCDIR config_tccdir_w32(alloca(MAX_PATH))
-#endif
-
-#ifdef TCC_TARGET_PE
-static void tcc_add_systemdir(TCCState *s)
-{
- char buf[1000];
- GetSystemDirectory(buf, sizeof buf);
- tcc_add_library_path(s, normalize_slashes(buf));
-}
-#endif
-#endif
-
-/********************************************************/
-#if CONFIG_TCC_SEMLOCK
-#if defined _WIN32
-ST_FUNC void wait_sem(TCCSem *p)
-{
- if (!p->init)
- InitializeCriticalSection(&p->cr), p->init = 1;
- EnterCriticalSection(&p->cr);
-}
-ST_FUNC void post_sem(TCCSem *p)
-{
- LeaveCriticalSection(&p->cr);
-}
-#elif defined __APPLE__
-/* Half-compatible MacOS doesn't have non-shared (process local)
- semaphores. Use the dispatch framework for lightweight locks. */
-ST_FUNC void wait_sem(TCCSem *p)
-{
- if (!p->init)
- p->sem = dispatch_semaphore_create(1), p->init = 1;
- dispatch_semaphore_wait(p->sem, DISPATCH_TIME_FOREVER);
-}
-ST_FUNC void post_sem(TCCSem *p)
-{
- dispatch_semaphore_signal(p->sem);
-}
-#else
-ST_FUNC void wait_sem(TCCSem *p)
-{
- if (!p->init)
- sem_init(&p->sem, 0, 1), p->init = 1;
- while (sem_wait(&p->sem) < 0 && errno == EINTR);
-}
-ST_FUNC void post_sem(TCCSem *p)
-{
- sem_post(&p->sem);
-}
-#endif
-#endif
-
-PUB_FUNC void tcc_enter_state(TCCState *s1)
-{
- if (s1->error_set_jmp_enabled)
- return;
- WAIT_SEM(&tcc_compile_sem);
- tcc_state = s1;
-}
-
-PUB_FUNC void tcc_exit_state(TCCState *s1)
-{
- if (s1->error_set_jmp_enabled)
- return;
- tcc_state = NULL;
- POST_SEM(&tcc_compile_sem);
-}
-
-/********************************************************/
-/* copy a string and truncate it. */
-ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s)
-{
- char *q, *q_end;
- int c;
-
- if (buf_size > 0) {
- q = buf;
- q_end = buf + buf_size - 1;
- while (q < q_end) {
- c = *s++;
- if (c == '\0')
- break;
- *q++ = c;
- }
- *q = '\0';
- }
- return buf;
-}
-
-/* strcat and truncate. */
-ST_FUNC char *pstrcat(char *buf, size_t buf_size, const char *s)
-{
- size_t len;
- len = strlen(buf);
- if (len < buf_size)
- pstrcpy(buf + len, buf_size - len, s);
- return buf;
-}
-
-ST_FUNC char *pstrncpy(char *out, const char *in, size_t num)
-{
- memcpy(out, in, num);
- out[num] = '\0';
- return out;
-}
-
-/* extract the basename of a file */
-PUB_FUNC char *tcc_basename(const char *name)
-{
- char *p = strchr(name, 0);
- while (p > name && !IS_DIRSEP(p[-1]))
- --p;
- return p;
-}
-
-/* extract extension part of a file
- *
- * (if no extension, return pointer to end-of-string)
- */
-PUB_FUNC char *tcc_fileextension (const char *name)
-{
- char *b = tcc_basename(name);
- char *e = strrchr(b, '.');
- return e ? e : strchr(b, 0);
-}
-
-ST_FUNC char *tcc_load_text(int fd)
-{
- int len = lseek(fd, 0, SEEK_END);
- char *buf = load_data(fd, 0, len + 1);
- buf[len] = 0;
- return buf;
-}
-
-/********************************************************/
-/* memory management */
-
-#undef free
-#undef malloc
-#undef realloc
-
-void mem_error(const char *msg)
-{
- fprintf(stderr, "%s\n", msg);
- exit (1);
-}
-
-#ifndef MEM_DEBUG
-
-PUB_FUNC void tcc_free(void *ptr)
-{
- free(ptr);
-}
-
-PUB_FUNC void *tcc_malloc(unsigned long size)
-{
- void *ptr;
- ptr = malloc(size);
- if (!ptr && size)
- mem_error("memory full (malloc)");
- return ptr;
-}
-
-PUB_FUNC void *tcc_mallocz(unsigned long size)
-{
- void *ptr;
- ptr = tcc_malloc(size);
- if (size)
- memset(ptr, 0, size);
- return ptr;
-}
-
-PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size)
-{
- void *ptr1;
- ptr1 = realloc(ptr, size);
- if (!ptr1 && size)
- mem_error("memory full (realloc)");
- return ptr1;
-}
-
-PUB_FUNC char *tcc_strdup(const char *str)
-{
- char *ptr;
- ptr = tcc_malloc(strlen(str) + 1);
- strcpy(ptr, str);
- return ptr;
-}
-
-#else
-
-#define MEM_DEBUG_MAGIC1 0xFEEDDEB1
-#define MEM_DEBUG_MAGIC2 0xFEEDDEB2
-#define MEM_DEBUG_MAGIC3 0xFEEDDEB3
-#define MEM_DEBUG_FILE_LEN 40
-#define MEM_DEBUG_CHECK3(header) \
- ((mem_debug_header_t*)((char*)header + header->size))->magic3
-#define MEM_USER_PTR(header) \
- ((char *)header + offsetof(mem_debug_header_t, magic3))
-#define MEM_HEADER_PTR(ptr) \
- (mem_debug_header_t *)((char*)ptr - offsetof(mem_debug_header_t, magic3))
-
-struct mem_debug_header {
- unsigned magic1;
- unsigned size;
- struct mem_debug_header *prev;
- struct mem_debug_header *next;
- int line_num;
- char file_name[MEM_DEBUG_FILE_LEN + 1];
- unsigned magic2;
- ALIGNED(16) unsigned char magic3[4];
-};
-
-typedef struct mem_debug_header mem_debug_header_t;
-
-TCC_SEM(static mem_sem);
-static mem_debug_header_t *mem_debug_chain;
-static unsigned mem_cur_size;
-static unsigned mem_max_size;
-static int nb_states;
-
-static mem_debug_header_t *malloc_check(void *ptr, const char *msg)
-{
- mem_debug_header_t * header = MEM_HEADER_PTR(ptr);
- if (header->magic1 != MEM_DEBUG_MAGIC1 ||
- header->magic2 != MEM_DEBUG_MAGIC2 ||
- read32le(MEM_DEBUG_CHECK3(header)) != MEM_DEBUG_MAGIC3 ||
- header->size == (unsigned)-1) {
- fprintf(stderr, "%s check failed\n", msg);
- if (header->magic1 == MEM_DEBUG_MAGIC1)
- fprintf(stderr, "%s:%u: block allocated here.\n",
- header->file_name, header->line_num);
- exit(1);
- }
- return header;
-}
-
-PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line)
-{
- int ofs;
- mem_debug_header_t *header;
-
- header = malloc(sizeof(mem_debug_header_t) + size);
- if (!header)
- mem_error("memory full (malloc)");
-
- header->magic1 = MEM_DEBUG_MAGIC1;
- header->magic2 = MEM_DEBUG_MAGIC2;
- header->size = size;
- write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3);
- header->line_num = line;
- ofs = strlen(file) - MEM_DEBUG_FILE_LEN;
- strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN);
- header->file_name[MEM_DEBUG_FILE_LEN] = 0;
-
- WAIT_SEM(&mem_sem);
- header->next = mem_debug_chain;
- header->prev = NULL;
- if (header->next)
- header->next->prev = header;
- mem_debug_chain = header;
- mem_cur_size += size;
- if (mem_cur_size > mem_max_size)
- mem_max_size = mem_cur_size;
- POST_SEM(&mem_sem);
-
- return MEM_USER_PTR(header);
-}
-
-PUB_FUNC void tcc_free_debug(void *ptr)
-{
- mem_debug_header_t *header;
- if (!ptr)
- return;
- header = malloc_check(ptr, "tcc_free");
-
- WAIT_SEM(&mem_sem);
- mem_cur_size -= header->size;
- header->size = (unsigned)-1;
- if (header->next)
- header->next->prev = header->prev;
- if (header->prev)
- header->prev->next = header->next;
- if (header == mem_debug_chain)
- mem_debug_chain = header->next;
- POST_SEM(&mem_sem);
- free(header);
-}
-
-PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line)
-{
- void *ptr;
- ptr = tcc_malloc_debug(size,file,line);
- memset(ptr, 0, size);
- return ptr;
-}
-
-PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line)
-{
- mem_debug_header_t *header;
- int mem_debug_chain_update = 0;
- if (!ptr)
- return tcc_malloc_debug(size, file, line);
- header = malloc_check(ptr, "tcc_realloc");
-
- WAIT_SEM(&mem_sem);
- mem_cur_size -= header->size;
- mem_debug_chain_update = (header == mem_debug_chain);
- header = realloc(header, sizeof(mem_debug_header_t) + size);
- if (!header)
- mem_error("memory full (realloc)");
- header->size = size;
- write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3);
- if (header->next)
- header->next->prev = header;
- if (header->prev)
- header->prev->next = header;
- if (mem_debug_chain_update)
- mem_debug_chain = header;
- mem_cur_size += size;
- if (mem_cur_size > mem_max_size)
- mem_max_size = mem_cur_size;
- POST_SEM(&mem_sem);
-
- return MEM_USER_PTR(header);
-}
-
-PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line)
-{
- char *ptr;
- ptr = tcc_malloc_debug(strlen(str) + 1, file, line);
- strcpy(ptr, str);
- return ptr;
-}
-
-PUB_FUNC void tcc_memcheck(int d)
-{
- WAIT_SEM(&mem_sem);
- nb_states += d;
- if (0 == nb_states && mem_cur_size) {
- mem_debug_header_t *header = mem_debug_chain;
- fflush(stdout);
- fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n",
- mem_cur_size, mem_max_size);
- while (header) {
- fprintf(stderr, "%s:%u: error: %u bytes leaked\n",
- header->file_name, header->line_num, header->size);
- header = header->next;
- }
- fflush(stderr);
- mem_cur_size = 0;
- mem_debug_chain = NULL;
-#if MEM_DEBUG-0 == 2
- exit(2);
-#endif
- }
- POST_SEM(&mem_sem);
-}
-#endif /* MEM_DEBUG */
-
-#define free(p) use_tcc_free(p)
-#define malloc(s) use_tcc_malloc(s)
-#define realloc(p, s) use_tcc_realloc(p, s)
-
-/********************************************************/
-/* dynarrays */
-
-ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data)
-{
- int nb, nb_alloc;
- void **pp;
-
- nb = *nb_ptr;
- pp = *(void ***)ptab;
- /* every power of two we double array size */
- if ((nb & (nb - 1)) == 0) {
- if (!nb)
- nb_alloc = 1;
- else
- nb_alloc = nb * 2;
- pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
- *(void***)ptab = pp;
- }
- pp[nb++] = data;
- *nb_ptr = nb;
-}
-
-ST_FUNC void dynarray_reset(void *pp, int *n)
-{
- void **p;
- for (p = *(void***)pp; *n; ++p, --*n)
- if (*p)
- tcc_free(*p);
- tcc_free(*(void**)pp);
- *(void**)pp = NULL;
-}
-
-static void tcc_split_path(TCCState *s, void *p_ary, int *p_nb_ary, const char *in)
-{
- const char *p;
- do {
- int c;
- CString str;
-
- cstr_new(&str);
- for (p = in; c = *p, c != '\0' && c != PATHSEP[0]; ++p) {
- if (c == '{' && p[1] && p[2] == '}') {
- c = p[1], p += 2;
- if (c == 'B')
- cstr_cat(&str, s->tcc_lib_path, -1);
- if (c == 'R')
- cstr_cat(&str, CONFIG_SYSROOT, -1);
- if (c == 'f' && file) {
- /* substitute current file's dir */
- const char *f = file->true_filename;
- const char *b = tcc_basename(f);
- if (b > f)
- cstr_cat(&str, f, b - f - 1);
- else
- cstr_cat(&str, ".", 1);
- }
- } else {
- cstr_ccat(&str, c);
- }
- }
- if (str.size) {
- cstr_ccat(&str, '\0');
- dynarray_add(p_ary, p_nb_ary, tcc_strdup(str.data));
- }
- cstr_free(&str);
- in = p+1;
- } while (*p);
-}
-
-/********************************************************/
-/* warning / error */
-
-/* warn_... option bits */
-#define WARN_ON 1 /* warning is on (-Woption) */
-#define WARN_ERR 2 /* warning is an error (-Werror=option) */
-#define WARN_NOE 4 /* warning is not an error (-Wno-error=option) */
-
-/* error1() modes */
-enum { ERROR_WARN, ERROR_NOABORT, ERROR_ERROR };
-
-static void error1(int mode, const char *fmt, va_list ap)
-{
- BufferedFile **pf, *f;
- TCCState *s1 = tcc_state;
- CString cs;
-
- tcc_exit_state(s1);
-
- if (mode == ERROR_WARN) {
- if (s1->warn_error)
- mode = ERROR_ERROR;
- if (s1->warn_num) {
- /* handle tcc_warning_c(warn_option)(fmt, ...) */
- int wopt = *(&s1->warn_none + s1->warn_num);
- s1->warn_num = 0;
- if (0 == (wopt & WARN_ON))
- return;
- if (wopt & WARN_ERR)
- mode = ERROR_ERROR;
- if (wopt & WARN_NOE)
- mode = ERROR_WARN;
- }
- if (s1->warn_none)
- return;
- }
-
- cstr_new(&cs);
- f = NULL;
- if (s1->error_set_jmp_enabled) { /* we're called while parsing a file */
- /* use upper file if inline ":asm:" or token ":paste:" */
- for (f = file; f && f->filename[0] == ':'; f = f->prev)
- ;
- }
- if (f) {
- for(pf = s1->include_stack; pf < s1->include_stack_ptr; pf++)
- cstr_printf(&cs, "In file included from %s:%d:\n",
- (*pf)->filename, (*pf)->line_num - 1);
- cstr_printf(&cs, "%s:%d: ",
- f->filename, f->line_num - !!(tok_flags & TOK_FLAG_BOL));
- } else if (s1->current_filename) {
- cstr_printf(&cs, "%s: ", s1->current_filename);
- }
- if (0 == cs.size)
- cstr_printf(&cs, "tcc: ");
- cstr_printf(&cs, mode == ERROR_WARN ? "warning: " : "error: ");
- cstr_vprintf(&cs, fmt, ap);
- if (!s1 || !s1->error_func) {
- /* default case: stderr */
- if (s1 && s1->output_type == TCC_OUTPUT_PREPROCESS && s1->ppfp == stdout)
- printf("\n"); /* print a newline during tcc -E */
- fflush(stdout); /* flush -v output */
- fprintf(stderr, "%s\n", (char*)cs.data);
- fflush(stderr); /* print error/warning now (win32) */
- } else {
- s1->error_func(s1->error_opaque, (char*)cs.data);
- }
- cstr_free(&cs);
- if (mode != ERROR_WARN)
- s1->nb_errors++;
- if (mode == ERROR_ERROR && s1->error_set_jmp_enabled) {
- while (nb_stk_data)
- tcc_free(*(void**)stk_data[--nb_stk_data]);
- longjmp(s1->error_jmp_buf, 1);
- }
-}
-
-LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func)
-{
- s->error_opaque = error_opaque;
- s->error_func = error_func;
-}
-
-LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s)
-{
- return s->error_func;
-}
-
-LIBTCCAPI void *tcc_get_error_opaque(TCCState *s)
-{
- return s->error_opaque;
-}
-
-/* error without aborting current compilation */
-PUB_FUNC int _tcc_error_noabort(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- error1(ERROR_NOABORT, fmt, ap);
- va_end(ap);
- return -1;
-}
-
-#undef _tcc_error
-PUB_FUNC void _tcc_error(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- error1(ERROR_ERROR, fmt, ap);
- exit(1);
-}
-#define _tcc_error use_tcc_error_noabort
-
-PUB_FUNC void _tcc_warning(const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- error1(ERROR_WARN, fmt, ap);
- va_end(ap);
-}
-
-
-/********************************************************/
-/* I/O layer */
-
-ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen)
-{
- BufferedFile *bf;
- int buflen = initlen ? initlen : IO_BUF_SIZE;
-
- bf = tcc_mallocz(sizeof(BufferedFile) + buflen);
- bf->buf_ptr = bf->buffer;
- bf->buf_end = bf->buffer + initlen;
- bf->buf_end[0] = CH_EOB; /* put eob symbol */
- pstrcpy(bf->filename, sizeof(bf->filename), filename);
-#ifdef _WIN32
- normalize_slashes(bf->filename);
-#endif
- bf->true_filename = bf->filename;
- bf->line_num = 1;
- bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
- bf->fd = -1;
- bf->prev = file;
- file = bf;
- tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
-}
-
-ST_FUNC void tcc_close(void)
-{
- TCCState *s1 = tcc_state;
- BufferedFile *bf = file;
- if (bf->fd > 0) {
- close(bf->fd);
- total_lines += bf->line_num - 1;
- }
- if (bf->true_filename != bf->filename)
- tcc_free(bf->true_filename);
- file = bf->prev;
- tcc_free(bf);
-}
-
-static int _tcc_open(TCCState *s1, const char *filename)
-{
- int fd;
- if (strcmp(filename, "-") == 0)
- fd = 0, filename = "<stdin>";
- else
- fd = open(filename, O_RDONLY | O_BINARY);
- if ((s1->verbose == 2 && fd >= 0) || s1->verbose == 3)
- printf("%s %*s%s\n", fd < 0 ? "nf":"->",
- (int)(s1->include_stack_ptr - s1->include_stack), "", filename);
- return fd;
-}
-
-ST_FUNC int tcc_open(TCCState *s1, const char *filename)
-{
- int fd = _tcc_open(s1, filename);
- if (fd < 0)
- return -1;
- tcc_open_bf(s1, filename, 0);
- file->fd = fd;
- return 0;
-}
-
-/* compile the file opened in 'file'. Return non zero if errors. */
-static int tcc_compile(TCCState *s1, int filetype, const char *str, int fd)
-{
- /* Here we enter the code section where we use the global variables for
- parsing and code generation (tccpp.c, tccgen.c, <target>-gen.c).
- Other threads need to wait until we're done.
-
- Alternatively we could use thread local storage for those global
- variables, which may or may not have advantages */
-
- tcc_enter_state(s1);
- s1->error_set_jmp_enabled = 1;
-
- if (setjmp(s1->error_jmp_buf) == 0) {
- s1->nb_errors = 0;
-
- if (fd == -1) {
- int len = strlen(str);
- tcc_open_bf(s1, "<string>", len);
- memcpy(file->buffer, str, len);
- } else {
- tcc_open_bf(s1, str, 0);
- file->fd = fd;
- }
-
- preprocess_start(s1, filetype);
- tccgen_init(s1);
-
- if (s1->output_type == TCC_OUTPUT_PREPROCESS) {
- tcc_preprocess(s1);
- } else {
- tccelf_begin_file(s1);
- if (filetype & (AFF_TYPE_ASM | AFF_TYPE_ASMPP)) {
- tcc_assemble(s1, !!(filetype & AFF_TYPE_ASMPP));
- } else {
- tccgen_compile(s1);
- }
- tccelf_end_file(s1);
- }
- }
- tccgen_finish(s1);
- preprocess_end(s1);
- s1->error_set_jmp_enabled = 0;
- tcc_exit_state(s1);
- return s1->nb_errors != 0 ? -1 : 0;
-}
-
-LIBTCCAPI int tcc_compile_string(TCCState *s, const char *str)
-{
- return tcc_compile(s, s->filetype, str, -1);
-}
-
-/* define a preprocessor symbol. value can be NULL, sym can be "sym=val" */
-LIBTCCAPI void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
-{
- const char *eq;
- if (NULL == (eq = strchr(sym, '=')))
- eq = strchr(sym, 0);
- if (NULL == value)
- value = *eq ? eq + 1 : "1";
- cstr_printf(&s1->cmdline_defs, "#define %.*s %s\n", (int)(eq-sym), sym, value);
-}
-
-/* undefine a preprocessor symbol */
-LIBTCCAPI void tcc_undefine_symbol(TCCState *s1, const char *sym)
-{
- cstr_printf(&s1->cmdline_defs, "#undef %s\n", sym);
-}
-
-
-LIBTCCAPI TCCState *tcc_new(void)
-{
- TCCState *s;
-
- s = tcc_mallocz(sizeof(TCCState));
- if (!s)
- return NULL;
-#ifdef MEM_DEBUG
- tcc_memcheck(1);
-#endif
-
-#undef gnu_ext
-
- s->gnu_ext = 1;
- s->tcc_ext = 1;
- s->nocommon = 1;
- s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/
- s->cversion = 199901; /* default unless -std=c11 is supplied */
- s->warn_implicit_function_declaration = 1;
- s->warn_discarded_qualifiers = 1;
- s->ms_extensions = 1;
-
-#ifdef CHAR_IS_UNSIGNED
- s->char_is_unsigned = 1;
-#endif
-#ifdef TCC_TARGET_I386
- s->seg_size = 32;
-#endif
- /* enable this if you want symbols with leading underscore on windows: */
-#if defined TCC_TARGET_MACHO /* || defined TCC_TARGET_PE */
- s->leading_underscore = 1;
-#endif
-#ifdef TCC_TARGET_ARM
- s->float_abi = ARM_FLOAT_ABI;
-#endif
-#ifdef CONFIG_NEW_DTAGS
- s->enable_new_dtags = 1;
-#endif
- s->ppfp = stdout;
- /* might be used in error() before preprocess_start() */
- s->include_stack_ptr = s->include_stack;
-
- tcc_set_lib_path(s, CONFIG_TCCDIR);
- return s;
-}
-
-LIBTCCAPI void tcc_delete(TCCState *s1)
-{
- /* free sections */
- tccelf_delete(s1);
-
- /* free library paths */
- dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
- dynarray_reset(&s1->crt_paths, &s1->nb_crt_paths);
-
- /* free include paths */
- dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
- dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
-
- tcc_free(s1->tcc_lib_path);
- tcc_free(s1->soname);
- tcc_free(s1->rpath);
- tcc_free(s1->elf_entryname);
- tcc_free(s1->init_symbol);
- tcc_free(s1->fini_symbol);
- tcc_free(s1->mapfile);
- tcc_free(s1->outfile);
- tcc_free(s1->deps_outfile);
-#if defined TCC_TARGET_MACHO
- tcc_free(s1->install_name);
-#endif
- dynarray_reset(&s1->files, &s1->nb_files);
- dynarray_reset(&s1->target_deps, &s1->nb_target_deps);
- dynarray_reset(&s1->pragma_libs, &s1->nb_pragma_libs);
- dynarray_reset(&s1->argv, &s1->argc);
- cstr_free(&s1->cmdline_defs);
- cstr_free(&s1->cmdline_incl);
- cstr_free(&s1->linker_arg);
-#ifdef TCC_IS_NATIVE
- /* free runtime memory */
- tcc_run_free(s1);
-#endif
- tcc_free(s1->dState);
- tcc_free(s1);
-#ifdef MEM_DEBUG
- tcc_memcheck(-1);
-#endif
-}
-
-LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type)
-{
-#ifdef CONFIG_TCC_PIE
- if (output_type == TCC_OUTPUT_EXE)
- output_type |= TCC_OUTPUT_DYN;
-#endif
- s->output_type = output_type;
-
- if (!s->nostdinc) {
- /* default include paths */
- /* -isystem paths have already been handled */
- tcc_add_sysinclude_path(s, CONFIG_TCC_SYSINCLUDEPATHS);
- }
-
- if (output_type == TCC_OUTPUT_PREPROCESS) {
- s->do_debug = 0;
- return 0;
- }
-
- tccelf_new(s);
- if (s->do_debug) {
- /* add debug sections */
- tcc_debug_new(s);
- }
-#ifdef CONFIG_TCC_BCHECK
- if (s->do_bounds_check) {
- /* if bound checking, then add corresponding sections */
- tccelf_bounds_new(s);
- }
-#endif
-
- if (output_type == TCC_OUTPUT_OBJ) {
- /* always elf for objects */
- s->output_format = TCC_OUTPUT_FORMAT_ELF;
- return 0;
- }
-
- tcc_add_library_path(s, CONFIG_TCC_LIBPATHS);
-
-#ifdef TCC_TARGET_PE
-# ifdef _WIN32
- /* allow linking with system dll's directly */
- tcc_add_systemdir(s);
-# endif
- /* target PE has its own startup code in libtcc1.a */
- return 0;
-
-#elif defined TCC_TARGET_MACHO
-# ifdef TCC_IS_NATIVE
- tcc_add_macos_sdkpath(s);
-# endif
- /* Mach-O with LC_MAIN doesn't need any crt startup code. */
- return 0;
-
-#else
- /* paths for crt objects */
- tcc_split_path(s, &s->crt_paths, &s->nb_crt_paths, CONFIG_TCC_CRTPREFIX);
-
- /* add libc crt1/crti objects */
- if (output_type != TCC_OUTPUT_MEMORY && !s->nostdlib) {
-#if TARGETOS_OpenBSD
- if (output_type != TCC_OUTPUT_DLL)
- tcc_add_crt(s, "crt0.o");
- if (output_type == TCC_OUTPUT_DLL)
- tcc_add_crt(s, "crtbeginS.o");
- else
- tcc_add_crt(s, "crtbegin.o");
-#elif TARGETOS_FreeBSD
- if (output_type != TCC_OUTPUT_DLL)
- tcc_add_crt(s, "crt1.o");
- tcc_add_crt(s, "crti.o");
- if (s->static_link)
- tcc_add_crt(s, "crtbeginT.o");
- else if (output_type & TCC_OUTPUT_DYN)
- tcc_add_crt(s, "crtbeginS.o");
- else
- tcc_add_crt(s, "crtbegin.o");
-#elif TARGETOS_NetBSD
- if (output_type != TCC_OUTPUT_DLL)
- tcc_add_crt(s, "crt0.o");
- tcc_add_crt(s, "crti.o");
- if (s->static_link)
- tcc_add_crt(s, "crtbeginT.o");
- else if (output_type & TCC_OUTPUT_DYN)
- tcc_add_crt(s, "crtbeginS.o");
- else
- tcc_add_crt(s, "crtbegin.o");
-#elif defined TARGETOS_ANDROID
- if (output_type != TCC_OUTPUT_DLL)
- tcc_add_crt(s, "crtbegin_dynamic.o");
- else
- tcc_add_crt(s, "crtbegin_so.o");
-#else
- if (output_type != TCC_OUTPUT_DLL)
- tcc_add_crt(s, "crt1.o");
- tcc_add_crt(s, "crti.o");
-#endif
- }
- return 0;
-#endif
-}
-
-LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname)
-{
- tcc_split_path(s, &s->include_paths, &s->nb_include_paths, pathname);
- return 0;
-}
-
-LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname)
-{
- tcc_split_path(s, &s->sysinclude_paths, &s->nb_sysinclude_paths, pathname);
- return 0;
-}
-
-/* add/update a 'DLLReference', Just find if level == -1 */
-ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level)
-{
- DLLReference *ref = NULL;
- int i;
- for (i = 0; i < s1->nb_loaded_dlls; i++)
- if (0 == strcmp(s1->loaded_dlls[i]->name, dllname)) {
- ref = s1->loaded_dlls[i];
- break;
- }
- if (level == -1)
- return ref;
- if (ref) {
- if (level < ref->level)
- ref->level = level;
- ref->found = 1;
- return ref;
- }
- ref = tcc_mallocz(sizeof(DLLReference) + strlen(dllname));
- strcpy(ref->name, dllname);
- dynarray_add(&s1->loaded_dlls, &s1->nb_loaded_dlls, ref);
- ref->level = level;
- ref->index = s1->nb_loaded_dlls;
- return ref;
-}
-
-/* OpenBSD: choose latest from libxxx.so.x.y versions */
-#if defined TARGETOS_OpenBSD && !defined _WIN32
-#include <glob.h>
-static int tcc_glob_so(TCCState *s1, const char *pattern, char *buf, int size)
-{
- const char *star;
- glob_t g;
- char *p;
- int i, v, v1, v2, v3;
-
- star = strchr(pattern, '*');
- if (!star || glob(pattern, 0, NULL, &g))
- return -1;
- for (v = -1, i = 0; i < g.gl_pathc; ++i) {
- p = g.gl_pathv[i];
- if (2 != sscanf(p + (star - pattern), "%d.%d.%d", &v1, &v2, &v3))
- continue;
- if ((v1 = v1 * 1000 + v2) > v)
- v = v1, pstrcpy(buf, size, p);
- }
- globfree(&g);
- return v;
-}
-#endif
-
-ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
-{
- int fd, ret = -1;
-
-#if defined TARGETOS_OpenBSD && !defined _WIN32
- char buf[1024];
- if (tcc_glob_so(s1, filename, buf, sizeof buf) >= 0)
- filename = buf;
-#endif
-
- /* ignore binary files with -E */
- if (s1->output_type == TCC_OUTPUT_PREPROCESS
- && (flags & AFF_TYPE_BIN))
- return 0;
-
- /* open the file */
- fd = _tcc_open(s1, filename);
- if (fd < 0) {
- if (flags & AFF_PRINT_ERROR)
- tcc_error_noabort("file '%s' not found", filename);
- return ret;
- }
-
- s1->current_filename = filename;
- if (flags & AFF_TYPE_BIN) {
- ElfW(Ehdr) ehdr;
- int obj_type;
-
- obj_type = tcc_object_type(fd, &ehdr);
- lseek(fd, 0, SEEK_SET);
-
- switch (obj_type) {
-
- case AFF_BINTYPE_REL:
- ret = tcc_load_object_file(s1, fd, 0);
- break;
-
- case AFF_BINTYPE_AR:
- ret = tcc_load_archive(s1, fd, !(flags & AFF_WHOLE_ARCHIVE));
- break;
-
-#ifdef TCC_TARGET_PE
- default:
- ret = pe_load_file(s1, fd, filename);
- goto check_success;
-
-#elif defined TCC_TARGET_MACHO
- case AFF_BINTYPE_DYN:
- case_dyn_or_tbd:
- if (s1->output_type == TCC_OUTPUT_MEMORY) {
-#ifdef TCC_IS_NATIVE
- void* dl;
- const char* soname = filename;
- if (obj_type != AFF_BINTYPE_DYN)
- soname = macho_tbd_soname(filename);
- dl = dlopen(soname, RTLD_GLOBAL | RTLD_LAZY);
- if (dl)
- tcc_add_dllref(s1, soname, 0)->handle = dl, ret = 0;
- if (filename != soname)
- tcc_free((void *)soname);
-#endif
- } else if (obj_type == AFF_BINTYPE_DYN) {
- ret = macho_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
- } else {
- ret = macho_load_tbd(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
- }
- break;
- default:
- {
- const char *ext = tcc_fileextension(filename);
- if (!strcmp(ext, ".tbd"))
- goto case_dyn_or_tbd;
- if (!strcmp(ext, ".dylib")) {
- obj_type = AFF_BINTYPE_DYN;
- goto case_dyn_or_tbd;
- }
- goto check_success;
- }
-
-#else /* unix */
- case AFF_BINTYPE_DYN:
- if (s1->output_type == TCC_OUTPUT_MEMORY) {
-#ifdef TCC_IS_NATIVE
- void* dl = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
- if (dl)
- tcc_add_dllref(s1, filename, 0)->handle = dl, ret = 0;
-#endif
- } else
- ret = tcc_load_dll(s1, fd, filename, (flags & AFF_REFERENCED_DLL) != 0);
- break;
-
- default:
- /* as GNU ld, consider it is an ld script if not recognized */
- ret = tcc_load_ldscript(s1, fd);
- goto check_success;
-
-#endif /* pe / macos / unix */
-
-check_success:
- if (ret < 0)
- tcc_error_noabort("%s: unrecognized file type", filename);
- break;
-
-#ifdef TCC_TARGET_COFF
- case AFF_BINTYPE_C67:
- ret = tcc_load_coff(s1, fd);
- break;
-#endif
- }
- close(fd);
- } else {
- /* update target deps */
- dynarray_add(&s1->target_deps, &s1->nb_target_deps, tcc_strdup(filename));
- ret = tcc_compile(s1, flags, filename, fd);
- }
- s1->current_filename = NULL;
- return ret;
-}
-
-LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename)
-{
- int filetype = s->filetype;
- if (0 == (filetype & AFF_TYPE_MASK)) {
- /* use a file extension to detect a filetype */
- const char *ext = tcc_fileextension(filename);
- if (ext[0]) {
- ext++;
- if (!strcmp(ext, "S"))
- filetype = AFF_TYPE_ASMPP;
- else if (!strcmp(ext, "s"))
- filetype = AFF_TYPE_ASM;
- else if (!PATHCMP(ext, "c")
- || !PATHCMP(ext, "h")
- || !PATHCMP(ext, "i"))
- filetype = AFF_TYPE_C;
- else
- filetype |= AFF_TYPE_BIN;
- } else {
- filetype = AFF_TYPE_C;
- }
- }
- return tcc_add_file_internal(s, filename, filetype | AFF_PRINT_ERROR);
-}
-
-LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname)
-{
- tcc_split_path(s, &s->library_paths, &s->nb_library_paths, pathname);
- return 0;
-}
-
-static int tcc_add_library_internal(TCCState *s, const char *fmt,
- const char *filename, int flags, char **paths, int nb_paths)
-{
- char buf[1024];
- int i;
-
- for(i = 0; i < nb_paths; i++) {
- snprintf(buf, sizeof(buf), fmt, paths[i], filename);
- if (tcc_add_file_internal(s, buf, flags | AFF_TYPE_BIN) == 0)
- return 0;
- }
- return -1;
-}
-
-/* find and load a dll. Return non zero if not found */
-ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags)
-{
- return tcc_add_library_internal(s, "%s/%s", filename, flags,
- s->library_paths, s->nb_library_paths);
-}
-
-/* find [cross-]libtcc1.a and tcc helper objects in library path */
-ST_FUNC void tcc_add_support(TCCState *s1, const char *filename)
-{
- char buf[100];
- if (CONFIG_TCC_CROSSPREFIX[0])
- filename = strcat(strcpy(buf, CONFIG_TCC_CROSSPREFIX), filename);
- if (tcc_add_dll(s1, filename, 0) < 0)
- tcc_error_noabort("%s not found", filename);
-}
-
-#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
-ST_FUNC int tcc_add_crt(TCCState *s1, const char *filename)
-{
- if (-1 == tcc_add_library_internal(s1, "%s/%s",
- filename, 0, s1->crt_paths, s1->nb_crt_paths))
- return tcc_error_noabort("file '%s' not found", filename);
- return 0;
-}
-#endif
-
-/* the library name is the same as the argument of the '-l' option */
-LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname)
-{
-#if defined TCC_TARGET_PE
- static const char * const libs[] = { "%s/%s.def", "%s/lib%s.def", "%s/%s.dll", "%s/lib%s.dll", "%s/lib%s.a", NULL };
- const char * const *pp = s->static_link ? libs + 4 : libs;
-#elif defined TCC_TARGET_MACHO
- static const char * const libs[] = { "%s/lib%s.dylib", "%s/lib%s.tbd", "%s/lib%s.a", NULL };
- const char * const *pp = s->static_link ? libs + 2 : libs;
-#elif defined TARGETOS_OpenBSD
- static const char * const libs[] = { "%s/lib%s.so.*", "%s/lib%s.a", NULL };
- const char * const *pp = s->static_link ? libs + 1 : libs;
-#else
- static const char * const libs[] = { "%s/lib%s.so", "%s/lib%s.a", NULL };
- const char * const *pp = s->static_link ? libs + 1 : libs;
-#endif
- int flags = s->filetype & AFF_WHOLE_ARCHIVE;
- while (*pp) {
- if (0 == tcc_add_library_internal(s, *pp,
- libraryname, flags, s->library_paths, s->nb_library_paths))
- return 0;
- ++pp;
- }
- return -1;
-}
-
-PUB_FUNC int tcc_add_library_err(TCCState *s1, const char *libname)
-{
- int ret = tcc_add_library(s1, libname);
- if (ret < 0)
- tcc_error_noabort("library '%s' not found", libname);
- return ret;
-}
-
-/* handle #pragma comment(lib,) */
-ST_FUNC void tcc_add_pragma_libs(TCCState *s1)
-{
- int i;
- for (i = 0; i < s1->nb_pragma_libs; i++)
- tcc_add_library_err(s1, s1->pragma_libs[i]);
-}
-
-LIBTCCAPI int tcc_add_symbol(TCCState *s1, const char *name, const void *val)
-{
-#ifdef TCC_TARGET_PE
- /* On x86_64 'val' might not be reachable with a 32bit offset.
- So it is handled here as if it were in a DLL. */
- pe_putimport(s1, 0, name, (uintptr_t)val);
-#else
- char buf[256];
- if (s1->leading_underscore) {
- buf[0] = '_';
- pstrcpy(buf + 1, sizeof(buf) - 1, name);
- name = buf;
- }
- set_global_sym(s1, name, NULL, (addr_t)(uintptr_t)val); /* NULL: SHN_ABS */
-#endif
- return 0;
-}
-
-LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path)
-{
- tcc_free(s->tcc_lib_path);
- s->tcc_lib_path = tcc_strdup(path);
-}
-
-/********************************************************/
-/* options parser */
-
-static int strstart(const char *val, const char **str)
-{
- const char *p, *q;
- p = *str;
- q = val;
- while (*q) {
- if (*p != *q)
- return 0;
- p++;
- q++;
- }
- *str = p;
- return 1;
-}
-
-/* Like strstart, but automatically takes into account that ld options can
- *
- * - start with double or single dash (e.g. '--soname' or '-soname')
- * - arguments can be given as separate or after '=' (e.g. '-Wl,-soname,x.so'
- * or '-Wl,-soname=x.so')
- *
- * you provide `val` always in 'option[=]' form (no leading -)
- */
-static int link_option(const char *str, const char *val, const char **ptr)
-{
- const char *p, *q;
- int ret;
-
- /* there should be 1 or 2 dashes */
- if (*str++ != '-')
- return 0;
- if (*str == '-')
- str++;
-
- /* then str & val should match (potentially up to '=') */
- p = str;
- q = val;
-
- ret = 1;
- if (q[0] == '?') {
- ++q;
- if (strstart("no-", &p))
- ret = -1;
- }
-
- while (*q != '\0' && *q != '=') {
- if (*p != *q)
- return 0;
- p++;
- q++;
- }
-
- /* '=' near eos means ',' or '=' is ok */
- if (*q == '=') {
- if (*p == 0)
- *ptr = p;
- if (*p != ',' && *p != '=')
- return 0;
- p++;
- } else if (*p) {
- return 0;
- }
- *ptr = p;
- return ret;
-}
-
-static const char *skip_linker_arg(const char **str)
-{
- const char *s1 = *str;
- const char *s2 = strchr(s1, ',');
- *str = s2 ? s2++ : (s2 = s1 + strlen(s1));
- return s2;
-}
-
-static void copy_linker_arg(char **pp, const char *s, int sep)
-{
- const char *q = s;
- char *p = *pp;
- int l = 0;
- if (p && sep)
- p[l = strlen(p)] = sep, ++l;
- skip_linker_arg(&q);
- pstrncpy(l + (*pp = tcc_realloc(p, q - s + l + 1)), s, q - s);
-}
-
-static void args_parser_add_file(TCCState *s, const char* filename, int filetype)
-{
- struct filespec *f = tcc_malloc(sizeof *f + strlen(filename));
- f->type = filetype;
- strcpy(f->name, filename);
- dynarray_add(&s->files, &s->nb_files, f);
-}
-
-/* set linker options */
-static int tcc_set_linker(TCCState *s, const char *option)
-{
- TCCState *s1 = s;
- while (*option) {
-
- const char *p = NULL;
- char *end = NULL;
- int ignoring = 0;
- int ret;
-
- if (link_option(option, "Bsymbolic", &p)) {
- s->symbolic = 1;
- } else if (link_option(option, "nostdlib", &p)) {
- s->nostdlib = 1;
- } else if (link_option(option, "e=", &p)
- || link_option(option, "entry=", &p)) {
- copy_linker_arg(&s->elf_entryname, p, 0);
- } else if (link_option(option, "fini=", &p)) {
- copy_linker_arg(&s->fini_symbol, p, 0);
- ignoring = 1;
- } else if (link_option(option, "image-base=", &p)
- || link_option(option, "Ttext=", &p)) {
- s->text_addr = strtoull(p, &end, 16);
- s->has_text_addr = 1;
- } else if (link_option(option, "init=", &p)) {
- copy_linker_arg(&s->init_symbol, p, 0);
- ignoring = 1;
- } else if (link_option(option, "Map=", &p)) {
- copy_linker_arg(&s->mapfile, p, 0);
- ignoring = 1;
- } else if (link_option(option, "oformat=", &p)) {
-#if defined(TCC_TARGET_PE)
- if (strstart("pe-", &p)) {
-#elif PTR_SIZE == 8
- if (strstart("elf64-", &p)) {
-#else
- if (strstart("elf32-", &p)) {
-#endif
- s->output_format = TCC_OUTPUT_FORMAT_ELF;
- } else if (!strcmp(p, "binary")) {
- s->output_format = TCC_OUTPUT_FORMAT_BINARY;
-#ifdef TCC_TARGET_COFF
- } else if (!strcmp(p, "coff")) {
- s->output_format = TCC_OUTPUT_FORMAT_COFF;
-#endif
- } else
- goto err;
-
- } else if (link_option(option, "as-needed", &p)) {
- ignoring = 1;
- } else if (link_option(option, "O", &p)) {
- ignoring = 1;
- } else if (link_option(option, "export-all-symbols", &p)) {
- s->rdynamic = 1;
- } else if (link_option(option, "export-dynamic", &p)) {
- s->rdynamic = 1;
- } else if (link_option(option, "rpath=", &p)) {
- copy_linker_arg(&s->rpath, p, ':');
- } else if (link_option(option, "enable-new-dtags", &p)) {
- s->enable_new_dtags = 1;
- } else if (link_option(option, "section-alignment=", &p)) {
- s->section_align = strtoul(p, &end, 16);
- } else if (link_option(option, "soname=", &p)) {
- copy_linker_arg(&s->soname, p, 0);
- } else if (link_option(option, "install_name=", &p)) {
- copy_linker_arg(&s->soname, p, 0);
-#ifdef TCC_TARGET_PE
- } else if (link_option(option, "large-address-aware", &p)) {
- s->pe_characteristics |= 0x20;
- } else if (link_option(option, "file-alignment=", &p)) {
- s->pe_file_align = strtoul(p, &end, 16);
- } else if (link_option(option, "stack=", &p)) {
- s->pe_stack_size = strtoul(p, &end, 10);
- } else if (link_option(option, "subsystem=", &p)) {
-#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
- if (!strcmp(p, "native")) {
- s->pe_subsystem = 1;
- } else if (!strcmp(p, "console")) {
- s->pe_subsystem = 3;
- } else if (!strcmp(p, "gui") || !strcmp(p, "windows")) {
- s->pe_subsystem = 2;
- } else if (!strcmp(p, "posix")) {
- s->pe_subsystem = 7;
- } else if (!strcmp(p, "efiapp")) {
- s->pe_subsystem = 10;
- } else if (!strcmp(p, "efiboot")) {
- s->pe_subsystem = 11;
- } else if (!strcmp(p, "efiruntime")) {
- s->pe_subsystem = 12;
- } else if (!strcmp(p, "efirom")) {
- s->pe_subsystem = 13;
-#elif defined(TCC_TARGET_ARM)
- if (!strcmp(p, "wince")) {
- s->pe_subsystem = 9;
-#endif
- } else
- goto err;
-#endif
-#ifdef TCC_TARGET_MACHO
- } else if (link_option(option, "all_load", &p)) {
- s->filetype |= AFF_WHOLE_ARCHIVE;
- } else if (link_option(option, "force_load", &p)) {
- s->filetype |= AFF_WHOLE_ARCHIVE;
- args_parser_add_file(s, p, AFF_TYPE_LIB | (s->filetype & ~AFF_TYPE_MASK));
- s->nb_libraries++;
- } else if (link_option(option, "single_module", &p)) {
- ignoring = 1;
-#endif
- } else if (ret = link_option(option, "?whole-archive", &p), ret) {
- if (ret > 0)
- s->filetype |= AFF_WHOLE_ARCHIVE;
- else
- s->filetype &= ~AFF_WHOLE_ARCHIVE;
- } else if (link_option(option, "z=", &p)) {
- ignoring = 1;
- } else if (p) {
- return 0;
- } else {
- err:
- return tcc_error_noabort("unsupported linker option '%s'", option);
- }
- if (ignoring)
- tcc_warning_c(warn_unsupported)("unsupported linker option '%s'", option);
- option = skip_linker_arg(&p);
- }
- return 1;
-}
-
-typedef struct TCCOption {
- const char *name;
- uint16_t index;
- uint16_t flags;
-} TCCOption;
-
-enum {
- TCC_OPTION_ignored = 0,
- TCC_OPTION_HELP,
- TCC_OPTION_HELP2,
- TCC_OPTION_v,
- TCC_OPTION_I,
- TCC_OPTION_D,
- TCC_OPTION_U,
- TCC_OPTION_P,
- TCC_OPTION_L,
- TCC_OPTION_B,
- TCC_OPTION_l,
- TCC_OPTION_bench,
- TCC_OPTION_bt,
- TCC_OPTION_b,
- TCC_OPTION_ba,
- TCC_OPTION_g,
- TCC_OPTION_c,
- TCC_OPTION_dumpversion,
- TCC_OPTION_d,
- TCC_OPTION_static,
- TCC_OPTION_std,
- TCC_OPTION_shared,
- TCC_OPTION_soname,
- TCC_OPTION_o,
- TCC_OPTION_r,
- TCC_OPTION_Wl,
- TCC_OPTION_Wp,
- TCC_OPTION_W,
- TCC_OPTION_O,
- TCC_OPTION_mfloat_abi,
- TCC_OPTION_m,
- TCC_OPTION_f,
- TCC_OPTION_isystem,
- TCC_OPTION_iwithprefix,
- TCC_OPTION_include,
- TCC_OPTION_nostdinc,
- TCC_OPTION_nostdlib,
- TCC_OPTION_print_search_dirs,
- TCC_OPTION_rdynamic,
- TCC_OPTION_pthread,
- TCC_OPTION_run,
- TCC_OPTION_w,
- TCC_OPTION_E,
- TCC_OPTION_M,
- TCC_OPTION_MD,
- TCC_OPTION_MF,
- TCC_OPTION_MM,
- TCC_OPTION_MMD,
- TCC_OPTION_x,
- TCC_OPTION_ar,
- TCC_OPTION_impdef,
- TCC_OPTION_dynamiclib,
- TCC_OPTION_flat_namespace,
- TCC_OPTION_two_levelnamespace,
- TCC_OPTION_undefined,
- TCC_OPTION_install_name,
- TCC_OPTION_compatibility_version ,
- TCC_OPTION_current_version,
-};
-
-#define TCC_OPTION_HAS_ARG 0x0001
-#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
-
-static const TCCOption tcc_options[] = {
- { "h", TCC_OPTION_HELP, 0 },
- { "-help", TCC_OPTION_HELP, 0 },
- { "?", TCC_OPTION_HELP, 0 },
- { "hh", TCC_OPTION_HELP2, 0 },
- { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "-version", TCC_OPTION_v, 0 }, /* handle as verbose, also prints version*/
- { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
- { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
- { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
- { "P", TCC_OPTION_P, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
- { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
- { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG },
- { "bench", TCC_OPTION_bench, 0 },
-#ifdef CONFIG_TCC_BACKTRACE
- { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-#endif
-#ifdef CONFIG_TCC_BCHECK
- { "b", TCC_OPTION_b, 0 },
-#endif
- { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-#ifdef TCC_TARGET_MACHO
- { "compatibility_version", TCC_OPTION_compatibility_version, TCC_OPTION_HAS_ARG },
- { "current_version", TCC_OPTION_current_version, TCC_OPTION_HAS_ARG },
-#endif
- { "c", TCC_OPTION_c, 0 },
-#ifdef TCC_TARGET_MACHO
- { "dynamiclib", TCC_OPTION_dynamiclib, 0 },
-#endif
- { "dumpversion", TCC_OPTION_dumpversion, 0},
- { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "static", TCC_OPTION_static, 0 },
- { "std", TCC_OPTION_std, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "shared", TCC_OPTION_shared, 0 },
- { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
- { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
- { "pthread", TCC_OPTION_pthread, 0},
- { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "rdynamic", TCC_OPTION_rdynamic, 0 },
- { "r", TCC_OPTION_r, 0 },
- { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "Wp,", TCC_OPTION_Wp, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-#ifdef TCC_TARGET_ARM
- { "mfloat-abi", TCC_OPTION_mfloat_abi, TCC_OPTION_HAS_ARG },
-#endif
- { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
-#ifdef TCC_TARGET_MACHO
- { "flat_namespace", TCC_OPTION_flat_namespace, 0 },
-#endif
- { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
- { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
- { "include", TCC_OPTION_include, TCC_OPTION_HAS_ARG },
- { "nostdinc", TCC_OPTION_nostdinc, 0 },
- { "nostdlib", TCC_OPTION_nostdlib, 0 },
- { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
- { "w", TCC_OPTION_w, 0 },
- { "E", TCC_OPTION_E, 0},
- { "M", TCC_OPTION_M, 0},
- { "MD", TCC_OPTION_MD, 0},
- { "MF", TCC_OPTION_MF, TCC_OPTION_HAS_ARG },
- { "MM", TCC_OPTION_MM, 0},
- { "MMD", TCC_OPTION_MMD, 0},
- { "x", TCC_OPTION_x, TCC_OPTION_HAS_ARG },
- { "ar", TCC_OPTION_ar, 0},
-#ifdef TCC_TARGET_PE
- { "impdef", TCC_OPTION_impdef, 0},
-#endif
-#ifdef TCC_TARGET_MACHO
- { "install_name", TCC_OPTION_install_name, TCC_OPTION_HAS_ARG },
- { "two_levelnamespace", TCC_OPTION_two_levelnamespace, 0 },
- { "undefined", TCC_OPTION_undefined, TCC_OPTION_HAS_ARG },
-#endif
- /* ignored (silently, except after -Wunsupported) */
- { "arch", 0, TCC_OPTION_HAS_ARG},
- { "C", 0, 0 },
- { "-param", 0, TCC_OPTION_HAS_ARG },
- { "pedantic", 0, 0 },
- { "pipe", 0, 0 },
- { "s", 0, 0 },
- { "traditional", 0, 0 },
- { NULL, 0, 0 },
-};
-
-typedef struct FlagDef {
- uint16_t offset;
- uint16_t flags;
- const char *name;
-} FlagDef;
-
-#define WD_ALL 0x0001 /* warning is activated when using -Wall */
-#define FD_INVERT 0x0002 /* invert value before storing */
-
-static const FlagDef options_W[] = {
- { offsetof(TCCState, warn_all), WD_ALL, "all" },
- { offsetof(TCCState, warn_error), 0, "error" },
- { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
- { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
- { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL, "implicit-function-declaration" },
- { offsetof(TCCState, warn_discarded_qualifiers), WD_ALL, "discarded-qualifiers" },
- { 0, 0, NULL }
-};
-
-static const FlagDef options_f[] = {
- { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
- { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
- { offsetof(TCCState, nocommon), FD_INVERT, "common" },
- { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
- { offsetof(TCCState, ms_extensions), 0, "ms-extensions" },
- { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
- { offsetof(TCCState, test_coverage), 0, "test-coverage" },
- { 0, 0, NULL }
-};
-
-static const FlagDef options_m[] = {
- { offsetof(TCCState, ms_bitfields), 0, "ms-bitfields" },
-#ifdef TCC_TARGET_X86_64
- { offsetof(TCCState, nosse), FD_INVERT, "sse" },
-#endif
- { 0, 0, NULL }
-};
-
-static int set_flag(TCCState *s, const FlagDef *flags, const char *name)
-{
- int value, mask, ret;
- const FlagDef *p;
- const char *r;
- unsigned char *f;
-
- r = name, value = !strstart("no-", &r), mask = 0;
-
- /* when called with options_W, look for -W[no-]error=<option> */
- if ((flags->flags & WD_ALL) && strstart("error=", &r))
- value = value ? WARN_ON|WARN_ERR : WARN_NOE, mask = WARN_ON;
-
- for (ret = -1, p = flags; p->name; ++p) {
- if (ret) {
- if (strcmp(r, p->name))
- continue;
- } else {
- if (0 == (p->flags & WD_ALL))
- continue;
- }
-
- f = (unsigned char *)s + p->offset;
- *f = (*f & mask) | (value ^ !!(p->flags & FD_INVERT));
-
- if (ret) {
- ret = 0;
- if (strcmp(r, "all"))
- break;
- }
- }
- return ret;
-}
-
-static int args_parser_make_argv(const char *r, int *argc, char ***argv)
-{
- int ret = 0, q, c;
- CString str;
- for(;;) {
- while (c = (unsigned char)*r, c && c <= ' ')
- ++r;
- if (c == 0)
- break;
- q = 0;
- cstr_new(&str);
- while (c = (unsigned char)*r, c) {
- ++r;
- if (c == '\\' && (*r == '"' || *r == '\\')) {
- c = *r++;
- } else if (c == '"') {
- q = !q;
- continue;
- } else if (q == 0 && c <= ' ') {
- break;
- }
- cstr_ccat(&str, c);
- }
- cstr_ccat(&str, 0);
- //printf("<%s>\n", str.data), fflush(stdout);
- dynarray_add(argv, argc, tcc_strdup(str.data));
- cstr_free(&str);
- ++ret;
- }
- return ret;
-}
-
-/* read list file */
-static int args_parser_listfile(TCCState *s,
- const char *filename, int optind, int *pargc, char ***pargv)
-{
- TCCState *s1 = s;
- int fd, i;
- char *p;
- int argc = 0;
- char **argv = NULL;
-
- fd = open(filename, O_RDONLY | O_BINARY);
- if (fd < 0)
- return tcc_error_noabort("listfile '%s' not found", filename);
-
- p = tcc_load_text(fd);
- for (i = 0; i < *pargc; ++i)
- if (i == optind)
- args_parser_make_argv(p, &argc, &argv);
- else
- dynarray_add(&argv, &argc, tcc_strdup((*pargv)[i]));
-
- tcc_free(p);
- dynarray_reset(&s->argv, &s->argc);
- *pargc = s->argc = argc, *pargv = s->argv = argv;
- return 0;
-}
-
-#if defined TCC_TARGET_MACHO
-static uint32_t parse_version(TCCState *s1, const char *version)
-{
- uint32_t a = 0;
- uint32_t b = 0;
- uint32_t c = 0;
- char* last;
-
- a = strtoul(version, &last, 10);
- if (*last == '.') {
- b = strtoul(&last[1], &last, 10);
- if (*last == '.')
- c = strtoul(&last[1], &last, 10);
- }
- if (*last || a > 0xffff || b > 0xff || c > 0xff)
- tcc_error_noabort("version a.b.c not correct: %s", version);
- return (a << 16) | (b << 8) | c;
-}
-#endif
-
-PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv, int optind)
-{
- TCCState *s1 = s;
- const TCCOption *popt;
- const char *optarg, *r;
- const char *run = NULL;
- int x;
- int tool = 0, arg_start = 0, noaction = optind;
- char **argv = *pargv;
- int argc = *pargc;
-
- cstr_reset(&s->linker_arg);
-
- while (optind < argc) {
- r = argv[optind];
- if (r[0] == '@' && r[1] != '\0') {
- if (args_parser_listfile(s, r + 1, optind, &argc, &argv))
- return -1;
- continue;
- }
- optind++;
- if (tool) {
- if (r[0] == '-' && r[1] == 'v' && r[2] == 0)
- ++s->verbose;
- continue;
- }
-reparse:
- if (r[0] != '-' || r[1] == '\0') {
- args_parser_add_file(s, r, s->filetype);
- if (run) {
-dorun:
- if (tcc_set_options(s, run))
- return -1;
- arg_start = optind - 1;
- break;
- }
- continue;
- }
-
- /* allow "tcc files... -run -- args ..." */
- if (r[1] == '-' && r[2] == '\0' && run)
- goto dorun;
-
- /* find option in table */
- for(popt = tcc_options; ; ++popt) {
- const char *p1 = popt->name;
- const char *r1 = r + 1;
- if (p1 == NULL)
- return tcc_error_noabort("invalid option -- '%s'", r);
- if (!strstart(p1, &r1))
- continue;
- optarg = r1;
- if (popt->flags & TCC_OPTION_HAS_ARG) {
- if (*r1 == '\0' && !(popt->flags & TCC_OPTION_NOSEP)) {
- if (optind >= argc)
- arg_err:
- return tcc_error_noabort("argument to '%s' is missing", r);
- optarg = argv[optind++];
- }
- } else if (*r1 != '\0')
- continue;
- break;
- }
-
- switch(popt->index) {
- case TCC_OPTION_HELP:
- x = OPT_HELP;
- goto extra_action;
- case TCC_OPTION_HELP2:
- x = OPT_HELP2;
- goto extra_action;
- case TCC_OPTION_I:
- tcc_add_include_path(s, optarg);
- break;
- case TCC_OPTION_D:
- tcc_define_symbol(s, optarg, NULL);
- break;
- case TCC_OPTION_U:
- tcc_undefine_symbol(s, optarg);
- break;
- case TCC_OPTION_L:
- tcc_add_library_path(s, optarg);
- break;
- case TCC_OPTION_B:
- /* set tcc utilities path (mainly for tcc development) */
- tcc_set_lib_path(s, optarg);
- ++noaction;
- break;
- case TCC_OPTION_l:
- args_parser_add_file(s, optarg, AFF_TYPE_LIB | (s->filetype & ~AFF_TYPE_MASK));
- s->nb_libraries++;
- break;
- case TCC_OPTION_pthread:
- s->option_pthread = 1;
- break;
- case TCC_OPTION_bench:
- s->do_bench = 1;
- break;
-#ifdef CONFIG_TCC_BACKTRACE
- case TCC_OPTION_bt:
- s->rt_num_callers = atoi(optarg);
- s->do_backtrace = 1;
- s->do_debug = 1;
- s->dwarf = DWARF_VERSION;
- break;
-#endif
-#ifdef CONFIG_TCC_BCHECK
- case TCC_OPTION_b:
- s->do_bounds_check = 1;
- s->do_backtrace = 1;
- s->do_debug = 1;
- s->dwarf = DWARF_VERSION;
- break;
-#endif
- case TCC_OPTION_g:
- s->do_debug = 1;
- s->dwarf = DWARF_VERSION;
-
- if (strstart("dwarf", &optarg))
- s->dwarf = (*optarg) ? (0 - atoi(optarg)) : DEFAULT_DWARF_VERSION;
- break;
- case TCC_OPTION_c:
- x = TCC_OUTPUT_OBJ;
- set_output_type:
- if (s->output_type)
- tcc_warning("-%s: overriding compiler action already specified", popt->name);
- s->output_type = x;
- break;
- case TCC_OPTION_d:
- if (*optarg == 'D')
- s->dflag = 3;
- else if (*optarg == 'M')
- s->dflag = 7;
- else if (*optarg == 't')
- s->dflag = 16;
- else if (isnum(*optarg))
- s->g_debug |= atoi(optarg);
- else
- goto unsupported_option;
- break;
- case TCC_OPTION_static:
- s->static_link = 1;
- break;
- case TCC_OPTION_std:
- if (strcmp(optarg, "=c11") == 0)
- s->cversion = 201112;
- break;
- case TCC_OPTION_shared:
- x = TCC_OUTPUT_DLL;
- goto set_output_type;
- case TCC_OPTION_soname:
- s->soname = tcc_strdup(optarg);
- break;
- case TCC_OPTION_o:
- if (s->outfile) {
- tcc_warning("multiple -o option");
- tcc_free(s->outfile);
- }
- s->outfile = tcc_strdup(optarg);
- break;
- case TCC_OPTION_r:
- /* generate a .o merging several output files */
- s->option_r = 1;
- x = TCC_OUTPUT_OBJ;
- goto set_output_type;
- case TCC_OPTION_isystem:
- tcc_add_sysinclude_path(s, optarg);
- break;
- case TCC_OPTION_include:
- cstr_printf(&s->cmdline_incl, "#include \"%s\"\n", optarg);
- break;
- case TCC_OPTION_nostdinc:
- s->nostdinc = 1;
- break;
- case TCC_OPTION_nostdlib:
- s->nostdlib = 1;
- break;
- case TCC_OPTION_run:
-#ifndef TCC_IS_NATIVE
- return tcc_error_noabort("-run is not available in a cross compiler");
-#else
- run = optarg;
- x = TCC_OUTPUT_MEMORY;
- goto set_output_type;
-#endif
- case TCC_OPTION_v:
- do ++s->verbose; while (*optarg++ == 'v');
- ++noaction;
- break;
- case TCC_OPTION_f:
- if (set_flag(s, options_f, optarg) < 0)
- goto unsupported_option;
- break;
-#ifdef TCC_TARGET_ARM
- case TCC_OPTION_mfloat_abi:
- /* tcc doesn't support soft float yet */
- if (!strcmp(optarg, "softfp")) {
- s->float_abi = ARM_SOFTFP_FLOAT;
- } else if (!strcmp(optarg, "hard"))
- s->float_abi = ARM_HARD_FLOAT;
- else
- return tcc_error_noabort("unsupported float abi '%s'", optarg);
- break;
-#endif
- case TCC_OPTION_m:
- if (set_flag(s, options_m, optarg) < 0) {
- if (x = atoi(optarg), x != 32 && x != 64)
- goto unsupported_option;
- if (PTR_SIZE != x/8)
- return x;
- ++noaction;
- }
- break;
- case TCC_OPTION_W:
- s->warn_none = 0;
- if (optarg[0] && set_flag(s, options_W, optarg) < 0)
- goto unsupported_option;
- break;
- case TCC_OPTION_w:
- s->warn_none = 1;
- break;
- case TCC_OPTION_rdynamic:
- s->rdynamic = 1;
- break;
- case TCC_OPTION_Wl:
- if (s->linker_arg.size)
- ((char*)s->linker_arg.data)[s->linker_arg.size - 1] = ',';
- cstr_cat(&s->linker_arg, optarg, 0);
- x = tcc_set_linker(s, s->linker_arg.data);
- if (x)
- cstr_reset(&s->linker_arg);
- if (x < 0)
- return -1;
- break;
- case TCC_OPTION_Wp:
- r = optarg;
- goto reparse;
- case TCC_OPTION_E:
- x = TCC_OUTPUT_PREPROCESS;
- goto set_output_type;
- case TCC_OPTION_P:
- s->Pflag = atoi(optarg) + 1;
- break;
- case TCC_OPTION_M:
- s->include_sys_deps = 1;
- // fall through
- case TCC_OPTION_MM:
- s->just_deps = 1;
- if(!s->deps_outfile)
- s->deps_outfile = tcc_strdup("-");
- // fall through
- case TCC_OPTION_MMD:
- s->gen_deps = 1;
- break;
- case TCC_OPTION_MD:
- s->gen_deps = 1;
- s->include_sys_deps = 1;
- break;
- case TCC_OPTION_MF:
- s->deps_outfile = tcc_strdup(optarg);
- break;
- case TCC_OPTION_dumpversion:
- printf ("%s\n", TCC_VERSION);
- exit(0);
- break;
- case TCC_OPTION_x:
- x = 0;
- if (*optarg == 'c')
- x = AFF_TYPE_C;
- else if (*optarg == 'a')
- x = AFF_TYPE_ASMPP;
- else if (*optarg == 'b')
- x = AFF_TYPE_BIN;
- else if (*optarg == 'n')
- x = AFF_TYPE_NONE;
- else
- tcc_warning("unsupported language '%s'", optarg);
- s->filetype = x | (s->filetype & ~AFF_TYPE_MASK);
- break;
- case TCC_OPTION_O:
- s->optimize = atoi(optarg);
- break;
- case TCC_OPTION_print_search_dirs:
- x = OPT_PRINT_DIRS;
- goto extra_action;
- case TCC_OPTION_impdef:
- x = OPT_IMPDEF;
- goto extra_action;
-#if defined TCC_TARGET_MACHO
- case TCC_OPTION_dynamiclib:
- x = TCC_OUTPUT_DLL;
- goto set_output_type;
- case TCC_OPTION_flat_namespace:
- break;
- case TCC_OPTION_two_levelnamespace:
- break;
- case TCC_OPTION_undefined:
- break;
- case TCC_OPTION_install_name:
- s->install_name = tcc_strdup(optarg);
- break;
- case TCC_OPTION_compatibility_version:
- s->compatibility_version = parse_version(s, optarg);
- break;
- case TCC_OPTION_current_version:
- s->current_version = parse_version(s, optarg);;
- break;
-#endif
- case TCC_OPTION_ar:
- x = OPT_AR;
- extra_action:
- arg_start = optind - 1;
- if (arg_start != noaction)
- return tcc_error_noabort("cannot parse %s here", r);
- tool = x;
- break;
- default:
-unsupported_option:
- tcc_warning_c(warn_unsupported)("unsupported option '%s'", r);
- break;
- }
- }
- if (s->linker_arg.size) {
- r = s->linker_arg.data;
- goto arg_err;
- }
- *pargc = argc - arg_start;
- *pargv = argv + arg_start;
- if (tool)
- return tool;
- if (optind != noaction)
- return 0;
- if (s->verbose == 2)
- return OPT_PRINT_DIRS;
- if (s->verbose)
- return OPT_V;
- return OPT_HELP;
-}
-
-LIBTCCAPI int tcc_set_options(TCCState *s, const char *r)
-{
- char **argv = NULL;
- int argc = 0, ret;
- args_parser_make_argv(r, &argc, &argv);
- ret = tcc_parse_args(s, &argc, &argv, 0);
- dynarray_reset(&argv, &argc);
- return ret < 0 ? ret : 0;
-}
-
-PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
-{
- if (!total_time)
- total_time = 1;
- fprintf(stderr, "# %d idents, %d lines, %u bytes\n"
- "# %0.3f s, %u lines/s, %0.1f MB/s\n",
- total_idents, total_lines, total_bytes,
- (double)total_time/1000,
- (unsigned)total_lines*1000/total_time,
- (double)total_bytes/1000/total_time);
- fprintf(stderr, "# text %u, data.rw %u, data.ro %u, bss %u bytes\n",
- s1->total_output[0],
- s1->total_output[1],
- s1->total_output[2],
- s1->total_output[3]
- );
-#ifdef MEM_DEBUG
- fprintf(stderr, "# %d bytes memory used\n", mem_max_size);
-#endif
-}
diff --git a/tinycc/libtcc.h b/tinycc/libtcc.h
deleted file mode 100644
index 8450ba8..0000000
--- a/tinycc/libtcc.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#ifndef LIBTCC_H
-#define LIBTCC_H
-
-#ifndef LIBTCCAPI
-# define LIBTCCAPI
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct TCCState;
-
-typedef struct TCCState TCCState;
-
-typedef void (*TCCErrorFunc)(void *opaque, const char *msg);
-
-/* create a new TCC compilation context */
-LIBTCCAPI TCCState *tcc_new(void);
-
-/* free a TCC compilation context */
-LIBTCCAPI void tcc_delete(TCCState *s);
-
-/* set CONFIG_TCCDIR at runtime */
-LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
-
-/* set error/warning display callback */
-LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc error_func);
-
-/* return error/warning callback */
-LIBTCCAPI TCCErrorFunc tcc_get_error_func(TCCState *s);
-
-/* return error/warning callback opaque pointer */
-LIBTCCAPI void *tcc_get_error_opaque(TCCState *s);
-
-/* set options as from command line (multiple supported) */
-LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
-
-/*****************************/
-/* preprocessor */
-
-/* add include path */
-LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);
-
-/* add in system include path */
-LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
-
-/* define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val" */
-LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
-
-/* undefine preprocess symbol 'sym' */
-LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
-
-/*****************************/
-/* compiling */
-
-/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
-LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
-
-/* compile a string containing a C source. Return -1 if error. */
-LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
-
-/*****************************/
-/* linking commands */
-
-/* set output type. MUST BE CALLED before any compilation */
-LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
-#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory */
-#define TCC_OUTPUT_EXE 2 /* executable file */
-#define TCC_OUTPUT_DLL 4 /* dynamic library */
-#define TCC_OUTPUT_OBJ 3 /* object file */
-#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess */
-
-/* equivalent to -Lpath option */
-LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
-
-/* the library name is the same as the argument of the '-l' option */
-LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);
-
-/* add a symbol to the compiled program */
-LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val);
-
-/* output an executable, library or object file. DO NOT call
- tcc_relocate() before. */
-LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
-
-/* link and run main() function and return its value. DO NOT call
- tcc_relocate() before. */
-LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
-
-/* do all relocations (needed before using tcc_get_symbol()) */
-LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
-/* possible values for 'ptr':
- - TCC_RELOCATE_AUTO : Allocate and manage memory internally
- - NULL : return required memory size for the step below
- - memory address : copy code to memory passed by the caller
- returns -1 if error. */
-#define TCC_RELOCATE_AUTO (void*)1
-
-/* return symbol value or NULL if not found */
-LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
-
-/* return symbol value or NULL if not found */
-LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
- void (*symbol_cb)(void *ctx, const char *name, const void *val));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/tinycc/stab.def b/tinycc/stab.def
deleted file mode 100644
index 48ea231..0000000
--- a/tinycc/stab.def
+++ /dev/null
@@ -1,234 +0,0 @@
-/* Table of DBX symbol codes for the GNU system.
- Copyright (C) 1988, 1997 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* This contains contribution from Cygnus Support. */
-
-/* Global variable. Only the name is significant.
- To find the address, look in the corresponding external symbol. */
-__define_stab (N_GSYM, 0x20, "GSYM")
-
-/* Function name for BSD Fortran. Only the name is significant.
- To find the address, look in the corresponding external symbol. */
-__define_stab (N_FNAME, 0x22, "FNAME")
-
-/* Function name or text-segment variable for C. Value is its address.
- Desc is supposedly starting line number, but GCC doesn't set it
- and DBX seems not to miss it. */
-__define_stab (N_FUN, 0x24, "FUN")
-
-/* Data-segment variable with internal linkage. Value is its address.
- "Static Sym". */
-__define_stab (N_STSYM, 0x26, "STSYM")
-
-/* BSS-segment variable with internal linkage. Value is its address. */
-__define_stab (N_LCSYM, 0x28, "LCSYM")
-
-/* Name of main routine. Only the name is significant.
- This is not used in C. */
-__define_stab (N_MAIN, 0x2a, "MAIN")
-
-/* Global symbol in Pascal.
- Supposedly the value is its line number; I'm skeptical. */
-__define_stab (N_PC, 0x30, "PC")
-
-/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
-__define_stab (N_NSYMS, 0x32, "NSYMS")
-
-/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
-__define_stab (N_NOMAP, 0x34, "NOMAP")
-
-/* New stab from Solaris. I don't know what it means, but it
- don't seem to contain useful information. */
-__define_stab (N_OBJ, 0x38, "OBJ")
-
-/* New stab from Solaris. I don't know what it means, but it
- don't seem to contain useful information. Possibly related to the
- optimization flags used in this module. */
-__define_stab (N_OPT, 0x3c, "OPT")
-
-/* Register variable. Value is number of register. */
-__define_stab (N_RSYM, 0x40, "RSYM")
-
-/* Modula-2 compilation unit. Can someone say what info it contains? */
-__define_stab (N_M2C, 0x42, "M2C")
-
-/* Line number in text segment. Desc is the line number;
- value is corresponding address. */
-__define_stab (N_SLINE, 0x44, "SLINE")
-
-/* Similar, for data segment. */
-__define_stab (N_DSLINE, 0x46, "DSLINE")
-
-/* Similar, for bss segment. */
-__define_stab (N_BSLINE, 0x48, "BSLINE")
-
-/* Sun's source-code browser stabs. ?? Don't know what the fields are.
- Supposedly the field is "path to associated .cb file". THIS VALUE
- OVERLAPS WITH N_BSLINE! */
-__define_stab (N_BROWS, 0x48, "BROWS")
-
-/* GNU Modula-2 definition module dependency. Value is the modification time
- of the definition file. Other is non-zero if it is imported with the
- GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
- are enough empty fields? */
-__define_stab(N_DEFD, 0x4a, "DEFD")
-
-/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
- and one is for C++. Still,... */
-/* GNU C++ exception variable. Name is variable name. */
-__define_stab (N_EHDECL, 0x50, "EHDECL")
-/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
-__define_stab (N_MOD2, 0x50, "MOD2")
-
-/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
- this entry is immediately followed by a CAUGHT stab saying what exception
- was caught. Multiple CAUGHT stabs means that multiple exceptions
- can be caught here. If Desc is 0, it means all exceptions are caught
- here. */
-__define_stab (N_CATCH, 0x54, "CATCH")
-
-/* Structure or union element. Value is offset in the structure. */
-__define_stab (N_SSYM, 0x60, "SSYM")
-
-/* Name of main source file.
- Value is starting text address of the compilation. */
-__define_stab (N_SO, 0x64, "SO")
-
-/* Automatic variable in the stack. Value is offset from frame pointer.
- Also used for type descriptions. */
-__define_stab (N_LSYM, 0x80, "LSYM")
-
-/* Beginning of an include file. Only Sun uses this.
- In an object file, only the name is significant.
- The Sun linker puts data into some of the other fields. */
-__define_stab (N_BINCL, 0x82, "BINCL")
-
-/* Name of sub-source file (#include file).
- Value is starting text address of the compilation. */
-__define_stab (N_SOL, 0x84, "SOL")
-
-/* Parameter variable. Value is offset from argument pointer.
- (On most machines the argument pointer is the same as the frame pointer. */
-__define_stab (N_PSYM, 0xa0, "PSYM")
-
-/* End of an include file. No name.
- This and N_BINCL act as brackets around the file's output.
- In an object file, there is no significant data in this entry.
- The Sun linker puts data into some of the fields. */
-__define_stab (N_EINCL, 0xa2, "EINCL")
-
-/* Alternate entry point. Value is its address. */
-__define_stab (N_ENTRY, 0xa4, "ENTRY")
-
-/* Beginning of lexical block.
- The desc is the nesting level in lexical blocks.
- The value is the address of the start of the text for the block.
- The variables declared inside the block *precede* the N_LBRAC symbol. */
-__define_stab (N_LBRAC, 0xc0, "LBRAC")
-
-/* Place holder for deleted include file. Replaces a N_BINCL and everything
- up to the corresponding N_EINCL. The Sun linker generates these when
- it finds multiple identical copies of the symbols from an include file.
- This appears only in output from the Sun linker. */
-__define_stab (N_EXCL, 0xc2, "EXCL")
-
-/* Modula-2 scope information. Can someone say what info it contains? */
-__define_stab (N_SCOPE, 0xc4, "SCOPE")
-
-/* End of a lexical block. Desc matches the N_LBRAC's desc.
- The value is the address of the end of the text for the block. */
-__define_stab (N_RBRAC, 0xe0, "RBRAC")
-
-/* Begin named common block. Only the name is significant. */
-__define_stab (N_BCOMM, 0xe2, "BCOMM")
-
-/* End named common block. Only the name is significant
- (and it should match the N_BCOMM). */
-__define_stab (N_ECOMM, 0xe4, "ECOMM")
-
-/* End common (local name): value is address.
- I'm not sure how this is used. */
-__define_stab (N_ECOML, 0xe8, "ECOML")
-
-/* These STAB's are used on Gould systems for Non-Base register symbols
- or something like that. FIXME. I have assigned the values at random
- since I don't have a Gould here. Fixups from Gould folk welcome... */
-__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
-__define_stab (N_NBDATA, 0xF2, "NBDATA")
-__define_stab (N_NBBSS, 0xF4, "NBBSS")
-__define_stab (N_NBSTS, 0xF6, "NBSTS")
-__define_stab (N_NBLCS, 0xF8, "NBLCS")
-
-/* Second symbol entry containing a length-value for the preceding entry.
- The value is the length. */
-__define_stab (N_LENG, 0xfe, "LENG")
-
-/* The above information, in matrix format.
-
- STAB MATRIX
- _________________________________________________
- | 00 - 1F are not dbx stab symbols |
- | In most cases, the low bit is the EXTernal bit|
-
- | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
- | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
-
- | 08 BSS | 0A INDR | 0C FN_SEQ | 0E |
- | 09 |EXT | 0B | 0D | 0F |
-
- | 10 | 12 COMM | 14 SETA | 16 SETT |
- | 11 | 13 | 15 | 17 |
-
- | 18 SETD | 1A SETB | 1C SETV | 1E WARNING|
- | 19 | 1B | 1D | 1F FN |
-
- |_______________________________________________|
- | Debug entries with bit 01 set are unused. |
- | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
- | 28 LCSYM | 2A MAIN | 2C | 2E |
- | 30 PC | 32 NSYMS | 34 NOMAP | 36 |
- | 38 OBJ | 3A | 3C OPT | 3E |
- | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE |
- | 48 BSLINE*| 4A DEFD | 4C | 4E |
- | 50 EHDECL*| 52 | 54 CATCH | 56 |
- | 58 | 5A | 5C | 5E |
- | 60 SSYM | 62 | 64 SO | 66 |
- | 68 | 6A | 6C | 6E |
- | 70 | 72 | 74 | 76 |
- | 78 | 7A | 7C | 7E |
- | 80 LSYM | 82 BINCL | 84 SOL | 86 |
- | 88 | 8A | 8C | 8E |
- | 90 | 92 | 94 | 96 |
- | 98 | 9A | 9C | 9E |
- | A0 PSYM | A2 EINCL | A4 ENTRY | A6 |
- | A8 | AA | AC | AE |
- | B0 | B2 | B4 | B6 |
- | B8 | BA | BC | BE |
- | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 |
- | C8 | CA | CC | CE |
- | D0 | D2 | D4 | D6 |
- | D8 | DA | DC | DE |
- | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 |
- | E8 ECOML | EA | EC | EE |
- | F0 | F2 | F4 | F6 |
- | F8 | FA | FC | FE LENG |
- +-----------------------------------------------+
- * 50 EHDECL is also MOD2.
- * 48 BSLINE is also BROWS.
- */
diff --git a/tinycc/stab.h b/tinycc/stab.h
deleted file mode 100644
index 80bd594..0000000
--- a/tinycc/stab.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __GNU_STAB__
-
-/* Indicate the GNU stab.h is in use. */
-
-#define __GNU_STAB__
-
-#define __define_stab(NAME, CODE, STRING) NAME=CODE,
-
-enum __stab_debug_code
-{
-#include "stab.def"
-LAST_UNUSED_STAB_CODE
-};
-
-#undef __define_stab
-
-#endif /* __GNU_STAB_ */
diff --git a/tinycc/tcc-doc.texi b/tinycc/tcc-doc.texi
deleted file mode 100644
index 411cdd5..0000000
--- a/tinycc/tcc-doc.texi
+++ /dev/null
@@ -1,1396 +0,0 @@
-\input texinfo @c -*- texinfo -*-
-@c %**start of header
-@setfilename tcc-doc.info
-@settitle Tiny C Compiler Reference Documentation
-@dircategory Software development
-@direntry
-* TCC: (tcc-doc). The Tiny C Compiler.
-@end direntry
-@c %**end of header
-
-@include config.texi
-
-@iftex
-@titlepage
-@afourpaper
-@sp 7
-@center @titlefont{Tiny C Compiler Reference Documentation}
-@sp 3
-@end titlepage
-@headings double
-@end iftex
-
-@contents
-
-@node Top, Introduction, (dir), (dir)
-@top Tiny C Compiler Reference Documentation
-
-This manual documents version @value{VERSION} of the Tiny C Compiler.
-
-@menu
-* Introduction:: Introduction to tcc.
-* Invoke:: Invocation of tcc (command line, options).
-* Clang:: ANSI C and extensions.
-* asm:: Assembler syntax.
-* linker:: Output file generation and supported targets.
-* Bounds:: Automatic bounds-checking of C code.
-* Libtcc:: The libtcc library.
-* devel:: Guide for Developers.
-@end menu
-
-
-@node Introduction
-@chapter Introduction
-
-TinyCC (aka TCC) is a small but hyper fast C compiler. Unlike other C
-compilers, it is meant to be self-relying: you do not need an
-external assembler or linker because TCC does that for you.
-
-TCC compiles so @emph{fast} that even for big projects @code{Makefile}s may
-not be necessary.
-
-TCC not only supports ANSI C, but also most of the new ISO C99
-standard and many GNUC extensions including inline assembly.
-
-TCC can also be used to make @emph{C scripts}, i.e. pieces of C source
-that you run as a Perl or Python script. Compilation is so fast that
-your script will be as fast as if it was an executable.
-
-TCC can also automatically generate memory and bound checks
-(@pxref{Bounds}) while allowing all C pointers operations. TCC can do
-these checks even if non patched libraries are used.
-
-With @code{libtcc}, you can use TCC as a backend for dynamic code
-generation (@pxref{Libtcc}).
-
-TCC mainly supports the i386 target on Linux and Windows. There are alpha
-ports for the ARM (@code{arm-tcc}) and the TMS320C67xx targets
-(@code{c67-tcc}). More information about the ARM port is available at
-@url{http://lists.gnu.org/archive/html/tinycc-devel/2003-10/msg00044.html}.
-
-For usage on Windows, see also @url{tcc-win32.txt}.
-
-@node Invoke
-@chapter Command line invocation
-
-@section Quick start
-
-@example
-@c man begin SYNOPSIS
-usage: tcc [options] [@var{infile1} @var{infile2}@dots{}] [@option{-run} @var{infile} @var{args}@dots{}]
-@c man end
-@end example
-
-@noindent
-@c man begin DESCRIPTION
-TCC options are a very much like gcc options. The main difference is that TCC
-can also execute directly the resulting program and give it runtime
-arguments.
-
-Here are some examples to understand the logic:
-
-@table @code
-@item @samp{tcc -run a.c}
-Compile @file{a.c} and execute it directly
-
-@item @samp{tcc -run a.c arg1}
-Compile a.c and execute it directly. arg1 is given as first argument to
-the @code{main()} of a.c.
-
-@item @samp{tcc a.c -run b.c arg1}
-Compile @file{a.c} and @file{b.c}, link them together and execute them. arg1 is given
-as first argument to the @code{main()} of the resulting program.
-@ignore
-Because multiple C files are specified, @option{--} are necessary to clearly
-separate the program arguments from the TCC options.
-@end ignore
-
-@item @samp{tcc -o myprog a.c b.c}
-Compile @file{a.c} and @file{b.c}, link them and generate the executable @file{myprog}.
-
-@item @samp{tcc -o myprog a.o b.o}
-link @file{a.o} and @file{b.o} together and generate the executable @file{myprog}.
-
-@item @samp{tcc -c a.c}
-Compile @file{a.c} and generate object file @file{a.o}.
-
-@item @samp{tcc -c asmfile.S}
-Preprocess with C preprocess and assemble @file{asmfile.S} and generate
-object file @file{asmfile.o}.
-
-@item @samp{tcc -c asmfile.s}
-Assemble (but not preprocess) @file{asmfile.s} and generate object file
-@file{asmfile.o}.
-
-@item @samp{tcc -r -o ab.o a.c b.c}
-Compile @file{a.c} and @file{b.c}, link them together and generate the object file @file{ab.o}.
-
-@end table
-
-Scripting:
-
-TCC can be invoked from @emph{scripts}, just as shell scripts. You just
-need to add @code{#!/usr/local/bin/tcc -run} at the start of your C source:
-
-@example
-#!/usr/local/bin/tcc -run
-#include <stdio.h>
-
-int main()
-@{
- printf("Hello World\n");
- return 0;
-@}
-@end example
-
-TCC can read C source code from @emph{standard input} when @option{-} is used in
-place of @option{infile}. Example:
-
-@example
-echo 'main()@{puts("hello");@}' | tcc -run -
-@end example
-@c man end
-
-@section Option summary
-
-General Options:
-
-@c man begin OPTIONS
-@table @option
-@item -c
-Generate an object file.
-
-@item -o outfile
-Put object file, executable, or dll into output file @file{outfile}.
-
-@item -run source [args...]
-Compile file @var{source} and run it with the command line arguments
-@var{args}. In order to be able to give more than one argument to a
-script, several TCC options can be given @emph{after} the
-@option{-run} option, separated by spaces:
-@example
-tcc "-run -L/usr/X11R6/lib -lX11" ex4.c
-@end example
-In a script, it gives the following header:
-@example
-#!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
-@end example
-
-@item -v
-Display TCC version.
-
-@item -vv
-Show included files. As sole argument, print search dirs. -vvv shows tries too.
-
-@item -bench
-Display compilation statistics.
-
-@end table
-
-Preprocessor options:
-
-@table @option
-@item -Idir
-Specify an additional include path. Include paths are searched in the
-order they are specified.
-
-System include paths are always searched after. The default system
-include paths are: @file{/usr/local/include}, @file{/usr/include}
-and @file{PREFIX/lib/tcc/include}. (@file{PREFIX} is usually
-@file{/usr} or @file{/usr/local}).
-
-@item -Dsym[=val]
-Define preprocessor symbol @samp{sym} to
-val. If val is not present, its value is @samp{1}. Function-like macros can
-also be defined: @option{-DF(a)=a+1}
-
-@item -Usym
-Undefine preprocessor symbol @samp{sym}.
-
-@item -E
-Preprocess only, to stdout or file (with -o).
-
-@end table
-
-Compilation flags:
-
-Note: each of the following options has a negative form beginning with
-@option{-fno-}.
-
-@table @option
-@item -funsigned-char
-Let the @code{char} type be unsigned.
-
-@item -fsigned-char
-Let the @code{char} type be signed.
-
-@item -fno-common
-Do not generate common symbols for uninitialized data.
-
-@item -fleading-underscore
-Add a leading underscore at the beginning of each C symbol.
-
-@item -fms-extensions
-Allow a MS C compiler extensions to the language. Currently this
-assumes a nested named structure declaration without an identifier
-behaves like an unnamed one.
-
-@item -fdollars-in-identifiers
-Allow dollar signs in identifiers
-
-@item -ftest-coverage
-Create code coverage code. After running the resulting code an executable.tcov
-or sofile.tcov file is generated with code coverage.
-
-@end table
-
-Warning options:
-
-@table @option
-@item -w
-Disable all warnings.
-
-@end table
-
-Note: each of the following warning options has a negative form beginning with
-@option{-Wno-}.
-
-@table @option
-@item -Wimplicit-function-declaration
-Warn about implicit function declaration.
-
-@item -Wunsupported
-Warn about unsupported GCC features that are ignored by TCC.
-
-@item -Wwrite-strings
-Make string constants be of type @code{const char *} instead of @code{char
-*}.
-
-@item -Werror
-Abort compilation if a warning is issued. Can be given an option to enable
-the specified warning and turn it into an error, for example
-@option{-Werror=unsupported}.
-
-@item -Wall
-Activate some useful warnings.
-
-@end table
-
-Linker options:
-
-@table @option
-@item -Ldir
-Specify an additional static library path for the @option{-l} option. The
-default library paths are @file{/usr/local/lib}, @file{/usr/lib} and @file{/lib}.
-
-@item -lxxx
-Link your program with dynamic library libxxx.so or static library
-libxxx.a. The library is searched in the paths specified by the
-@option{-L} option and @env{LIBRARY_PATH} variable.
-
-@item -Bdir
-Set the path where the tcc internal libraries (and include files) can be
-found (default is @file{PREFIX/lib/tcc}).
-
-@item -shared
-Generate a shared library instead of an executable.
-
-@item -soname name
-set name for shared library to be used at runtime
-
-@item -static
-Generate a statically linked executable (default is a shared linked
-executable).
-
-@item -rdynamic
-Export global symbols to the dynamic linker. It is useful when a library
-opened with @code{dlopen()} needs to access executable symbols.
-
-@item -r
-Generate an object file combining all input files.
-
-@item -Wl,-rpath=path
-Put custom search path for dynamic libraries into executable.
-
-@item -Wl,--enable-new-dtags
-When putting a custom search path for dynamic libraries into the executable,
-create the new ELF dynamic tag DT_RUNPATH instead of the old legacy DT_RPATH.
-
-@item -Wl,--oformat=fmt
-Use @var{fmt} as output format. The supported output formats are:
-@table @code
-@item elf32-i386
-ELF output format (default)
-@item binary
-Binary image (only for executable output)
-@item coff
-COFF output format (only for executable output for TMS320C67xx target)
-@end table
-
-@item -Wl,--export-all-symbols
-@item -Wl,--export-dynamic
-Export global symbols to the dynamic linker. It is useful when a library
-opened with @code{dlopen()} needs to access executable symbols.
-
-@item -Wl,-subsystem=console/gui/wince/...
-Set type for PE (Windows) executables.
-
-@item -Wl,-[Ttext=# | section-alignment=# | file-alignment=# | image-base=# | stack=#]
-Modify executable layout.
-
-@item -Wl,-Bsymbolic
-Set DT_SYMBOLIC tag.
-
-@item -Wl,-(no-)whole-archive
-Turn on/off linking of all objects in archives.
-
-@end table
-
-Debugger options:
-
-@table @option
-@item -g
-Generate run time stab debug information so that you get clear run time
-error messages: @code{ test.c:68: in function 'test5()': dereferencing
-invalid pointer} instead of the laconic @code{Segmentation
-fault}.
-
-@item -gdwarf[-x]
-Generate run time dwarf debug information instead of stab debug information.
-
-@item -b
-Generate additional support code to check memory allocations and array/pointer
-bounds (@pxref{Bounds}). @option{-g} is implied.
-
-@item -bt[N]
-Display N callers in stack traces. This is useful with @option{-g} or @option{-b}.
-With executables, additional support for stack traces is included.
-
-A function @code{ int tcc_backtrace(const char *fmt, ...); } is provided
-to trigger a stack trace with a message on demand.
-
-@end table
-
-Misc options:
-
-@table @option
-
-@item -M
-Just output makefile fragment with dependencies
-
-@item -MM
-Like -M except mention only user header files, not system header files.
-
-@item -MD
-Generate makefile fragment with dependencies.
-
-@item -MMD
-Like -MD except mention only user header files, not system header files.
-
-@item -MF depfile
-Use @file{depfile} as output for -MD.
-
-@item -print-search-dirs
-Print the configured installation directory and a list of library
-and include directories tcc will search.
-
-@item -dumpversion
-Print version.
-
-@end table
-
-Target specific options:
-
-@table @option
-@item -mms-bitfields
-Use an algorithm for bitfield alignment consistent with MSVC. Default is
-gcc's algorithm.
-
-@item -mfloat-abi (ARM only)
-Select the float ABI. Possible values: @code{softfp} and @code{hard}
-
-@item -mno-sse
-Do not use sse registers on x86_64
-
-@item -m32, -m64
-Pass command line to the i386/x86_64 cross compiler.
-
-@end table
-
-Note: GCC options @option{-Ox}, @option{-fx} and @option{-mx} are
-ignored.
-@c man end
-
-@c man begin ENVIRONMENT
-Environment variables that affect how tcc operates.
-
-@table @option
-
-@item CPATH
-@item C_INCLUDE_PATH
-A colon-separated list of directories searched for include files,
-directories given with @option{-I} are searched first.
-
-@item LIBRARY_PATH
-A colon-separated list of directories searched for libraries for the
-@option{-l} option, directories given with @option{-L} are searched first.
-
-@end table
-
-@c man end
-
-@ignore
-
-@setfilename tcc
-@settitle Tiny C Compiler
-
-@c man begin SEEALSO
-cpp(1),
-gcc(1)
-@c man end
-
-@c man begin AUTHOR
-Fabrice Bellard
-@c man end
-
-@end ignore
-
-@node Clang
-@chapter C language support
-
-@section ANSI C
-
-TCC implements all the ANSI C standard, including structure bit fields
-and floating point numbers (@code{long double}, @code{double}, and
-@code{float} fully supported).
-
-@section ISOC99 extensions
-
-TCC implements many features of the new C standard: ISO C99. Currently
-missing items are: complex and imaginary numbers.
-
-Currently implemented ISOC99 features:
-
-@itemize
-
-@item variable length arrays.
-
-@item 64 bit @code{long long} types are fully supported.
-
-@item The boolean type @code{_Bool} is supported.
-
-@item @code{__func__} is a string variable containing the current
-function name.
-
-@item Variadic macros: @code{__VA_ARGS__} can be used for
- function-like macros:
-@example
- #define dprintf(level, __VA_ARGS__) printf(__VA_ARGS__)
-@end example
-
-@noindent
-@code{dprintf} can then be used with a variable number of parameters.
-
-@item Declarations can appear anywhere in a block (as in C++).
-
-@item Array and struct/union elements can be initialized in any order by
- using designators:
-@example
- struct @{ int x, y; @} st[10] = @{ [0].x = 1, [0].y = 2 @};
-
- int tab[10] = @{ 1, 2, [5] = 5, [9] = 9@};
-@end example
-
-@item Compound initializers are supported:
-@example
- int *p = (int [])@{ 1, 2, 3 @};
-@end example
-to initialize a pointer pointing to an initialized array. The same
-works for structures and strings.
-
-@item Hexadecimal floating point constants are supported:
-@example
- double d = 0x1234p10;
-@end example
-
-@noindent
-is the same as writing
-@example
- double d = 4771840.0;
-@end example
-
-@item @code{inline} keyword is ignored.
-
-@item @code{restrict} keyword is ignored.
-@end itemize
-
-@section GNU C extensions
-
-TCC implements some GNU C extensions:
-
-@itemize
-
-@item array designators can be used without '=':
-@example
- int a[10] = @{ [0] 1, [5] 2, 3, 4 @};
-@end example
-
-@item Structure field designators can be a label:
-@example
- struct @{ int x, y; @} st = @{ x: 1, y: 1@};
-@end example
-instead of
-@example
- struct @{ int x, y; @} st = @{ .x = 1, .y = 1@};
-@end example
-
-@item @code{\e} is ASCII character 27.
-
-@item case ranges : ranges can be used in @code{case}s:
-@example
- switch(a) @{
- case 1 @dots{} 9:
- printf("range 1 to 9\n");
- break;
- default:
- printf("unexpected\n");
- break;
- @}
-@end example
-
-@cindex aligned attribute
-@cindex packed attribute
-@cindex section attribute
-@cindex unused attribute
-@cindex cdecl attribute
-@cindex stdcall attribute
-@cindex regparm attribute
-@cindex dllexport attribute
-@cindex nodecorate attribute
-
-@item The keyword @code{__attribute__} is handled to specify variable or
-function attributes. The following attributes are supported:
- @itemize
-
- @item @code{aligned(n)}: align a variable or a structure field to n bytes
-(must be a power of two).
-
- @item @code{packed}: force alignment of a variable or a structure field to
- 1.
-
- @item @code{section(name)}: generate function or data in assembly section
-name (name is a string containing the section name) instead of the default
-section.
-
- @item @code{unused}: specify that the variable or the function is unused.
-
- @item @code{cdecl}: use standard C calling convention (default).
-
- @item @code{stdcall}: use Pascal-like calling convention.
-
- @item @code{regparm(n)}: use fast i386 calling convention. @var{n} must be
-between 1 and 3. The first @var{n} function parameters are respectively put in
-registers @code{%eax}, @code{%edx} and @code{%ecx}.
-
- @item @code{dllexport}: export function from dll/executable (win32 only)
-
- @item @code{nodecorate}: do not apply any decorations that would otherwise be applied when exporting function from dll/executable (win32 only)
-
- @end itemize
-
-Here are some examples:
-@example
- int a __attribute__ ((aligned(8), section(".mysection")));
-@end example
-
-@noindent
-align variable @code{a} to 8 bytes and put it in section @code{.mysection}.
-
-@example
- int my_add(int a, int b) __attribute__ ((section(".mycodesection")))
- @{
- return a + b;
- @}
-@end example
-
-@noindent
-generate function @code{my_add} in section @code{.mycodesection}.
-
-@item GNU style variadic macros:
-@example
- #define dprintf(fmt, args@dots{}) printf(fmt, ## args)
-
- dprintf("no arg\n");
- dprintf("one arg %d\n", 1);
-@end example
-
-@item @code{__FUNCTION__} is interpreted as C99 @code{__func__}
-(so it has not exactly the same semantics as string literal GNUC
-where it is a string literal).
-
-@item The @code{__alignof__} keyword can be used as @code{sizeof}
-to get the alignment of a type or an expression.
-
-@item The @code{typeof(x)} returns the type of @code{x}.
-@code{x} is an expression or a type.
-
-@item Computed gotos: @code{&&label} returns a pointer of type
-@code{void *} on the goto label @code{label}. @code{goto *expr} can be
-used to jump on the pointer resulting from @code{expr}.
-
-@item Inline assembly with asm instruction:
-@cindex inline assembly
-@cindex assembly, inline
-@cindex __asm__
-@example
-static inline void * my_memcpy(void * to, const void * from, size_t n)
-@{
-int d0, d1, d2;
-__asm__ __volatile__(
- "rep ; movsl\n\t"
- "testb $2,%b4\n\t"
- "je 1f\n\t"
- "movsw\n"
- "1:\ttestb $1,%b4\n\t"
- "je 2f\n\t"
- "movsb\n"
- "2:"
- : "=&c" (d0), "=&D" (d1), "=&S" (d2)
- :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
- : "memory");
-return (to);
-@}
-@end example
-
-@noindent
-@cindex gas
-TCC includes its own x86 inline assembler with a @code{gas}-like (GNU
-assembler) syntax. No intermediate files are generated. GCC 3.x named
-operands are supported.
-
-@item @code{__builtin_types_compatible_p()} and @code{__builtin_constant_p()}
-are supported.
-
-@item @code{#pragma pack} is supported for win32 compatibility.
-
-@end itemize
-
-@section TinyCC extensions
-
-@itemize
-
-@item @code{__TINYC__} is a predefined macro to indicate that you use TCC.
-
-@item @code{#!} at the start of a line is ignored to allow scripting.
-
-@item Binary digits can be entered (@code{0b101} instead of
-@code{5}).
-
-@end itemize
-
-@node asm
-@chapter TinyCC Assembler
-
-Since version 0.9.16, TinyCC integrates its own assembler. TinyCC
-assembler supports a gas-like syntax (GNU assembler). You can
-deactivate assembler support if you want a smaller TinyCC executable
-(the C compiler does not rely on the assembler).
-
-TinyCC Assembler is used to handle files with @file{.S} (C
-preprocessed assembler) and @file{.s} extensions. It is also used to
-handle the GNU inline assembler with the @code{asm} keyword.
-
-@section Syntax
-
-TinyCC Assembler supports most of the gas syntax. The tokens are the
-same as C.
-
-@itemize
-
-@item C and C++ comments are supported.
-
-@item Identifiers are the same as C, so you cannot use '.' or '$'.
-
-@item Only 32 bit integer numbers are supported.
-
-@end itemize
-
-@section Expressions
-
-@itemize
-
-@item Integers in decimal, octal and hexa are supported.
-
-@item Unary operators: +, -, ~.
-
-@item Binary operators in decreasing priority order:
-
-@enumerate
-@item *, /, %
-@item &, |, ^
-@item +, -
-@end enumerate
-
-@item A value is either an absolute number or a label plus an offset.
-All operators accept absolute values except '+' and '-'. '+' or '-' can be
-used to add an offset to a label. '-' supports two labels only if they
-are the same or if they are both defined and in the same section.
-
-@end itemize
-
-@section Labels
-
-@itemize
-
-@item All labels are considered as local, except undefined ones.
-
-@item Numeric labels can be used as local @code{gas}-like labels.
-They can be defined several times in the same source. Use 'b'
-(backward) or 'f' (forward) as suffix to reference them:
-
-@example
- 1:
- jmp 1b /* jump to '1' label before */
- jmp 1f /* jump to '1' label after */
- 1:
-@end example
-
-@end itemize
-
-@section Directives
-@cindex assembler directives
-@cindex directives, assembler
-@cindex align directive
-@cindex skip directive
-@cindex space directive
-@cindex byte directive
-@cindex word directive
-@cindex short directive
-@cindex int directive
-@cindex long directive
-@cindex quad directive
-@cindex globl directive
-@cindex global directive
-@cindex section directive
-@cindex text directive
-@cindex data directive
-@cindex bss directive
-@cindex fill directive
-@cindex org directive
-@cindex previous directive
-@cindex string directive
-@cindex asciz directive
-@cindex ascii directive
-
-All directives are preceded by a '.'. The following directives are
-supported:
-
-@itemize
-@item .align n[,value]
-@item .skip n[,value]
-@item .space n[,value]
-@item .byte value1[,...]
-@item .word value1[,...]
-@item .short value1[,...]
-@item .int value1[,...]
-@item .long value1[,...]
-@item .quad immediate_value1[,...]
-@item .globl symbol
-@item .global symbol
-@item .section section
-@item .text
-@item .data
-@item .bss
-@item .fill repeat[,size[,value]]
-@item .org n
-@item .previous
-@item .string string[,...]
-@item .asciz string[,...]
-@item .ascii string[,...]
-@end itemize
-
-@section X86 Assembler
-@cindex assembler
-
-All X86 opcodes are supported. Only ATT syntax is supported (source
-then destination operand order). If no size suffix is given, TinyCC
-tries to guess it from the operand sizes.
-
-Currently, MMX opcodes are supported but not SSE ones.
-
-@node linker
-@chapter TinyCC Linker
-@cindex linker
-
-@section ELF file generation
-@cindex ELF
-
-TCC can directly output relocatable ELF files (object files),
-executable ELF files and dynamic ELF libraries without relying on an
-external linker.
-
-Dynamic ELF libraries can be output but the C compiler does not generate
-position independent code (PIC). It means that the dynamic library
-code generated by TCC cannot be factorized among processes yet.
-
-TCC linker eliminates unreferenced object code in libraries. A single pass is
-done on the object and library list, so the order in which object files and
-libraries are specified is important (same constraint as GNU ld). No grouping
-options (@option{--start-group} and @option{--end-group}) are supported.
-
-@section ELF file loader
-
-TCC can load ELF object files, archives (.a files) and dynamic
-libraries (.so).
-
-@section PE-i386 file generation
-@cindex PE-i386
-
-TCC for Windows supports the native Win32 executable file format (PE-i386). It
-generates EXE files (console and gui) and DLL files.
-
-For usage on Windows, see also tcc-win32.txt.
-
-@section GNU Linker Scripts
-@cindex scripts, linker
-@cindex linker scripts
-@cindex GROUP, linker command
-@cindex FILE, linker command
-@cindex OUTPUT_FORMAT, linker command
-@cindex TARGET, linker command
-
-Because on many Linux systems some dynamic libraries (such as
-@file{/usr/lib/libc.so}) are in fact GNU ld link scripts (horrible!),
-the TCC linker also supports a subset of GNU ld scripts.
-
-The @code{GROUP} and @code{FILE} commands are supported. @code{OUTPUT_FORMAT}
-and @code{TARGET} are ignored.
-
-Example from @file{/usr/lib/libc.so}:
-@example
-/* GNU ld script
- Use the shared library, but some functions are only in
- the static library, so try that secondarily. */
-GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a )
-@end example
-
-@node Bounds
-@chapter TinyCC Memory and Bound checks
-@cindex bound checks
-@cindex memory checks
-
-This feature is activated with the @option{-b} option (@pxref{Invoke}).
-Here are some examples of caught errors:
-
-@table @asis
-
-@item Invalid range with standard string function:
-@example
-@{
- char tab[10];
- memset(tab, 0, 11);
-@}
-@end example
-
-@item Out of bounds-error in global or local arrays:
-@example
-@{
- int tab[10];
- for(i=0;i<11;i++) @{
- sum += tab[i];
- @}
-@}
-@end example
-
-@item Out of bounds-error in malloc'ed data:
-@example
-@{
- int *tab;
- tab = malloc(20 * sizeof(int));
- for(i=0;i<21;i++) @{
- sum += tab[i];
- @}
- free(tab);
-@}
-@end example
-
-@item Access of freed memory:
-@example
-@{
- int *tab;
- tab = malloc(20 * sizeof(int));
- free(tab);
- for(i=0;i<20;i++) @{
- sum += tab[i];
- @}
-@}
-@end example
-
-@item Double free:
-@example
-@{
- int *tab;
- tab = malloc(20 * sizeof(int));
- free(tab);
- free(tab);
-@}
-@end example
-@end table
-
-TCC defines @code{__BOUNDS_CHECKING_ON} if activated.
-
-There are five environment variables that can be used to control the behavior:
-@itemize
-@item TCC_BOUNDS_WARN_POINTER_ADD
-- Print warning when pointer add creates an illegal pointer.
-@item TCC_BOUNDS_PRINT_CALLS
-- Print bound checking calls. Can be used for debugging.
-@item TCC_BOUNDS_PRINT_HEAP
-- Print heap objects that are not freed at exit of program.
-@item TCC_BOUNDS_PRINT_STATISTIC
-- Print statistic information at exit of program.
-@item TCC_BOUNDS_NEVER_FATAL
-- Try to continue in case of a bound checking error.
-@end itemize
-
-Also, a function @code{__bounds_checking(x)} can be used to turn off/on bounds
-checking from usercode (see below).
-
-Notes:
-@itemize
-@item Only available on i386 (linux and windows), x86_64 (linux and windows),
-arm, arm64 and riscv64 for the moment.
-@item The generated code is slower and bigger.
-@item The bound checking code is not included in shared libraries. The main
-executable should always be compiled with the @option{-b}.
-@item Pointer size is @emph{unchanged} and code generated with bound checks is
-@emph{fully compatible} with unchecked code. When a pointer comes from
-unchecked code, it is assumed to be valid. Even very obscure C code with
-casts should work correctly.
-@item Signal handlers are not compatible with bounds checking. The
-bounds checking code disables checking in signal/sigaction handlers.
-The fork() function call in a multi threaded application is also a problem.
-The bound checking code fixes this for the child process.
-@item The reason that signals and fork have problems is that we use locking
-inside the bounds checking code.
-Inside a signal handler we can not use locks. Also in a multi threaded
-application after a fork the child process can have the lock set
-by another thread.
-@item The BOUNDS_CHECKING_OFF and BOUNDS_CHECKING_ON can also be used to
-disable bounds checking for some code.
-@item The __bounds_checking call adds a value to a thread local value.
-The value starts at 0. If the value is not 0 the code is not checked
-for bounds checking errors.
-@end itemize
-
-@example
-#if defined(__TINYC__) && __BOUNDS_CHECKING_ON
-extern void __bounds_checking (int x);
-# define BOUNDS_CHECKING_OFF __bounds_checking(1)
-# define BOUNDS_CHECKING_ON __bounds_checking(-1)
-#else
-# define BOUNDS_CHECKING_OFF
-# define BOUNDS_CHECKING_ON
-#endif
-@end example
-
-For more information about the ideas behind this method, see
-@url{http://www.doc.ic.ac.uk/~phjk/BoundsChecking.html}.
-
-@node Libtcc
-@chapter The @code{libtcc} library
-
-The @code{libtcc} library enables you to use TCC as a backend for
-dynamic code generation.
-
-Read the @file{libtcc.h} to have an overview of the API. Read
-@file{libtcc_test.c} to have a very simple example.
-
-The idea consists in giving a C string containing the program you want
-to compile directly to @code{libtcc}. Then you can access to any global
-symbol (function or variable) defined.
-
-@node devel
-@chapter Developer's guide
-
-This chapter gives some hints to understand how TCC works. You can skip
-it if you do not intend to modify the TCC code.
-
-@section File reading
-
-The @code{BufferedFile} structure contains the context needed to read a
-file, including the current line number. @code{tcc_open()} opens a new
-file and @code{tcc_close()} closes it. @code{inp()} returns the next
-character.
-
-@section Lexer
-
-@code{next()} reads the next token in the current
-file. @code{next_nomacro()} reads the next token without macro
-expansion.
-
-@code{tok} contains the current token (see @code{TOK_xxx})
-constants. Identifiers and keywords are also keywords. @code{tokc}
-contains additional infos about the token (for example a constant value
-if number or string token).
-
-@section Parser
-
-The parser is hardcoded (yacc is not necessary). It does only one pass,
-except:
-
-@itemize
-
-@item For initialized arrays with unknown size, a first pass
-is done to count the number of elements.
-
-@item For architectures where arguments are evaluated in
-reverse order, a first pass is done to reverse the argument order.
-
-@end itemize
-
-@section Types
-
-The types are stored in a single 'int' variable. It was chosen in the
-first stages of development when tcc was much simpler. Now, it may not
-be the best solution.
-
-@example
-#define VT_INT 0 /* integer type */
-#define VT_BYTE 1 /* signed byte type */
-#define VT_SHORT 2 /* short type */
-#define VT_VOID 3 /* void type */
-#define VT_PTR 4 /* pointer */
-#define VT_ENUM 5 /* enum definition */
-#define VT_FUNC 6 /* function type */
-#define VT_STRUCT 7 /* struct/union definition */
-#define VT_FLOAT 8 /* IEEE float */
-#define VT_DOUBLE 9 /* IEEE double */
-#define VT_LDOUBLE 10 /* IEEE long double */
-#define VT_BOOL 11 /* ISOC99 boolean type */
-#define VT_LLONG 12 /* 64 bit integer */
-#define VT_LONG 13 /* long integer (NEVER USED as type, only
- during parsing) */
-#define VT_BTYPE 0x000f /* mask for basic type */
-#define VT_UNSIGNED 0x0010 /* unsigned type */
-#define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
-#define VT_VLA 0x20000 /* VLA type (also has VT_PTR and VT_ARRAY) */
-#define VT_BITFIELD 0x0040 /* bitfield modifier */
-#define VT_CONSTANT 0x0800 /* const modifier */
-#define VT_VOLATILE 0x1000 /* volatile modifier */
-#define VT_DEFSIGN 0x2000 /* signed type */
-
-#define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
-@end example
-
-When a reference to another type is needed (for pointers, functions and
-structures), the @code{32 - VT_STRUCT_SHIFT} high order bits are used to
-store an identifier reference.
-
-The @code{VT_UNSIGNED} flag can be set for chars, shorts, ints and long
-longs.
-
-Arrays are considered as pointers @code{VT_PTR} with the flag
-@code{VT_ARRAY} set. Variable length arrays are considered as special
-arrays and have flag @code{VT_VLA} set instead of @code{VT_ARRAY}.
-
-The @code{VT_BITFIELD} flag can be set for chars, shorts, ints and long
-longs. If it is set, then the bitfield position is stored from bits
-VT_STRUCT_SHIFT to VT_STRUCT_SHIFT + 5 and the bit field size is stored
-from bits VT_STRUCT_SHIFT + 6 to VT_STRUCT_SHIFT + 11.
-
-@code{VT_LONG} is never used except during parsing.
-
-During parsing, the storage of an object is also stored in the type
-integer:
-
-@example
-#define VT_EXTERN 0x00000080 /* extern definition */
-#define VT_STATIC 0x00000100 /* static variable */
-#define VT_TYPEDEF 0x00000200 /* typedef definition */
-#define VT_INLINE 0x00000400 /* inline definition */
-#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */
-#define VT_EXPORT 0x00008000 /* win32: data exported from dll */
-#define VT_WEAK 0x00010000 /* win32: data exported from dll */
-@end example
-
-@section Symbols
-
-All symbols are stored in hashed symbol stacks. Each symbol stack
-contains @code{Sym} structures.
-
-@code{Sym.v} contains the symbol name (remember
-an identifier is also a token, so a string is never necessary to store
-it). @code{Sym.t} gives the type of the symbol. @code{Sym.r} is usually
-the register in which the corresponding variable is stored. @code{Sym.c} is
-usually a constant associated to the symbol like its address for normal
-symbols, and the number of entries for symbols representing arrays.
-Variable length array types use @code{Sym.c} as a location on the stack
-which holds the runtime sizeof for the type.
-
-Four main symbol stacks are defined:
-
-@table @code
-
-@item define_stack
-for the macros (@code{#define}s).
-
-@item global_stack
-for the global variables, functions and types.
-
-@item local_stack
-for the local variables, functions and types.
-
-@item global_label_stack
-for the local labels (for @code{goto}).
-
-@item label_stack
-for GCC block local labels (see the @code{__label__} keyword).
-
-@end table
-
-@code{sym_push()} is used to add a new symbol in the local symbol
-stack. If no local symbol stack is active, it is added in the global
-symbol stack.
-
-@code{sym_pop(st,b)} pops symbols from the symbol stack @var{st} until
-the symbol @var{b} is on the top of stack. If @var{b} is NULL, the stack
-is emptied.
-
-@code{sym_find(v)} return the symbol associated to the identifier
-@var{v}. The local stack is searched first from top to bottom, then the
-global stack.
-
-@section Sections
-
-The generated code and data are written in sections. The structure
-@code{Section} contains all the necessary information for a given
-section. @code{new_section()} creates a new section. ELF file semantics
-is assumed for each section.
-
-The following sections are predefined:
-
-@table @code
-
-@item text_section
-is the section containing the generated code. @var{ind} contains the
-current position in the code section.
-
-@item data_section
-contains initialized data
-
-@item bss_section
-contains uninitialized data
-
-@item bounds_section
-@itemx lbounds_section
-are used when bound checking is activated
-
-@item stab_section
-@itemx stabstr_section
-are used when debugging is active to store debug information
-
-@item symtab_section
-@itemx strtab_section
-contain the exported symbols (currently only used for debugging).
-
-@end table
-
-@section Code generation
-@cindex code generation
-
-@subsection Introduction
-
-The TCC code generator directly generates linked binary code in one
-pass. It is rather unusual these days (see gcc for example which
-generates text assembly), but it can be very fast and surprisingly
-little complicated.
-
-The TCC code generator is register based. Optimization is only done at
-the expression level. No intermediate representation of expression is
-kept except the current values stored in the @emph{value stack}.
-
-On x86, three temporary registers are used. When more registers are
-needed, one register is spilled into a new temporary variable on the stack.
-
-@subsection The value stack
-@cindex value stack, introduction
-
-When an expression is parsed, its value is pushed on the value stack
-(@var{vstack}). The top of the value stack is @var{vtop}. Each value
-stack entry is the structure @code{SValue}.
-
-@code{SValue.t} is the type. @code{SValue.r} indicates how the value is
-currently stored in the generated code. It is usually a CPU register
-index (@code{REG_xxx} constants), but additional values and flags are
-defined:
-
-@example
-#define VT_CONST 0x00f0
-#define VT_LLOCAL 0x00f1
-#define VT_LOCAL 0x00f2
-#define VT_CMP 0x00f3
-#define VT_JMP 0x00f4
-#define VT_JMPI 0x00f5
-#define VT_LVAL 0x0100
-#define VT_SYM 0x0200
-#define VT_MUSTCAST 0x0400
-#define VT_MUSTBOUND 0x0800
-#define VT_BOUNDED 0x8000
-#define VT_LVAL_BYTE 0x1000
-#define VT_LVAL_SHORT 0x2000
-#define VT_LVAL_UNSIGNED 0x4000
-#define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
-@end example
-
-@table @code
-
-@item VT_CONST
-indicates that the value is a constant. It is stored in the union
-@code{SValue.c}, depending on its type.
-
-@item VT_LOCAL
-indicates a local variable pointer at offset @code{SValue.c.i} in the
-stack.
-
-@item VT_CMP
-indicates that the value is actually stored in the CPU flags (i.e. the
-value is the consequence of a test). The value is either 0 or 1. The
-actual CPU flags used is indicated in @code{SValue.c.i}.
-
-If any code is generated which destroys the CPU flags, this value MUST be
-put in a normal register.
-
-@item VT_JMP
-@itemx VT_JMPI
-indicates that the value is the consequence of a conditional jump. For VT_JMP,
-it is 1 if the jump is taken, 0 otherwise. For VT_JMPI it is inverted.
-
-These values are used to compile the @code{||} and @code{&&} logical
-operators.
-
-If any code is generated, this value MUST be put in a normal
-register. Otherwise, the generated code won't be executed if the jump is
-taken.
-
-@item VT_LVAL
-is a flag indicating that the value is actually an lvalue (left value of
-an assignment). It means that the value stored is actually a pointer to
-the wanted value.
-
-Understanding the use @code{VT_LVAL} is very important if you want to
-understand how TCC works.
-
-@item VT_LVAL_BYTE
-@itemx VT_LVAL_SHORT
-@itemx VT_LVAL_UNSIGNED
-if the lvalue has an integer type, then these flags give its real
-type. The type alone is not enough in case of cast optimisations.
-
-@item VT_LLOCAL
-is a saved lvalue on the stack. @code{VT_LVAL} must also be set with
-@code{VT_LLOCAL}. @code{VT_LLOCAL} can arise when a @code{VT_LVAL} in
-a register has to be saved to the stack, or it can come from an
-architecture-specific calling convention.
-
-@item VT_MUSTCAST
-indicates that a cast to the value type must be performed if the value
-is used (lazy casting).
-
-@item VT_SYM
-indicates that the symbol @code{SValue.sym} must be added to the constant.
-
-@item VT_MUSTBOUND
-@itemx VT_BOUNDED
-are only used for optional bound checking.
-
-@end table
-
-@subsection Manipulating the value stack
-@cindex value stack
-
-@code{vsetc()} and @code{vset()} pushes a new value on the value
-stack. If the previous @var{vtop} was stored in a very unsafe place(for
-example in the CPU flags), then some code is generated to put the
-previous @var{vtop} in a safe storage.
-
-@code{vpop()} pops @var{vtop}. In some cases, it also generates cleanup
-code (for example if stacked floating point registers are used as on
-x86).
-
-The @code{gv(rc)} function generates code to evaluate @var{vtop} (the
-top value of the stack) into registers. @var{rc} selects in which
-register class the value should be put. @code{gv()} is the @emph{most
-important function} of the code generator.
-
-@code{gv2()} is the same as @code{gv()} but for the top two stack
-entries.
-
-@subsection CPU dependent code generation
-@cindex CPU dependent
-See the @file{i386-gen.c} file to have an example.
-
-@table @code
-
-@item load()
-must generate the code needed to load a stack value into a register.
-
-@item store()
-must generate the code needed to store a register into a stack value
-lvalue.
-
-@item gfunc_start()
-@itemx gfunc_param()
-@itemx gfunc_call()
-should generate a function call
-
-@item gfunc_prolog()
-@itemx gfunc_epilog()
-should generate a function prolog/epilog.
-
-@item gen_opi(op)
-must generate the binary integer operation @var{op} on the two top
-entries of the stack which are guaranteed to contain integer types.
-
-The result value should be put on the stack.
-
-@item gen_opf(op)
-same as @code{gen_opi()} for floating point operations. The two top
-entries of the stack are guaranteed to contain floating point values of
-same types.
-
-@item gen_cvt_itof()
-integer to floating point conversion.
-
-@item gen_cvt_ftoi()
-floating point to integer conversion.
-
-@item gen_cvt_ftof()
-floating point to floating point of different size conversion.
-
-@end table
-
-@section Optimizations done
-@cindex optimizations
-@cindex constant propagation
-@cindex strength reduction
-@cindex comparison operators
-@cindex caching processor flags
-@cindex flags, caching
-@cindex jump optimization
-Constant propagation is done for all operations. Multiplications and
-divisions are optimized to shifts when appropriate. Comparison
-operators are optimized by maintaining a special cache for the
-processor flags. &&, || and ! are optimized by maintaining a special
-'jump target' value. No other jump optimization is currently performed
-because it would require to store the code in a more abstract fashion.
-
-@unnumbered Concept Index
-@printindex cp
-
-@bye
-
-@c Local variables:
-@c fill-column: 78
-@c texinfo-column-for-description: 32
-@c End:
diff --git a/tinycc/tcc.c b/tinycc/tcc.c
deleted file mode 100644
index 0c6f6ac..0000000
--- a/tinycc/tcc.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * TCC - Tiny C Compiler
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "tcc.h"
-#if ONE_SOURCE
-# include "libtcc.c"
-#endif
-#include "tcctools.c"
-
-static const char help[] =
- "Tiny C Compiler "TCC_VERSION" - Copyright (C) 2001-2006 Fabrice Bellard\n"
- "Usage: tcc [options...] [-o outfile] [-c] infile(s)...\n"
- " tcc [options...] -run infile (or --) [arguments...]\n"
- "General options:\n"
- " -c compile only - generate an object file\n"
- " -o outfile set output filename\n"
- " -run run compiled source\n"
- " -fflag set or reset (with 'no-' prefix) 'flag' (see tcc -hh)\n"
- " -std=c99 Conform to the ISO 1999 C standard (default).\n"
- " -std=c11 Conform to the ISO 2011 C standard.\n"
- " -Wwarning set or reset (with 'no-' prefix) 'warning' (see tcc -hh)\n"
- " -w disable all warnings\n"
- " -v --version show version\n"
- " -vv show search paths or loaded files\n"
- " -h -hh show this, show more help\n"
- " -bench show compilation statistics\n"
- " - use stdin pipe as infile\n"
- " @listfile read arguments from listfile\n"
- "Preprocessor options:\n"
- " -Idir add include path 'dir'\n"
- " -Dsym[=val] define 'sym' with value 'val'\n"
- " -Usym undefine 'sym'\n"
- " -E preprocess only\n"
- " -C keep comments (not yet implemented)\n"
- "Linker options:\n"
- " -Ldir add library path 'dir'\n"
- " -llib link with dynamic or static library 'lib'\n"
- " -r generate (relocatable) object file\n"
- " -shared generate a shared library/dll\n"
- " -rdynamic export all global symbols to dynamic linker\n"
- " -soname set name for shared library to be used at runtime\n"
- " -Wl,-opt[=val] set linker option (see tcc -hh)\n"
- "Debugger options:\n"
- " -g generate stab runtime debug info\n"
- " -gdwarf[-x] generate dwarf runtime debug info\n"
-#ifdef CONFIG_TCC_BCHECK
- " -b compile with built-in memory and bounds checker (implies -g)\n"
-#endif
-#ifdef CONFIG_TCC_BACKTRACE
- " -bt[N] link with backtrace (stack dump) support [show max N callers]\n"
-#endif
- "Misc. options:\n"
- " -x[c|a|b|n] specify type of the next infile (C,ASM,BIN,NONE)\n"
- " -nostdinc do not use standard system include paths\n"
- " -nostdlib do not link with standard crt and libraries\n"
- " -Bdir set tcc's private include/library dir\n"
- " -M[M]D generate make dependency file [ignore system files]\n"
- " -M[M] as above but no other output\n"
- " -MF file specify dependency file name\n"
-#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
- " -m32/64 defer to i386/x86_64 cross compiler\n"
-#endif
- "Tools:\n"
- " create library : tcc -ar [crstvx] lib [files]\n"
-#ifdef TCC_TARGET_PE
- " create def file : tcc -impdef lib.dll [-v] [-o lib.def]\n"
-#endif
- ;
-
-static const char help2[] =
- "Tiny C Compiler "TCC_VERSION" - More Options\n"
- "Special options:\n"
- " -P -P1 with -E: no/alternative #line output\n"
- " -dD -dM with -E: output #define directives\n"
- " -pthread same as -D_REENTRANT and -lpthread\n"
- " -On same as -D__OPTIMIZE__ for n > 0\n"
- " -Wp,-opt same as -opt\n"
- " -include file include 'file' above each input file\n"
- " -isystem dir add 'dir' to system include path\n"
- " -static link to static libraries (not recommended)\n"
- " -dumpversion print version\n"
- " -print-search-dirs print search paths\n"
- " -dt with -run/-E: auto-define 'test_...' macros\n"
- "Ignored options:\n"
- " -arch -C --param -pedantic -pipe -s -traditional\n"
- "-W[no-]... warnings:\n"
- " all turn on some (*) warnings\n"
- " error[=warning] stop after warning (any or specified)\n"
- " write-strings strings are const\n"
- " unsupported warn about ignored options, pragmas, etc.\n"
- " implicit-function-declaration warn for missing prototype (*)\n"
- " discarded-qualifiers warn when const is dropped (*)\n"
- "-f[no-]... flags:\n"
- " unsigned-char default char is unsigned\n"
- " signed-char default char is signed\n"
- " common use common section instead of bss\n"
- " leading-underscore decorate extern symbols\n"
- " ms-extensions allow anonymous struct in struct\n"
- " dollars-in-identifiers allow '$' in C symbols\n"
- " test-coverage create code coverage code\n"
- "-m... target specific options:\n"
- " ms-bitfields use MSVC bitfield layout\n"
-#ifdef TCC_TARGET_ARM
- " float-abi hard/softfp on arm\n"
-#endif
-#ifdef TCC_TARGET_X86_64
- " no-sse disable floats on x86_64\n"
-#endif
- "-Wl,... linker options:\n"
- " -nostdlib do not link with standard crt/libs\n"
- " -[no-]whole-archive load lib(s) fully/only as needed\n"
- " -export-all-symbols same as -rdynamic\n"
- " -export-dynamic same as -rdynamic\n"
- " -image-base= -Ttext= set base address of executable\n"
- " -section-alignment= set section alignment in executable\n"
-#ifdef TCC_TARGET_PE
- " -file-alignment= set PE file alignment\n"
- " -stack= set PE stack reserve\n"
- " -large-address-aware set related PE option\n"
- " -subsystem=[console/windows] set PE subsystem\n"
- " -oformat=[pe-* binary] set executable output format\n"
- "Predefined macros:\n"
- " tcc -E -dM - < nul\n"
-#else
- " -rpath= set dynamic library search path\n"
- " -enable-new-dtags set DT_RUNPATH instead of DT_RPATH\n"
- " -soname= set DT_SONAME elf tag\n"
-#if defined(TCC_TARGET_MACHO)
- " -install_name= set DT_SONAME elf tag (soname macOS alias)\n"
-#endif
- " -Bsymbolic set DT_SYMBOLIC elf tag\n"
- " -oformat=[elf32/64-* binary] set executable output format\n"
- " -init= -fini= -Map= -as-needed -O (ignored)\n"
- "Predefined macros:\n"
- " tcc -E -dM - < /dev/null\n"
-#endif
- "See also the manual for more details.\n"
- ;
-
-static const char version[] =
- "tcc version "TCC_VERSION
-#ifdef TCC_GITHASH
- " "TCC_GITHASH
-#endif
- " ("
-#ifdef TCC_TARGET_I386
- "i386"
-#elif defined TCC_TARGET_X86_64
- "x86_64"
-#elif defined TCC_TARGET_C67
- "C67"
-#elif defined TCC_TARGET_ARM
- "ARM"
-# ifdef TCC_ARM_EABI
- " eabi"
-# ifdef TCC_ARM_HARDFLOAT
- "hf"
-# endif
-# endif
-#elif defined TCC_TARGET_ARM64
- "AArch64"
-#elif defined TCC_TARGET_RISCV64
- "riscv64"
-#endif
-#ifdef TCC_TARGET_PE
- " Windows"
-#elif defined(TCC_TARGET_MACHO)
- " Darwin"
-#elif TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
- " FreeBSD"
-#elif TARGETOS_OpenBSD
- " OpenBSD"
-#elif TARGETOS_NetBSD
- " NetBSD"
-#else
- " Linux"
-#endif
- ")\n"
- ;
-
-static void print_dirs(const char *msg, char **paths, int nb_paths)
-{
- int i;
- printf("%s:\n%s", msg, nb_paths ? "" : " -\n");
- for(i = 0; i < nb_paths; i++)
- printf(" %s\n", paths[i]);
-}
-
-static void print_search_dirs(TCCState *s)
-{
- printf("install: %s\n", s->tcc_lib_path);
- /* print_dirs("programs", NULL, 0); */
- print_dirs("include", s->sysinclude_paths, s->nb_sysinclude_paths);
- print_dirs("libraries", s->library_paths, s->nb_library_paths);
- printf("libtcc1:\n %s/%s\n", s->library_paths[0], CONFIG_TCC_CROSSPREFIX TCC_LIBTCC1);
-#if !defined TCC_TARGET_PE && !defined TCC_TARGET_MACHO
- print_dirs("crt", s->crt_paths, s->nb_crt_paths);
- printf("elfinterp:\n %s\n", DEFAULT_ELFINTERP(s));
-#endif
-}
-
-static void set_environment(TCCState *s)
-{
- char * path;
-
- path = getenv("C_INCLUDE_PATH");
- if(path != NULL) {
- tcc_add_sysinclude_path(s, path);
- }
- path = getenv("CPATH");
- if(path != NULL) {
- tcc_add_include_path(s, path);
- }
- path = getenv("LIBRARY_PATH");
- if(path != NULL) {
- tcc_add_library_path(s, path);
- }
-}
-
-static char *default_outputfile(TCCState *s, const char *first_file)
-{
- char buf[1024];
- char *ext;
- const char *name = "a";
-
- if (first_file && strcmp(first_file, "-"))
- name = tcc_basename(first_file);
- snprintf(buf, sizeof(buf), "%s", name);
- ext = tcc_fileextension(buf);
-#ifdef TCC_TARGET_PE
- if (s->output_type == TCC_OUTPUT_DLL)
- strcpy(ext, ".dll");
- else
- if (s->output_type == TCC_OUTPUT_EXE)
- strcpy(ext, ".exe");
- else
-#endif
- if ((s->just_deps || s->output_type == TCC_OUTPUT_OBJ) && !s->option_r && *ext)
- strcpy(ext, ".o");
- else
- strcpy(buf, "a.out");
- return tcc_strdup(buf);
-}
-
-static unsigned getclock_ms(void)
-{
-#ifdef _WIN32
- return GetTickCount();
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec*1000 + (tv.tv_usec+500)/1000;
-#endif
-}
-
-int main(int argc0, char **argv0)
-{
- TCCState *s, *s1;
- int ret, opt, n = 0, t = 0, done;
- unsigned start_time = 0, end_time = 0;
- const char *first_file;
- int argc; char **argv;
- FILE *ppfp = stdout;
-
-redo:
- argc = argc0, argv = argv0;
- s = s1 = tcc_new();
-#ifdef CONFIG_TCC_SWITCHES /* predefined options */
- tcc_set_options(s, CONFIG_TCC_SWITCHES);
-#endif
- opt = tcc_parse_args(s, &argc, &argv, 1);
- if (opt < 0)
- return 1;
-
- if (n == 0) {
- if (opt == OPT_HELP) {
- fputs(help, stdout);
- if (!s->verbose)
- return 0;
- ++opt;
- }
- if (opt == OPT_HELP2) {
- fputs(help2, stdout);
- return 0;
- }
- if (opt == OPT_M32 || opt == OPT_M64)
- return tcc_tool_cross(s, argv, opt);
- if (s->verbose)
- printf(version);
- if (opt == OPT_AR)
- return tcc_tool_ar(s, argc, argv);
-#ifdef TCC_TARGET_PE
- if (opt == OPT_IMPDEF)
- return tcc_tool_impdef(s, argc, argv);
-#endif
- if (opt == OPT_V)
- return 0;
- if (opt == OPT_PRINT_DIRS) {
- /* initialize search dirs */
- set_environment(s);
- tcc_set_output_type(s, TCC_OUTPUT_MEMORY);
- print_search_dirs(s);
- return 0;
- }
-
- if (s->nb_files == 0) {
- tcc_error_noabort("no input files");
- } else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
- if (s->outfile && 0!=strcmp("-",s->outfile)) {
- ppfp = fopen(s->outfile, "w");
- if (!ppfp)
- tcc_error_noabort("could not write '%s'", s->outfile);
- }
- } else if (s->output_type == TCC_OUTPUT_OBJ && !s->option_r) {
- if (s->nb_libraries)
- tcc_error_noabort("cannot specify libraries with -c");
- else if (s->nb_files > 1 && s->outfile)
- tcc_error_noabort("cannot specify output file with -c many files");
- }
- if (s->nb_errors)
- return 1;
- if (s->do_bench)
- start_time = getclock_ms();
- }
-
- set_environment(s);
- if (s->output_type == 0)
- s->output_type = TCC_OUTPUT_EXE;
- tcc_set_output_type(s, s->output_type);
- s->ppfp = ppfp;
-
- if ((s->output_type == TCC_OUTPUT_MEMORY
- || s->output_type == TCC_OUTPUT_PREPROCESS)
- && (s->dflag & 16)) { /* -dt option */
- if (t)
- s->dflag |= 32;
- s->run_test = ++t;
- if (n)
- --n;
- }
-
- /* compile or add each files or library */
- first_file = NULL, ret = 0;
- do {
- struct filespec *f = s->files[n];
- s->filetype = f->type;
- if (f->type & AFF_TYPE_LIB) {
- if (tcc_add_library_err(s, f->name) < 0)
- ret = 1;
- } else {
- if (1 == s->verbose)
- printf("-> %s\n", f->name);
- if (!first_file)
- first_file = f->name;
- if (tcc_add_file(s, f->name) < 0)
- ret = 1;
- }
- done = ret || ++n >= s->nb_files;
- } while (!done && (s->output_type != TCC_OUTPUT_OBJ || s->option_r));
-
- if (s->do_bench)
- end_time = getclock_ms();
-
- if (s->run_test) {
- t = 0;
- } else if (s->output_type == TCC_OUTPUT_PREPROCESS) {
- ;
- } else if (0 == ret) {
- if (s->output_type == TCC_OUTPUT_MEMORY) {
-#ifdef TCC_IS_NATIVE
- ret = tcc_run(s, argc, argv);
-#endif
- } else {
- if (!s->outfile)
- s->outfile = default_outputfile(s, first_file);
- if (!s->just_deps && tcc_output_file(s, s->outfile))
- ret = 1;
- else if (s->gen_deps)
- ret = gen_makedeps(s, s->outfile, s->deps_outfile);
- }
- }
-
- if (done && 0 == t && 0 == ret && s->do_bench)
- tcc_print_stats(s, end_time - start_time);
-
- tcc_delete(s);
- if (!done)
- goto redo; /* compile more files with -c */
- if (t)
- goto redo; /* run more tests with -dt -run */
-
- if (ppfp && ppfp != stdout)
- fclose(ppfp);
- return ret;
-}
diff --git a/tinycc/tcc.h b/tinycc/tcc.h
deleted file mode 100644
index a4abccf..0000000
--- a/tinycc/tcc.h
+++ /dev/null
@@ -1,1937 +0,0 @@
-/*
- * TCC - Tiny C Compiler
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _TCC_H
-#define _TCC_H
-
-#define _GNU_SOURCE
-#define _DARWIN_C_SOURCE
-#include "config.h"
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-/* gnu headers use to #define __attribute__ to empty for non-gcc compilers */
-#ifdef __TINYC__
-# undef __attribute__
-#endif
-#include <string.h>
-#include <errno.h>
-#include <math.h>
-#include <fcntl.h>
-#include <setjmp.h>
-#include <time.h>
-#include <sys/stat.h>
-
-#ifndef _WIN32
-# include <unistd.h>
-# include <sys/time.h>
-# ifndef CONFIG_TCC_STATIC
-# include <dlfcn.h>
-# endif
-/* XXX: need to define this to use them in non ISOC99 context */
-extern float strtof (const char *__nptr, char **__endptr);
-extern long double strtold (const char *__nptr, char **__endptr);
-#endif
-
-#ifdef _WIN32
-# define WIN32_LEAN_AND_MEAN 1
-# include <windows.h>
-# include <io.h> /* open, close etc. */
-# include <direct.h> /* getcwd */
-# include <malloc.h> /* alloca */
-# ifdef __GNUC__
-# include <stdint.h>
-# endif
-# define inline __inline
-# define snprintf _snprintf
-# define vsnprintf _vsnprintf
-# ifndef __GNUC__
-# define strtold (long double)strtod
-# define strtof (float)strtod
-# define strtoll _strtoi64
-# define strtoull _strtoui64
-# endif
-# ifdef LIBTCC_AS_DLL
-# define LIBTCCAPI __declspec(dllexport)
-# define PUB_FUNC LIBTCCAPI
-# endif
-# ifdef _MSC_VER
-# pragma warning (disable : 4244) // conversion from 'uint64_t' to 'int', possible loss of data
-# pragma warning (disable : 4267) // conversion from 'size_t' to 'int', possible loss of data
-# pragma warning (disable : 4996) // The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name
-# pragma warning (disable : 4018) // signed/unsigned mismatch
-# pragma warning (disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
-# define ssize_t intptr_t
-# ifdef _X86_
-# define __i386__ 1
-# endif
-# ifdef _AMD64_
-# define __x86_64__ 1
-# endif
-# endif
-# ifndef va_copy
-# define va_copy(a,b) a = b
-# endif
-# undef CONFIG_TCC_STATIC
-#endif
-
-#ifndef PAGESIZE
-# ifdef _SC_PAGESIZE
-# define PAGESIZE sysconf(_SC_PAGESIZE)
-# else
-# define PAGESIZE 4096
-# endif
-#endif
-
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-#ifndef offsetof
-#define offsetof(type, field) ((size_t) &((type *)0)->field)
-#endif
-
-#ifndef countof
-#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
-#endif
-
-#ifdef _MSC_VER
-# define NORETURN __declspec(noreturn)
-# define ALIGNED(x) __declspec(align(x))
-# define PRINTF_LIKE(x,y)
-#else
-# define NORETURN __attribute__((noreturn))
-# define ALIGNED(x) __attribute__((aligned(x)))
-# define PRINTF_LIKE(x,y) __attribute__ ((format (printf, (x), (y))))
-#endif
-
-#ifdef _WIN32
-# define IS_DIRSEP(c) (c == '/' || c == '\\')
-# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))
-# define PATHCMP stricmp
-# define PATHSEP ";"
-#else
-# define IS_DIRSEP(c) (c == '/')
-# define IS_ABSPATH(p) IS_DIRSEP(p[0])
-# define PATHCMP strcmp
-# define PATHSEP ":"
-#endif
-
-/* -------------------------------------------- */
-
-/* parser debug */
-/* #define PARSE_DEBUG */
-/* preprocessor debug */
-/* #define PP_DEBUG */
-/* include file debug */
-/* #define INC_DEBUG */
-/* memory leak debug (only for single threaded usage) */
-/* #define MEM_DEBUG */
-/* assembler debug */
-/* #define ASM_DEBUG */
-
-/* target selection */
-/* #define TCC_TARGET_I386 *//* i386 code generator */
-/* #define TCC_TARGET_X86_64 *//* x86-64 code generator */
-/* #define TCC_TARGET_ARM *//* ARMv4 code generator */
-/* #define TCC_TARGET_ARM64 *//* ARMv8 code generator */
-/* #define TCC_TARGET_C67 *//* TMS320C67xx code generator */
-/* #define TCC_TARGET_RISCV64 *//* risc-v code generator */
-
-/* default target is I386 */
-#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
- !defined(TCC_TARGET_ARM64) && !defined(TCC_TARGET_C67) && \
- !defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_RISCV64)
-# if defined __x86_64__
-# define TCC_TARGET_X86_64
-# elif defined __arm__
-# define TCC_TARGET_ARM
-# define TCC_ARM_EABI
-# define TCC_ARM_VFP
-# define TCC_ARM_HARDFLOAT
-# elif defined __aarch64__
-# define TCC_TARGET_ARM64
-# elif defined __riscv
-# define TCC_TARGET_RISCV64
-# else
-# define TCC_TARGET_I386
-# endif
-# ifdef _WIN32
-# define TCC_TARGET_PE 1
-# endif
-# ifdef __APPLE__
-# define TCC_TARGET_MACHO 1
-# endif
-#endif
-
-/* only native compiler supports -run */
-#if defined _WIN32 == defined TCC_TARGET_PE \
- && defined __APPLE__ == defined TCC_TARGET_MACHO
-# if defined __i386__ && defined TCC_TARGET_I386
-# define TCC_IS_NATIVE
-# elif defined __x86_64__ && defined TCC_TARGET_X86_64
-# define TCC_IS_NATIVE
-# elif defined __arm__ && defined TCC_TARGET_ARM
-# define TCC_IS_NATIVE
-# elif defined __aarch64__ && defined TCC_TARGET_ARM64
-# define TCC_IS_NATIVE
-# elif defined __riscv && defined __LP64__ && defined TCC_TARGET_RISCV64
-# define TCC_IS_NATIVE
-# endif
-#endif
-
-#if defined CONFIG_TCC_BACKTRACE && CONFIG_TCC_BACKTRACE==0
-# undef CONFIG_TCC_BACKTRACE
-#else
-# define CONFIG_TCC_BACKTRACE 1 /* enable builtin stack backtraces */
-#endif
-
-#if defined CONFIG_TCC_BCHECK && CONFIG_TCC_BCHECK==0
-# undef CONFIG_TCC_BCHECK
-#else
-# define CONFIG_TCC_BCHECK 1 /* enable bound checking code */
-#endif
-
-#if defined CONFIG_NEW_MACHO && CONFIG_NEW_MACHO==0
-# undef CONFIG_NEW_MACHO
-#else
-# define CONFIG_NEW_MACHO 1 /* enable new macho code */
-#endif
-
-#if defined TARGETOS_OpenBSD \
- || defined TARGETOS_FreeBSD \
- || defined TARGETOS_NetBSD \
- || defined TARGETOS_FreeBSD_kernel
-# define TARGETOS_BSD 1
-#elif !(defined TCC_TARGET_PE || defined TCC_TARGET_MACHO)
-# define TARGETOS_Linux 1
-#endif
-
-#if defined TCC_TARGET_PE || defined TCC_TARGET_MACHO
-# define ELF_OBJ_ONLY /* create elf .o but native executables */
-#endif
-
-/* No ten-byte long doubles on window and macos except in
- cross-compilers made by a mingw-GCC */
-#if defined TCC_TARGET_PE \
- || (defined TCC_TARGET_MACHO && defined TCC_TARGET_ARM64) \
- || (defined _WIN32 && !defined __GNUC__)
-# define TCC_USING_DOUBLE_FOR_LDOUBLE 1
-#endif
-
-#ifdef CONFIG_TCC_PIE
-# define CONFIG_TCC_PIC 1
-#endif
-
-/* ------------ path configuration ------------ */
-
-#ifndef CONFIG_SYSROOT
-# define CONFIG_SYSROOT ""
-#endif
-#if !defined CONFIG_TCCDIR && !defined _WIN32
-# define CONFIG_TCCDIR "/usr/local/lib/tcc"
-#endif
-#ifndef CONFIG_LDDIR
-# define CONFIG_LDDIR "lib"
-#endif
-#ifdef CONFIG_TRIPLET
-# define USE_TRIPLET(s) s "/" CONFIG_TRIPLET
-# define ALSO_TRIPLET(s) USE_TRIPLET(s) ":" s
-#else
-# define USE_TRIPLET(s) s
-# define ALSO_TRIPLET(s) s
-#endif
-
-/* path to find crt1.o, crti.o and crtn.o */
-#ifndef CONFIG_TCC_CRTPREFIX
-# define CONFIG_TCC_CRTPREFIX USE_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR)
-#endif
-
-#ifndef CONFIG_USR_INCLUDE
-# define CONFIG_USR_INCLUDE "/usr/include"
-#endif
-
-/* Below: {B} is substituted by CONFIG_TCCDIR (rsp. -B option) */
-
-/* system include paths */
-#ifndef CONFIG_TCC_SYSINCLUDEPATHS
-# if defined TCC_TARGET_PE || defined _WIN32
-# define CONFIG_TCC_SYSINCLUDEPATHS "{B}/include"PATHSEP"{B}/include/winapi"
-# else
-# define CONFIG_TCC_SYSINCLUDEPATHS \
- "{B}/include" \
- ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/include") \
- ":" ALSO_TRIPLET(CONFIG_SYSROOT CONFIG_USR_INCLUDE)
-# endif
-#endif
-
-/* library search paths */
-#ifndef CONFIG_TCC_LIBPATHS
-# ifdef TCC_TARGET_PE
-# define CONFIG_TCC_LIBPATHS "{B}/lib"
-# else
-# define CONFIG_TCC_LIBPATHS \
- "{B}" \
- ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/" CONFIG_LDDIR) \
- ":" ALSO_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) \
- ":" ALSO_TRIPLET(CONFIG_SYSROOT "/usr/local/" CONFIG_LDDIR)
-# endif
-#endif
-
-/* name of ELF interpreter */
-#ifndef CONFIG_TCC_ELFINTERP
-# if TARGETOS_FreeBSD
-# define CONFIG_TCC_ELFINTERP "/libexec/ld-elf.so.1"
-# elif TARGETOS_FreeBSD_kernel
-# if defined(TCC_TARGET_X86_64)
-# define CONFIG_TCC_ELFINTERP "/lib/ld-kfreebsd-x86-64.so.1"
-# else
-# define CONFIG_TCC_ELFINTERP "/lib/ld.so.1"
-# endif
-# elif TARGETOS_DragonFly
-# define CONFIG_TCC_ELFINTERP "/usr/libexec/ld-elf.so.2"
-# elif TARGETOS_NetBSD
-# define CONFIG_TCC_ELFINTERP "/usr/libexec/ld.elf_so"
-# elif TARGETOS_OpenBSD
-# define CONFIG_TCC_ELFINTERP "/usr/libexec/ld.so"
-# elif defined __GNU__
-# define CONFIG_TCC_ELFINTERP "/lib/ld.so"
-# elif defined(TCC_TARGET_PE)
-# define CONFIG_TCC_ELFINTERP "-"
-# elif defined(TCC_UCLIBC)
-# define CONFIG_TCC_ELFINTERP "/lib/ld-uClibc.so.0" /* is there a uClibc for x86_64 ? */
-# elif defined TCC_TARGET_ARM64
-# if defined(TCC_MUSL)
-# define CONFIG_TCC_ELFINTERP "/lib/ld-musl-aarch64.so.1"
-# else
-# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-aarch64.so.1"
-# endif
-# elif defined(TCC_TARGET_X86_64)
-# if defined(TCC_MUSL)
-# define CONFIG_TCC_ELFINTERP "/lib/ld-musl-x86_64.so.1"
-# else
-# define CONFIG_TCC_ELFINTERP "/lib64/ld-linux-x86-64.so.2"
-# endif
-# elif defined(TCC_TARGET_RISCV64)
-# define CONFIG_TCC_ELFINTERP "/lib/ld-linux-riscv64-lp64d.so.1"
-# elif !defined(TCC_ARM_EABI)
-# if defined(TCC_MUSL)
-# if defined(TCC_TARGET_I386)
-# define CONFIG_TCC_ELFINTERP "/lib/ld-musl-i386.so.1"
-# else
-# define CONFIG_TCC_ELFINTERP "/lib/ld-musl-arm.so.1"
-# endif
-# else
-# define CONFIG_TCC_ELFINTERP "/lib/ld-linux.so.2"
-# endif
-# endif
-#endif
-
-/* var elf_interp dans *-gen.c */
-#ifdef CONFIG_TCC_ELFINTERP
-# define DEFAULT_ELFINTERP(s) CONFIG_TCC_ELFINTERP
-#else
-# define DEFAULT_ELFINTERP(s) default_elfinterp(s)
-#endif
-
-/* (target specific) libtcc1.a */
-#ifndef TCC_LIBTCC1
-# define TCC_LIBTCC1 "\0"
-#endif
-
-#ifndef CONFIG_TCC_CROSSPREFIX
-# define CONFIG_TCC_CROSSPREFIX ""
-#endif
-
-/* library to use with CONFIG_USE_LIBGCC instead of libtcc1.a */
-#if defined CONFIG_USE_LIBGCC && !defined TCC_LIBGCC
-#define TCC_LIBGCC USE_TRIPLET(CONFIG_SYSROOT "/" CONFIG_LDDIR) "/libgcc_s.so.1"
-#endif
-
-/* -------------------------------------------- */
-
-#include "libtcc.h"
-#include "elf.h"
-#include "stab.h"
-#include "dwarf.h"
-
-/* -------------------------------------------- */
-
-#ifndef PUB_FUNC /* functions used by tcc.c but not in libtcc.h */
-# define PUB_FUNC
-#endif
-
-#ifndef ONE_SOURCE
-# define ONE_SOURCE 1
-#endif
-
-/* support using libtcc from threads */
-#ifndef CONFIG_TCC_SEMLOCK
-# define CONFIG_TCC_SEMLOCK 1
-#endif
-
-#if ONE_SOURCE
-#define ST_INLN static inline
-#define ST_FUNC static
-#define ST_DATA static
-#else
-#define ST_INLN
-#define ST_FUNC
-#define ST_DATA extern
-#endif
-
-#ifdef TCC_PROFILE /* profile all functions */
-# define static
-#endif
-
-/* -------------------------------------------- */
-/* include the target specific definitions */
-
-#define TARGET_DEFS_ONLY
-#ifdef TCC_TARGET_I386
-# include "i386-gen.c"
-# include "i386-link.c"
-#elif defined TCC_TARGET_X86_64
-# include "x86_64-gen.c"
-# include "x86_64-link.c"
-#elif defined TCC_TARGET_ARM
-# include "arm-gen.c"
-# include "arm-link.c"
-# include "arm-asm.c"
-#elif defined TCC_TARGET_ARM64
-# include "arm64-gen.c"
-# include "arm64-link.c"
-# include "arm-asm.c"
-#elif defined TCC_TARGET_C67
-# define TCC_TARGET_COFF
-# include "coff.h"
-# include "c67-gen.c"
-# include "c67-link.c"
-#elif defined(TCC_TARGET_RISCV64)
-# include "riscv64-gen.c"
-# include "riscv64-link.c"
-# include "riscv64-asm.c"
-#else
-#error unknown target
-#endif
-#undef TARGET_DEFS_ONLY
-
-/* -------------------------------------------- */
-
-#if PTR_SIZE == 8
-# define ELFCLASSW ELFCLASS64
-# define ElfW(type) Elf##64##_##type
-# define ELFW(type) ELF##64##_##type
-# define ElfW_Rel ElfW(Rela)
-# define SHT_RELX SHT_RELA
-# define REL_SECTION_FMT ".rela%s"
-#else
-# define ELFCLASSW ELFCLASS32
-# define ElfW(type) Elf##32##_##type
-# define ELFW(type) ELF##32##_##type
-# define ElfW_Rel ElfW(Rel)
-# define SHT_RELX SHT_REL
-# define REL_SECTION_FMT ".rel%s"
-#endif
-/* target address type */
-#define addr_t ElfW(Addr)
-#define ElfSym ElfW(Sym)
-
-#if PTR_SIZE == 8 && !defined TCC_TARGET_PE
-# define LONG_SIZE 8
-#else
-# define LONG_SIZE 4
-#endif
-
-/* -------------------------------------------- */
-
-#define INCLUDE_STACK_SIZE 32
-#define IFDEF_STACK_SIZE 64
-#define VSTACK_SIZE 512
-#define STRING_MAX_SIZE 1024
-#define TOKSTR_MAX_SIZE 256
-#define PACK_STACK_SIZE 8
-
-#define TOK_HASH_SIZE 16384 /* must be a power of two */
-#define TOK_ALLOC_INCR 512 /* must be a power of two */
-#define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
-
-/* token symbol management */
-typedef struct TokenSym {
- struct TokenSym *hash_next;
- struct Sym *sym_define; /* direct pointer to define */
- struct Sym *sym_label; /* direct pointer to label */
- struct Sym *sym_struct; /* direct pointer to structure */
- struct Sym *sym_identifier; /* direct pointer to identifier */
- int tok; /* token number */
- int len;
- char str[1];
-} TokenSym;
-
-#ifdef TCC_TARGET_PE
-typedef unsigned short nwchar_t;
-#else
-typedef int nwchar_t;
-#endif
-
-typedef struct CString {
- int size; /* size in bytes */
- int size_allocated;
- void *data; /* either 'char *' or 'nwchar_t *' */
- struct CString *prev;
-} CString;
-
-/* type definition */
-typedef struct CType {
- int t;
- struct Sym *ref;
-} CType;
-
-/* constant value */
-typedef union CValue {
- long double ld;
- double d;
- float f;
- uint64_t i;
- struct {
- const void *data;
- int size;
- } str;
- int tab[LDOUBLE_SIZE/4];
-} CValue;
-
-/* value on stack */
-typedef struct SValue {
- CType type; /* type */
- unsigned short r; /* register + flags */
- unsigned short r2; /* second register, used for 'long long'
- type. If not used, set to VT_CONST */
- union {
- struct { int jtrue, jfalse; }; /* forward jmps */
- CValue c; /* constant, if VT_CONST */
- };
- union {
- struct { unsigned short cmp_op, cmp_r; }; /* VT_CMP operation */
- struct Sym *sym; /* symbol, if (VT_SYM | VT_CONST), or if */
- }; /* result of unary() for an identifier. */
-
-} SValue;
-
-/* symbol attributes */
-struct SymAttr {
- unsigned short
- aligned : 5, /* alignment as log2+1 (0 == unspecified) */
- packed : 1,
- weak : 1,
- visibility : 2,
- dllexport : 1,
- nodecorate : 1,
- dllimport : 1,
- addrtaken : 1,
- nodebug : 1,
- xxxx : 2; /* not used */
-};
-
-/* function attributes or temporary attributes for parsing */
-struct FuncAttr {
- unsigned
- func_call : 3, /* calling convention (0..5), see below */
- func_type : 2, /* FUNC_OLD/NEW/ELLIPSIS */
- func_noreturn : 1, /* attribute((noreturn)) */
- func_ctor : 1, /* attribute((constructor)) */
- func_dtor : 1, /* attribute((destructor)) */
- func_args : 8, /* PE __stdcall args */
- func_alwinl : 1, /* always_inline */
- xxxx : 15;
-};
-
-/* symbol management */
-typedef struct Sym {
- int v; /* symbol token */
- unsigned short r; /* associated register or VT_CONST/VT_LOCAL and LVAL type */
- struct SymAttr a; /* symbol attributes */
- union {
- struct {
- int c; /* associated number or Elf symbol index */
- union {
- int sym_scope; /* scope level for locals */
- int jnext; /* next jump label */
- struct FuncAttr f; /* function attributes */
- int auxtype; /* bitfield access type */
- };
- };
- long long enum_val; /* enum constant if IS_ENUM_VAL */
- int *d; /* define token stream */
- struct Sym *ncl; /* next cleanup */
- };
- CType type; /* associated type */
- union {
- int *vla_array_str; /* vla array code */
- struct Sym *next; /* next related symbol (for fields and anoms) */
- struct Sym *cleanupstate; /* in defined labels */
- int asm_label; /* associated asm label */
- };
- struct Sym *prev; /* prev symbol in stack */
- struct Sym *prev_tok; /* previous symbol for this token */
-} Sym;
-
-/* section definition */
-typedef struct Section {
- unsigned long data_offset; /* current data offset */
- unsigned char *data; /* section data */
- unsigned long data_allocated; /* used for realloc() handling */
- TCCState *s1;
- int sh_name; /* elf section name (only used during output) */
- int sh_num; /* elf section number */
- int sh_type; /* elf section type */
- int sh_flags; /* elf section flags */
- int sh_info; /* elf section info */
- int sh_addralign; /* elf section alignment */
- int sh_entsize; /* elf entry size */
- unsigned long sh_size; /* section size (only used during output) */
- addr_t sh_addr; /* address at which the section is relocated */
- unsigned long sh_offset; /* file offset */
- int nb_hashed_syms; /* used to resize the hash table */
- struct Section *link; /* link to another section */
- struct Section *reloc; /* corresponding section for relocation, if any */
- struct Section *hash; /* hash table for symbols */
- struct Section *prev; /* previous section on section stack */
- char name[1]; /* section name */
-} Section;
-
-typedef struct DLLReference {
- int level;
- void *handle;
- unsigned char found, index;
- char name[1];
-} DLLReference;
-
-/* -------------------------------------------------- */
-
-#define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
-#define SYM_FIELD 0x20000000 /* struct/union field symbol space */
-#define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
-
-/* stored in 'Sym->f.func_type' field */
-#define FUNC_NEW 1 /* ansi function prototype */
-#define FUNC_OLD 2 /* old function prototype */
-#define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
-
-/* stored in 'Sym->f.func_call' field */
-#define FUNC_CDECL 0 /* standard c call */
-#define FUNC_STDCALL 1 /* pascal c call */
-#define FUNC_FASTCALL1 2 /* first param in %eax */
-#define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
-#define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
-#define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
-
-/* field 'Sym.t' for macros */
-#define MACRO_OBJ 0 /* object like macro */
-#define MACRO_FUNC 1 /* function like macro */
-
-/* field 'Sym.r' for C labels */
-#define LABEL_DEFINED 0 /* label is defined */
-#define LABEL_FORWARD 1 /* label is forward defined */
-#define LABEL_DECLARED 2 /* label is declared but never used */
-#define LABEL_GONE 3 /* label isn't in scope, but not yet popped
- from local_label_stack (stmt exprs) */
-
-/* type_decl() types */
-#define TYPE_ABSTRACT 1 /* type without variable */
-#define TYPE_DIRECT 2 /* type with variable */
-#define TYPE_PARAM 4 /* type declares function parameter */
-#define TYPE_NEST 8 /* nested call to post_type */
-
-#define IO_BUF_SIZE 8192
-
-typedef struct BufferedFile {
- uint8_t *buf_ptr;
- uint8_t *buf_end;
- int fd;
- struct BufferedFile *prev;
- int line_num; /* current line number - here to simplify code */
- int line_ref; /* tcc -E: last printed line */
- int ifndef_macro; /* #ifndef macro / #endif search */
- int ifndef_macro_saved; /* saved ifndef_macro */
- int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
- int include_next_index; /* next search path */
- char filename[1024]; /* filename */
- char *true_filename; /* filename not modified by # line directive */
- unsigned char unget[4];
- unsigned char buffer[1]; /* extra size for CH_EOB char */
-} BufferedFile;
-
-#define CH_EOB '\\' /* end of buffer or '\0' char in file */
-#define CH_EOF (-1) /* end of file */
-
-/* used to record tokens */
-typedef struct TokenString {
- int *str;
- int len;
- int lastlen;
- int allocated_len;
- int last_line_num;
- int save_line_num;
- /* used to chain token-strings with begin/end_macro() */
- struct TokenString *prev;
- const int *prev_ptr;
- char alloc;
-} TokenString;
-
-/* GNUC attribute definition */
-typedef struct AttributeDef {
- struct SymAttr a;
- struct FuncAttr f;
- struct Section *section;
- Sym *cleanup_func;
- int alias_target; /* token */
- int asm_label; /* associated asm label */
- char attr_mode; /* __attribute__((__mode__(...))) */
-} AttributeDef;
-
-/* inline functions */
-typedef struct InlineFunc {
- TokenString *func_str;
- Sym *sym;
- char filename[1];
-} InlineFunc;
-
-/* include file cache, used to find files faster and also to eliminate
- inclusion if the include file is protected by #ifndef ... #endif */
-typedef struct CachedInclude {
- struct stat st;
-#ifdef _WIN32
- unsigned long long hash;
-#endif
- int ifndef_macro;
- int once;
- int hash_next; /* -1 if none */
- char filename[1]; /* path specified in #include */
-} CachedInclude;
-
-#define CACHED_INCLUDES_HASH_SIZE 32
-
-#ifdef CONFIG_TCC_ASM
-typedef struct ExprValue {
- uint64_t v;
- Sym *sym;
- int pcrel;
-} ExprValue;
-
-#define MAX_ASM_OPERANDS 30
-typedef struct ASMOperand {
- int id; /* GCC 3 optional identifier (0 if number only supported) */
- char constraint[16];
- char asm_str[16]; /* computed asm string for operand */
- SValue *vt; /* C value of the expression */
- int ref_index; /* if >= 0, gives reference to a output constraint */
- int input_index; /* if >= 0, gives reference to an input constraint */
- int priority; /* priority, used to assign registers */
- int reg; /* if >= 0, register number used for this operand */
- int is_llong; /* true if double register value */
- int is_memory; /* true if memory operand */
- int is_rw; /* for '+' modifier */
- int is_label; /* for asm goto */
-} ASMOperand;
-#endif
-
-/* extra symbol attributes (not in symbol table) */
-struct sym_attr {
- unsigned got_offset;
- unsigned plt_offset;
- int plt_sym;
- int dyn_index;
-#ifdef TCC_TARGET_ARM
- unsigned char plt_thumb_stub:1;
-#endif
-};
-
-struct TCCState {
- unsigned char verbose; /* if true, display some information during compilation */
- unsigned char nostdinc; /* if true, no standard headers are added */
- unsigned char nostdlib; /* if true, no standard libraries are added */
- unsigned char nocommon; /* if true, do not use common symbols for .bss data */
- unsigned char static_link; /* if true, static linking is performed */
- unsigned char rdynamic; /* if true, all symbols are exported */
- unsigned char symbolic; /* if true, resolve symbols in the current module first */
- unsigned char filetype; /* file type for compilation (NONE,C,ASM) */
- unsigned char optimize; /* only to #define __OPTIMIZE__ */
- unsigned char option_pthread; /* -pthread option */
- unsigned char enable_new_dtags; /* -Wl,--enable-new-dtags */
- unsigned int cversion; /* supported C ISO version, 199901 (the default), 201112, ... */
-
- /* C language options */
- unsigned char char_is_unsigned;
- unsigned char leading_underscore;
- unsigned char ms_extensions; /* allow nested named struct w/o identifier behave like unnamed */
- unsigned char dollars_in_identifiers; /* allows '$' char in identifiers */
- unsigned char ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */
-
- /* warning switches */
- unsigned char warn_none;
- unsigned char warn_all;
- unsigned char warn_error;
- unsigned char warn_write_strings;
- unsigned char warn_unsupported;
- unsigned char warn_implicit_function_declaration;
- unsigned char warn_discarded_qualifiers;
- #define WARN_ON 1 /* warning is on (-Woption) */
- unsigned char warn_num; /* temp var for tcc_warning_c() */
-
- unsigned char option_r; /* option -r */
- unsigned char do_bench; /* option -bench */
- unsigned char just_deps; /* option -M */
- unsigned char gen_deps; /* option -MD */
- unsigned char include_sys_deps; /* option -MD */
-
- /* compile with debug symbol (and use them if error during execution) */
- unsigned char do_debug;
- unsigned char dwarf;
- unsigned char do_backtrace;
-#ifdef CONFIG_TCC_BCHECK
- /* compile with built-in memory and bounds checker */
- unsigned char do_bounds_check;
-#endif
- unsigned char test_coverage; /* generate test coverage code */
-
- /* use GNU C extensions */
- unsigned char gnu_ext;
- /* use TinyCC extensions */
- unsigned char tcc_ext;
-
- unsigned char dflag; /* -dX value */
- unsigned char Pflag; /* -P switch (LINE_MACRO_OUTPUT_FORMAT) */
-
-#ifdef TCC_TARGET_X86_64
- unsigned char nosse; /* For -mno-sse support. */
-#endif
-#ifdef TCC_TARGET_ARM
- unsigned char float_abi; /* float ABI of the generated code*/
-#endif
-
- unsigned char has_text_addr;
- addr_t text_addr; /* address of text section */
- unsigned section_align; /* section alignment */
-#ifdef TCC_TARGET_I386
- int seg_size; /* 32. Can be 16 with i386 assembler (.code16) */
-#endif
-
- char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
- char *soname; /* as specified on the command line (-soname) */
- char *rpath; /* as specified on the command line (-Wl,-rpath=) */
- char *elf_entryname; /* "_start" unless set */
- char *init_symbol; /* symbols to call at load-time (not used currently) */
- char *fini_symbol; /* symbols to call at unload-time (not used currently) */
- char *mapfile; /* create a mapfile (not used currently) */
-
- /* output type, see TCC_OUTPUT_XXX */
- int output_type;
- /* output format, see TCC_OUTPUT_FORMAT_xxx */
- int output_format;
- /* nth test to run with -dt -run */
- int run_test;
-
- /* array of all loaded dlls (including those referenced by loaded dlls) */
- DLLReference **loaded_dlls;
- int nb_loaded_dlls;
-
- /* include paths */
- char **include_paths;
- int nb_include_paths;
-
- char **sysinclude_paths;
- int nb_sysinclude_paths;
-
- /* library paths */
- char **library_paths;
- int nb_library_paths;
-
- /* crt?.o object path */
- char **crt_paths;
- int nb_crt_paths;
-
- /* -D / -U options */
- CString cmdline_defs;
- /* -include options */
- CString cmdline_incl;
-
- /* error handling */
- void *error_opaque;
- void (*error_func)(void *opaque, const char *msg);
- int error_set_jmp_enabled;
- jmp_buf error_jmp_buf;
- int nb_errors;
-
- /* output file for preprocessing (-E) */
- FILE *ppfp;
-
- /* for -MD/-MF: collected dependencies for this compilation */
- char **target_deps;
- int nb_target_deps;
-
- /* compilation */
- BufferedFile *include_stack[INCLUDE_STACK_SIZE];
- BufferedFile **include_stack_ptr;
-
- int ifdef_stack[IFDEF_STACK_SIZE];
- int *ifdef_stack_ptr;
-
- /* included files enclosed with #ifndef MACRO */
- int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
- CachedInclude **cached_includes;
- int nb_cached_includes;
-
- /* #pragma pack stack */
- int pack_stack[PACK_STACK_SIZE];
- int *pack_stack_ptr;
- char **pragma_libs;
- int nb_pragma_libs;
-
- /* inline functions are stored as token lists and compiled last
- only if referenced */
- struct InlineFunc **inline_fns;
- int nb_inline_fns;
-
- /* sections */
- Section **sections;
- int nb_sections; /* number of sections, including first dummy section */
-
- Section **priv_sections;
- int nb_priv_sections; /* number of private sections */
-
- /* predefined sections */
- Section *text_section, *data_section, *rodata_section, *bss_section;
- Section *common_section;
- Section *cur_text_section; /* current section where function code is generated */
-#ifdef CONFIG_TCC_BCHECK
- /* bound check related sections */
- Section *bounds_section; /* contains global data bound description */
- Section *lbounds_section; /* contains local data bound description */
-#endif
- /* symbol section */
- Section *symtab_section;
- /* temporary dynamic symbol sections (for dll loading) */
- Section *dynsymtab_section;
- /* exported dynamic symbol section */
- Section *dynsym;
- /* copy of the global symtab_section variable */
- Section *symtab;
- /* got & plt handling */
- Section *got, *plt;
- /* debug sections */
- Section *stab_section;
- Section *dwarf_info_section;
- Section *dwarf_abbrev_section;
- Section *dwarf_line_section;
- Section *dwarf_aranges_section;
- Section *dwarf_str_section;
- Section *dwarf_line_str_section;
- int dwlo, dwhi; /* dwarf section range */
- /* test coverage */
- Section *tcov_section;
- /* debug state */
- struct _tccdbg *dState;
-
- /* Is there a new undefined sym since last new_undef_sym() */
- int new_undef_sym;
- /* extra attributes (eg. GOT/PLT value) for symtab symbols */
- struct sym_attr *sym_attrs;
- int nb_sym_attrs;
- /* ptr to next reloc entry reused */
- ElfW_Rel *qrel;
- #define qrel s1->qrel
-
-#ifdef TCC_TARGET_RISCV64
- struct pcrel_hi { addr_t addr, val; } last_hi;
- #define last_hi s1->last_hi
-#endif
-
-#ifdef TCC_TARGET_PE
- /* PE info */
- int pe_subsystem;
- unsigned pe_characteristics;
- unsigned pe_file_align;
- unsigned pe_stack_size;
- addr_t pe_imagebase;
-# ifdef TCC_TARGET_X86_64
- Section *uw_pdata;
- int uw_sym;
- unsigned uw_offs;
-# endif
-#endif
-
-#if defined TCC_TARGET_MACHO
- char *install_name;
- uint32_t compatibility_version;
- uint32_t current_version;
-#endif
-
-#ifndef ELF_OBJ_ONLY
- int nb_sym_versions;
- struct sym_version *sym_versions;
- int nb_sym_to_version;
- int *sym_to_version;
- int dt_verneednum;
- Section *versym_section;
- Section *verneed_section;
-#endif
-
-#ifdef TCC_IS_NATIVE
- const char *runtime_main;
- void **runtime_mem;
- int nb_runtime_mem;
-#endif
-
-#ifdef CONFIG_TCC_BACKTRACE
- int rt_num_callers;
-#endif
-
- /* benchmark info */
- int total_idents;
- int total_lines;
- unsigned int total_bytes;
- unsigned int total_output[4];
-
- /* option -dnum (for general development purposes) */
- int g_debug;
-
- /* used by tcc_load_ldscript */
- int fd, cc;
-
- /* for warnings/errors for object files */
- const char *current_filename;
-
- /* used by main and tcc_parse_args only */
- struct filespec **files; /* files seen on command line */
- int nb_files; /* number thereof */
- int nb_libraries; /* number of libs thereof */
- char *outfile; /* output filename */
- char *deps_outfile; /* option -MF */
- int argc;
- char **argv;
- CString linker_arg; /* collect -Wl options */
-};
-
-struct filespec {
- char type;
- char name[1];
-};
-
-/* The current value can be: */
-#define VT_VALMASK 0x003f /* mask for value location, register or: */
-#define VT_CONST 0x0030 /* constant in vc (must be first non register value) */
-#define VT_LLOCAL 0x0031 /* lvalue, offset on stack */
-#define VT_LOCAL 0x0032 /* offset on stack */
-#define VT_CMP 0x0033 /* the value is stored in processor flags (in vc) */
-#define VT_JMP 0x0034 /* value is the consequence of jmp true (even) */
-#define VT_JMPI 0x0035 /* value is the consequence of jmp false (odd) */
-#define VT_LVAL 0x0100 /* var is an lvalue */
-#define VT_SYM 0x0200 /* a symbol value is added */
-#define VT_MUSTCAST 0x0C00 /* value must be casted to be correct (used for
- char/short stored in integer registers) */
-#define VT_NONCONST 0x1000 /* VT_CONST, but not an (C standard) integer
- constant expression */
-#define VT_MUSTBOUND 0x4000 /* bound checking must be done before
- dereferencing value */
-#define VT_BOUNDED 0x8000 /* value is bounded. The address of the
- bounding function call point is in vc */
-/* types */
-#define VT_BTYPE 0x000f /* mask for basic type */
-#define VT_VOID 0 /* void type */
-#define VT_BYTE 1 /* signed byte type */
-#define VT_SHORT 2 /* short type */
-#define VT_INT 3 /* integer type */
-#define VT_LLONG 4 /* 64 bit integer */
-#define VT_PTR 5 /* pointer */
-#define VT_FUNC 6 /* function type */
-#define VT_STRUCT 7 /* struct/union definition */
-#define VT_FLOAT 8 /* IEEE float */
-#define VT_DOUBLE 9 /* IEEE double */
-#define VT_LDOUBLE 10 /* IEEE long double */
-#define VT_BOOL 11 /* ISOC99 boolean type */
-#define VT_QLONG 13 /* 128-bit integer. Only used for x86-64 ABI */
-#define VT_QFLOAT 14 /* 128-bit float. Only used for x86-64 ABI */
-
-#define VT_UNSIGNED 0x0010 /* unsigned type */
-#define VT_DEFSIGN 0x0020 /* explicitly signed or unsigned */
-#define VT_ARRAY 0x0040 /* array type (also has VT_PTR) */
-#define VT_BITFIELD 0x0080 /* bitfield modifier */
-#define VT_CONSTANT 0x0100 /* const modifier */
-#define VT_VOLATILE 0x0200 /* volatile modifier */
-#define VT_VLA 0x0400 /* VLA type (also has VT_PTR and VT_ARRAY) */
-#define VT_LONG 0x0800 /* long type (also has VT_INT rsp. VT_LLONG) */
-
-/* storage */
-#define VT_EXTERN 0x00001000 /* extern definition */
-#define VT_STATIC 0x00002000 /* static variable */
-#define VT_TYPEDEF 0x00004000 /* typedef definition */
-#define VT_INLINE 0x00008000 /* inline definition */
-/* currently unused: 0x000[1248]0000 */
-
-#define VT_STRUCT_SHIFT 20 /* shift for bitfield shift values (32 - 2*6) */
-#define VT_STRUCT_MASK (((1U << (6+6)) - 1) << VT_STRUCT_SHIFT | VT_BITFIELD)
-#define BIT_POS(t) (((t) >> VT_STRUCT_SHIFT) & 0x3f)
-#define BIT_SIZE(t) (((t) >> (VT_STRUCT_SHIFT + 6)) & 0x3f)
-
-#define VT_UNION (1 << VT_STRUCT_SHIFT | VT_STRUCT)
-#define VT_ENUM (2 << VT_STRUCT_SHIFT) /* integral type is an enum really */
-#define VT_ENUM_VAL (3 << VT_STRUCT_SHIFT) /* integral type is an enum constant really */
-
-#define IS_ENUM(t) ((t & VT_STRUCT_MASK) == VT_ENUM)
-#define IS_ENUM_VAL(t) ((t & VT_STRUCT_MASK) == VT_ENUM_VAL)
-#define IS_UNION(t) ((t & (VT_STRUCT_MASK|VT_BTYPE)) == VT_UNION)
-
-#define VT_ATOMIC VT_VOLATILE
-
-/* type mask (except storage) */
-#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
-#define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
-
-/* symbol was created by tccasm.c first */
-#define VT_ASM (VT_VOID | 1 << VT_STRUCT_SHIFT)
-#define VT_ASM_FUNC (VT_ASM | 2 << VT_STRUCT_SHIFT)
-#define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM)
-
-/* general: set/get the pseudo-bitfield value for bit-mask M */
-#define BFVAL(M,N) ((unsigned)((M) & ~((M) << 1)) * (N))
-#define BFGET(X,M) (((X) & (M)) / BFVAL(M,1))
-#define BFSET(X,M,N) ((X) = ((X) & ~(M)) | BFVAL(M,N))
-
-/* token values */
-
-/* conditional ops */
-#define TOK_LAND 0x90
-#define TOK_LOR 0x91
-/* warning: the following compare tokens depend on i386 asm code */
-#define TOK_ULT 0x92
-#define TOK_UGE 0x93
-#define TOK_EQ 0x94
-#define TOK_NE 0x95
-#define TOK_ULE 0x96
-#define TOK_UGT 0x97
-#define TOK_Nset 0x98
-#define TOK_Nclear 0x99
-#define TOK_LT 0x9c
-#define TOK_GE 0x9d
-#define TOK_LE 0x9e
-#define TOK_GT 0x9f
-
-#define TOK_ISCOND(t) (t >= TOK_LAND && t <= TOK_GT)
-
-#define TOK_DEC 0x80 /* -- */
-#define TOK_MID 0x81 /* inc/dec, to void constant */
-#define TOK_INC 0x82 /* ++ */
-#define TOK_UDIV 0x83 /* unsigned division */
-#define TOK_UMOD 0x84 /* unsigned modulo */
-#define TOK_PDIV 0x85 /* fast division with undefined rounding for pointers */
-#define TOK_UMULL 0x86 /* unsigned 32x32 -> 64 mul */
-#define TOK_ADDC1 0x87 /* add with carry generation */
-#define TOK_ADDC2 0x88 /* add with carry use */
-#define TOK_SUBC1 0x89 /* add with carry generation */
-#define TOK_SUBC2 0x8a /* add with carry use */
-#define TOK_SHL '<' /* shift left */
-#define TOK_SAR '>' /* signed shift right */
-#define TOK_SHR 0x8b /* unsigned shift right */
-#define TOK_NEG TOK_MID /* unary minus operation (for floats) */
-
-#define TOK_ARROW 0xa0 /* -> */
-#define TOK_DOTS 0xa1 /* three dots */
-#define TOK_TWODOTS 0xa2 /* C++ token ? */
-#define TOK_TWOSHARPS 0xa3 /* ## preprocessing token */
-#define TOK_PLCHLDR 0xa4 /* placeholder token as defined in C99 */
-#define TOK_NOSUBST 0xa5 /* means following token has already been pp'd */
-#define TOK_PPJOIN 0xa6 /* A '##' in the right position to mean pasting */
-
-/* assignment operators */
-#define TOK_A_ADD 0xb0
-#define TOK_A_SUB 0xb1
-#define TOK_A_MUL 0xb2
-#define TOK_A_DIV 0xb3
-#define TOK_A_MOD 0xb4
-#define TOK_A_AND 0xb5
-#define TOK_A_OR 0xb6
-#define TOK_A_XOR 0xb7
-#define TOK_A_SHL 0xb8
-#define TOK_A_SAR 0xb9
-
-#define TOK_ASSIGN(t) (t >= TOK_A_ADD && t <= TOK_A_SAR)
-#define TOK_ASSIGN_OP(t) ("+-*/%&|^<>"[t - TOK_A_ADD])
-
-/* tokens that carry values (in additional token string space / tokc) --> */
-#define TOK_CCHAR 0xc0 /* char constant in tokc */
-#define TOK_LCHAR 0xc1
-#define TOK_CINT 0xc2 /* number in tokc */
-#define TOK_CUINT 0xc3 /* unsigned int constant */
-#define TOK_CLLONG 0xc4 /* long long constant */
-#define TOK_CULLONG 0xc5 /* unsigned long long constant */
-#define TOK_CLONG 0xc6 /* long constant */
-#define TOK_CULONG 0xc7 /* unsigned long constant */
-#define TOK_STR 0xc8 /* pointer to string in tokc */
-#define TOK_LSTR 0xc9
-#define TOK_CFLOAT 0xca /* float constant */
-#define TOK_CDOUBLE 0xcb /* double constant */
-#define TOK_CLDOUBLE 0xcc /* long double constant */
-#define TOK_PPNUM 0xcd /* preprocessor number */
-#define TOK_PPSTR 0xce /* preprocessor string */
-#define TOK_LINENUM 0xcf /* line number info */
-
-#define TOK_HAS_VALUE(t) (t >= TOK_CCHAR && t <= TOK_LINENUM)
-
-#define TOK_EOF (-1) /* end of file */
-#define TOK_LINEFEED 10 /* line feed */
-
-/* all identifiers and strings have token above that */
-#define TOK_IDENT 256
-
-enum tcc_token {
- TOK_LAST = TOK_IDENT - 1
-#define DEF(id, str) ,id
-#include "tcctok.h"
-#undef DEF
-};
-
-/* keywords: tok >= TOK_IDENT && tok < TOK_UIDENT */
-#define TOK_UIDENT TOK_DEFINE
-
-/* ------------ libtcc.c ------------ */
-
-ST_DATA struct TCCState *tcc_state;
-ST_DATA void** stk_data;
-ST_DATA int nb_stk_data;
-
-/* public functions currently used by the tcc main function */
-ST_FUNC char *pstrcpy(char *buf, size_t buf_size, const char *s);
-ST_FUNC char *pstrcat(char *buf, size_t buf_size, const char *s);
-ST_FUNC char *pstrncpy(char *out, const char *in, size_t num);
-PUB_FUNC char *tcc_basename(const char *name);
-PUB_FUNC char *tcc_fileextension (const char *name);
-
-#ifndef MEM_DEBUG
-PUB_FUNC void tcc_free(void *ptr);
-PUB_FUNC void *tcc_malloc(unsigned long size);
-PUB_FUNC void *tcc_mallocz(unsigned long size);
-PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size);
-PUB_FUNC char *tcc_strdup(const char *str);
-#else
-#define tcc_free(ptr) tcc_free_debug(ptr)
-#define tcc_malloc(size) tcc_malloc_debug(size, __FILE__, __LINE__)
-#define tcc_mallocz(size) tcc_mallocz_debug(size, __FILE__, __LINE__)
-#define tcc_realloc(ptr,size) tcc_realloc_debug(ptr, size, __FILE__, __LINE__)
-#define tcc_strdup(str) tcc_strdup_debug(str, __FILE__, __LINE__)
-PUB_FUNC void tcc_free_debug(void *ptr);
-PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line);
-PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line);
-PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line);
-PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
-#endif
-
-#define free(p) use_tcc_free(p)
-#define malloc(s) use_tcc_malloc(s)
-#define realloc(p, s) use_tcc_realloc(p, s)
-#undef strdup
-#define strdup(s) use_tcc_strdup(s)
-PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) PRINTF_LIKE(1,2);
-PUB_FUNC NORETURN void _tcc_error(const char *fmt, ...) PRINTF_LIKE(1,2);
-PUB_FUNC void _tcc_warning(const char *fmt, ...) PRINTF_LIKE(1,2);
-#define tcc_internal_error(msg) tcc_error("internal compiler error\n"\
- "%s:%d: in %s(): " msg, __FILE__,__LINE__,__FUNCTION__)
-
-/* other utilities */
-ST_FUNC void dynarray_add(void *ptab, int *nb_ptr, void *data);
-ST_FUNC void dynarray_reset(void *pp, int *n);
-ST_INLN void cstr_ccat(CString *cstr, int ch);
-ST_FUNC void cstr_cat(CString *cstr, const char *str, int len);
-ST_FUNC void cstr_wccat(CString *cstr, int ch);
-ST_FUNC void cstr_new(CString *cstr);
-ST_FUNC void cstr_free(CString *cstr);
-ST_FUNC int cstr_printf(CString *cs, const char *fmt, ...) PRINTF_LIKE(2,3);
-ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap);
-ST_FUNC void cstr_reset(CString *cstr);
-ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
-ST_FUNC int tcc_open(TCCState *s1, const char *filename);
-ST_FUNC void tcc_close(void);
-
-/* mark a memory pointer on stack for cleanup after errors */
-#define stk_push(p) dynarray_add(&stk_data, &nb_stk_data, p)
-#define stk_pop() (--nb_stk_data)
-/* mark CString on stack for cleanup errors */
-#define cstr_new_s(cstr) (cstr_new(cstr), stk_push(&(cstr)->data))
-#define cstr_free_s(cstr) (cstr_free(cstr), stk_pop())
-
-ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags);
-/* flags: */
-#define AFF_PRINT_ERROR 0x10 /* print error if file not found */
-#define AFF_REFERENCED_DLL 0x20 /* load a referenced dll from another dll */
-#define AFF_TYPE_BIN 0x40 /* file to add is binary */
-#define AFF_WHOLE_ARCHIVE 0x80 /* load all objects from archive */
-/* s->filetype: */
-#define AFF_TYPE_NONE 0
-#define AFF_TYPE_C 1
-#define AFF_TYPE_ASM 2
-#define AFF_TYPE_ASMPP 4
-#define AFF_TYPE_LIB 8
-#define AFF_TYPE_MASK (15 | AFF_TYPE_BIN)
-/* values from tcc_object_type(...) */
-#define AFF_BINTYPE_REL 1
-#define AFF_BINTYPE_DYN 2
-#define AFF_BINTYPE_AR 3
-#define AFF_BINTYPE_C67 4
-
-#ifndef ELF_OBJ_ONLY
-ST_FUNC int tcc_add_crt(TCCState *s, const char *filename);
-#endif
-ST_FUNC int tcc_add_dll(TCCState *s, const char *filename, int flags);
-ST_FUNC void tcc_add_support(TCCState *s1, const char *filename);
-#ifdef CONFIG_TCC_BCHECK
-ST_FUNC void tcc_add_bcheck(TCCState *s1);
-#endif
-#ifdef CONFIG_TCC_BACKTRACE
-ST_FUNC void tcc_add_btstub(TCCState *s1);
-#endif
-ST_FUNC void tcc_add_pragma_libs(TCCState *s1);
-PUB_FUNC int tcc_add_library_err(TCCState *s, const char *f);
-PUB_FUNC void tcc_print_stats(TCCState *s, unsigned total_time);
-PUB_FUNC int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
-#ifdef _WIN32
-ST_FUNC char *normalize_slashes(char *path);
-#endif
-ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level);
-ST_FUNC char *tcc_load_text(int fd);
-
-/* tcc_parse_args return codes: */
-#define OPT_HELP 1
-#define OPT_HELP2 2
-#define OPT_V 3
-#define OPT_PRINT_DIRS 4
-#define OPT_AR 5
-#define OPT_IMPDEF 6
-#define OPT_M32 32
-#define OPT_M64 64
-
-/* ------------ tccpp.c ------------ */
-
-ST_DATA struct BufferedFile *file;
-ST_DATA int tok;
-ST_DATA CValue tokc;
-ST_DATA const int *macro_ptr;
-ST_DATA int parse_flags;
-ST_DATA int tok_flags;
-ST_DATA CString tokcstr; /* current parsed string, if any */
-
-/* display benchmark infos */
-ST_DATA int tok_ident;
-ST_DATA TokenSym **table_ident;
-
-#define TOK_FLAG_BOL 0x0001 /* beginning of line before */
-#define TOK_FLAG_BOF 0x0002 /* beginning of file before */
-#define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
-#define TOK_FLAG_EOF 0x0008 /* end of file */
-
-#define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
-#define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
-#define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
- token. line feed is also
- returned at eof */
-#define PARSE_FLAG_ASM_FILE 0x0008 /* we processing an asm file: '#' can be used for line comment, etc. */
-#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
-#define PARSE_FLAG_ACCEPT_STRAYS 0x0020 /* next() returns '\\' token */
-#define PARSE_FLAG_TOK_STR 0x0040 /* return parsed strings instead of TOK_PPSTR */
-
-/* isidnum_table flags: */
-#define IS_SPC 1
-#define IS_ID 2
-#define IS_NUM 4
-
-enum line_macro_output_format {
- LINE_MACRO_OUTPUT_FORMAT_GCC,
- LINE_MACRO_OUTPUT_FORMAT_NONE,
- LINE_MACRO_OUTPUT_FORMAT_STD,
- LINE_MACRO_OUTPUT_FORMAT_P10 = 11
-};
-
-ST_FUNC TokenSym *tok_alloc(const char *str, int len);
-ST_FUNC int tok_alloc_const(const char *str);
-ST_FUNC const char *get_tok_str(int v, CValue *cv);
-ST_FUNC void begin_macro(TokenString *str, int alloc);
-ST_FUNC void end_macro(void);
-ST_FUNC int set_idnum(int c, int val);
-ST_INLN void tok_str_new(TokenString *s);
-ST_FUNC TokenString *tok_str_alloc(void);
-ST_FUNC void tok_str_free(TokenString *s);
-ST_FUNC void tok_str_free_str(int *str);
-ST_FUNC void tok_str_add(TokenString *s, int t);
-ST_FUNC void tok_str_add_tok(TokenString *s);
-ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg);
-ST_FUNC void define_undef(Sym *s);
-ST_INLN Sym *define_find(int v);
-ST_FUNC void free_defines(Sym *b);
-ST_FUNC void parse_define(void);
-ST_FUNC void preprocess(int is_bof);
-ST_FUNC void next(void);
-ST_INLN void unget_tok(int last_tok);
-ST_FUNC void preprocess_start(TCCState *s1, int filetype);
-ST_FUNC void preprocess_end(TCCState *s1);
-ST_FUNC void tccpp_new(TCCState *s);
-ST_FUNC void tccpp_delete(TCCState *s);
-ST_FUNC int tcc_preprocess(TCCState *s1);
-ST_FUNC void skip(int c);
-ST_FUNC NORETURN void expect(const char *msg);
-
-/* space excluding newline */
-static inline int is_space(int ch) {
- return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
-}
-static inline int isid(int c) {
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
-}
-static inline int isnum(int c) {
- return c >= '0' && c <= '9';
-}
-static inline int isoct(int c) {
- return c >= '0' && c <= '7';
-}
-static inline int toup(int c) {
- return (c >= 'a' && c <= 'z') ? c - 'a' + 'A' : c;
-}
-
-/* ------------ tccgen.c ------------ */
-
-#define SYM_POOL_NB (8192 / sizeof(Sym))
-
-ST_DATA Sym *global_stack;
-ST_DATA Sym *local_stack;
-ST_DATA Sym *local_label_stack;
-ST_DATA Sym *global_label_stack;
-ST_DATA Sym *define_stack;
-ST_DATA CType int_type, func_old_type, char_pointer_type;
-ST_DATA SValue *vtop;
-ST_DATA int rsym, anon_sym, ind, loc;
-ST_DATA char debug_modes;
-
-ST_DATA int nocode_wanted; /* true if no code generation wanted for an expression */
-ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
-ST_DATA CType func_vt; /* current function return type (used by return instruction) */
-ST_DATA int func_var; /* true if current function is variadic */
-ST_DATA int func_vc;
-ST_DATA int func_ind;
-ST_DATA const char *funcname;
-
-ST_FUNC void tccgen_init(TCCState *s1);
-ST_FUNC int tccgen_compile(TCCState *s1);
-ST_FUNC void tccgen_finish(TCCState *s1);
-ST_FUNC void check_vstack(void);
-
-ST_INLN int is_float(int t);
-ST_FUNC int ieee_finite(double d);
-ST_FUNC int exact_log2p1(int i);
-ST_FUNC void test_lvalue(void);
-
-ST_FUNC ElfSym *elfsym(Sym *);
-ST_FUNC void update_storage(Sym *sym);
-ST_FUNC void put_extern_sym2(Sym *sym, int sh_num, addr_t value, unsigned long size, int can_add_underscore);
-ST_FUNC void put_extern_sym(Sym *sym, Section *section, addr_t value, unsigned long size);
-#if PTR_SIZE == 4
-ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type);
-#endif
-ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type, addr_t addend);
-
-ST_INLN void sym_free(Sym *sym);
-ST_FUNC Sym *sym_push(int v, CType *type, int r, int c);
-ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
-ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c);
-ST_FUNC Sym *sym_find2(Sym *s, int v);
-ST_INLN Sym *sym_find(int v);
-ST_FUNC Sym *label_find(int v);
-ST_FUNC Sym *label_push(Sym **ptop, int v, int flags);
-ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep);
-ST_INLN Sym *struct_find(int v);
-
-ST_FUNC Sym *global_identifier_push(int v, int t, int c);
-ST_FUNC Sym *external_global_sym(int v, CType *type);
-ST_FUNC Sym *external_helper_sym(int v);
-ST_FUNC void vpush_helper_func(int v);
-ST_FUNC void vset(CType *type, int r, int v);
-ST_FUNC void vset_VT_CMP(int op);
-ST_FUNC void vpushi(int v);
-ST_FUNC void vpushv(SValue *v);
-ST_FUNC void vpushsym(CType *type, Sym *sym);
-ST_FUNC void vswap(void);
-ST_FUNC void vrote(SValue *e, int n);
-ST_FUNC void vrott(int n);
-ST_FUNC void vrotb(int n);
-ST_FUNC void vpop(void);
-#if PTR_SIZE == 4
-ST_FUNC void lexpand(void);
-#endif
-#ifdef TCC_TARGET_ARM
-ST_FUNC int get_reg_ex(int rc, int rc2);
-#endif
-ST_FUNC void save_reg(int r);
-ST_FUNC void save_reg_upstack(int r, int n);
-ST_FUNC int get_reg(int rc);
-ST_FUNC void save_regs(int n);
-ST_FUNC void gaddrof(void);
-ST_FUNC int gv(int rc);
-ST_FUNC void gv2(int rc1, int rc2);
-ST_FUNC void gen_op(int op);
-ST_FUNC int type_size(CType *type, int *a);
-ST_FUNC void mk_pointer(CType *type);
-ST_FUNC void vstore(void);
-ST_FUNC void inc(int post, int c);
-ST_FUNC CString* parse_mult_str(const char *msg);
-ST_FUNC CString* parse_asm_str(void);
-ST_FUNC void indir(void);
-ST_FUNC void unary(void);
-ST_FUNC void gexpr(void);
-ST_FUNC int expr_const(void);
-#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
-ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size);
-#endif
-#if defined TCC_TARGET_X86_64 && !defined TCC_TARGET_PE
-ST_FUNC int classify_x86_64_va_arg(CType *ty);
-#endif
-#ifdef CONFIG_TCC_BCHECK
-ST_FUNC void gbound_args(int nb_args);
-ST_DATA int func_bound_add_epilog;
-#endif
-
-/* ------------ tccelf.c ------------ */
-
-#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
-#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
-#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
-#define TCC_OUTPUT_DYN TCC_OUTPUT_DLL
-
-#define ARMAG "!<arch>\n" /* For COFF and a.out archives */
-
-typedef struct {
- unsigned int n_strx; /* index into string table of name */
- unsigned char n_type; /* type of symbol */
- unsigned char n_other; /* misc info (usually empty) */
- unsigned short n_desc; /* description field */
- unsigned int n_value; /* value of symbol */
-} Stab_Sym;
-
-ST_FUNC void tccelf_new(TCCState *s);
-ST_FUNC void tccelf_delete(TCCState *s);
-ST_FUNC void tccelf_begin_file(TCCState *s1);
-ST_FUNC void tccelf_end_file(TCCState *s1);
-#ifdef CONFIG_TCC_BCHECK
-ST_FUNC void tccelf_bounds_new(TCCState *s);
-#endif
-ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags);
-ST_FUNC void section_realloc(Section *sec, unsigned long new_size);
-ST_FUNC size_t section_add(Section *sec, addr_t size, int align);
-ST_FUNC void *section_ptr_add(Section *sec, addr_t size);
-ST_FUNC Section *find_section(TCCState *s1, const char *name);
-ST_FUNC Section *new_symtab(TCCState *s1, const char *symtab_name, int sh_type, int sh_flags, const char *strtab_name, const char *hash_name, int hash_sh_flags);
-
-ST_FUNC int put_elf_str(Section *s, const char *sym);
-ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
-ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size, int info, int other, int shndx, const char *name);
-ST_FUNC int find_elf_sym(Section *s, const char *name);
-ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset, int type, int symbol);
-ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset, int type, int symbol, addr_t addend);
-
-ST_FUNC void resolve_common_syms(TCCState *s1);
-ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve);
-ST_FUNC void relocate_sections(TCCState *s1);
-
-ST_FUNC ssize_t full_read(int fd, void *buf, size_t count);
-ST_FUNC void *load_data(int fd, unsigned long file_offset, unsigned long size);
-ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h);
-ST_FUNC int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
-ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte);
-ST_FUNC void add_array(TCCState *s1, const char *sec, int c);
-
-ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc);
-ST_FUNC addr_t get_sym_addr(TCCState *s, const char *name, int err, int forc);
-ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,
- void (*symbol_cb)(void *ctx, const char *name, const void *val));
-ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs);
-
-/* Browse each elem of type <type> in section <sec> starting at elem <startoff>
- using variable <elem> */
-#define for_each_elem(sec, startoff, elem, type) \
- for (elem = (type *) sec->data + startoff; \
- elem < (type *) (sec->data + sec->data_offset); elem++)
-
-#ifndef ELF_OBJ_ONLY
-ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level);
-ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd);
-#endif
-#ifndef TCC_TARGET_PE
-ST_FUNC void tcc_add_runtime(TCCState *s1);
-#endif
-
-/* ------------ xxx-link.c ------------ */
-
-#if !defined ELF_OBJ_ONLY || defined TCC_TARGET_MACHO
-ST_FUNC int code_reloc (int reloc_type);
-ST_FUNC int gotplt_entry_type (int reloc_type);
-/* Whether to generate a GOT/PLT entry and when. NO_GOTPLT_ENTRY is first so
- that unknown relocation don't create a GOT or PLT entry */
-enum gotplt_entry {
- NO_GOTPLT_ENTRY, /* never generate (eg. GLOB_DAT & JMP_SLOT relocs) */
- BUILD_GOT_ONLY, /* only build GOT (eg. TPOFF relocs) */
- AUTO_GOTPLT_ENTRY, /* generate if sym is UNDEF */
- ALWAYS_GOTPLT_ENTRY /* always generate (eg. PLTOFF relocs) */
-};
-#define NEED_RELOC_TYPE
-
-#if !defined TCC_TARGET_MACHO || defined TCC_IS_NATIVE
-ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr);
-ST_FUNC void relocate_plt(TCCState *s1);
-ST_FUNC void build_got_entries(TCCState *s1, int got_sym); /* in tccelf.c */
-#define NEED_BUILD_GOT
-
-#endif
-#endif
-
-ST_FUNC void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val);
-
-/* ------------ xxx-gen.c ------------ */
-ST_DATA const char * const target_machine_defs;
-ST_DATA const int reg_classes[NB_REGS];
-
-ST_FUNC void gsym_addr(int t, int a);
-ST_FUNC void gsym(int t);
-ST_FUNC void load(int r, SValue *sv);
-ST_FUNC void store(int r, SValue *v);
-ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *align, int *regsize);
-ST_FUNC void gfunc_call(int nb_args);
-ST_FUNC void gfunc_prolog(Sym *func_sym);
-ST_FUNC void gfunc_epilog(void);
-ST_FUNC void gen_fill_nops(int);
-ST_FUNC int gjmp(int t);
-ST_FUNC void gjmp_addr(int a);
-ST_FUNC int gjmp_cond(int op, int t);
-ST_FUNC int gjmp_append(int n, int t);
-ST_FUNC void gen_opi(int op);
-ST_FUNC void gen_opf(int op);
-ST_FUNC void gen_cvt_ftoi(int t);
-ST_FUNC void gen_cvt_itof(int t);
-ST_FUNC void gen_cvt_ftof(int t);
-ST_FUNC void ggoto(void);
-#ifndef TCC_TARGET_C67
-ST_FUNC void o(unsigned int c);
-#endif
-ST_FUNC void gen_vla_sp_save(int addr);
-ST_FUNC void gen_vla_sp_restore(int addr);
-ST_FUNC void gen_vla_alloc(CType *type, int align);
-
-static inline uint16_t read16le(unsigned char *p) {
- return p[0] | (uint16_t)p[1] << 8;
-}
-static inline void write16le(unsigned char *p, uint16_t x) {
- p[0] = x & 255; p[1] = x >> 8 & 255;
-}
-static inline uint32_t read32le(unsigned char *p) {
- return read16le(p) | (uint32_t)read16le(p + 2) << 16;
-}
-static inline void write32le(unsigned char *p, uint32_t x) {
- write16le(p, x); write16le(p + 2, x >> 16);
-}
-static inline void add32le(unsigned char *p, int32_t x) {
- write32le(p, read32le(p) + x);
-}
-static inline uint64_t read64le(unsigned char *p) {
- return read32le(p) | (uint64_t)read32le(p + 4) << 32;
-}
-static inline void write64le(unsigned char *p, uint64_t x) {
- write32le(p, x); write32le(p + 4, x >> 32);
-}
-static inline void add64le(unsigned char *p, int64_t x) {
- write64le(p, read64le(p) + x);
-}
-
-/* ------------ i386-gen.c ------------ */
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM
-ST_FUNC void g(int c);
-ST_FUNC void gen_le16(int c);
-ST_FUNC void gen_le32(int c);
-#endif
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
-ST_FUNC void gen_addr32(int r, Sym *sym, int c);
-ST_FUNC void gen_addrpc32(int r, Sym *sym, int c);
-ST_FUNC void gen_cvt_csti(int t);
-ST_FUNC void gen_increment_tcov (SValue *sv);
-#endif
-
-/* ------------ x86_64-gen.c ------------ */
-#ifdef TCC_TARGET_X86_64
-ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c);
-ST_FUNC void gen_opl(int op);
-#ifdef TCC_TARGET_PE
-ST_FUNC void gen_vla_result(int addr);
-#endif
-ST_FUNC void gen_cvt_sxtw(void);
-ST_FUNC void gen_cvt_csti(int t);
-#endif
-
-/* ------------ arm-gen.c ------------ */
-#ifdef TCC_TARGET_ARM
-#if defined(TCC_ARM_EABI) && !defined(CONFIG_TCC_ELFINTERP)
-PUB_FUNC const char *default_elfinterp(struct TCCState *s);
-#endif
-ST_FUNC void arm_init(struct TCCState *s);
-ST_FUNC void gen_increment_tcov (SValue *sv);
-#endif
-
-/* ------------ arm64-gen.c ------------ */
-#ifdef TCC_TARGET_ARM64
-ST_FUNC void gen_opl(int op);
-ST_FUNC void gfunc_return(CType *func_type);
-ST_FUNC void gen_va_start(void);
-ST_FUNC void gen_va_arg(CType *t);
-ST_FUNC void gen_clear_cache(void);
-ST_FUNC void gen_cvt_sxtw(void);
-ST_FUNC void gen_cvt_csti(int t);
-ST_FUNC void gen_increment_tcov (SValue *sv);
-#endif
-
-/* ------------ riscv64-gen.c ------------ */
-#ifdef TCC_TARGET_RISCV64
-ST_FUNC void gen_opl(int op);
-//ST_FUNC void gfunc_return(CType *func_type);
-ST_FUNC void gen_va_start(void);
-ST_FUNC void arch_transfer_ret_regs(int);
-ST_FUNC void gen_cvt_sxtw(void);
-ST_FUNC void gen_increment_tcov (SValue *sv);
-#endif
-
-/* ------------ c67-gen.c ------------ */
-#ifdef TCC_TARGET_C67
-#endif
-
-/* ------------ tcccoff.c ------------ */
-#ifdef TCC_TARGET_COFF
-ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f);
-ST_FUNC int tcc_load_coff(TCCState * s1, int fd);
-#endif
-
-/* ------------ tccasm.c ------------ */
-ST_FUNC void asm_instr(void);
-ST_FUNC void asm_global_instr(void);
-ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess);
-#ifdef CONFIG_TCC_ASM
-ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
-ST_FUNC Sym* get_asm_sym(int name, Sym *csym);
-ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
-ST_FUNC int asm_int_expr(TCCState *s1);
-/* ------------ i386-asm.c ------------ */
-ST_FUNC void gen_expr32(ExprValue *pe);
-#ifdef TCC_TARGET_X86_64
-ST_FUNC void gen_expr64(ExprValue *pe);
-#endif
-ST_FUNC void asm_opcode(TCCState *s1, int opcode);
-ST_FUNC int asm_parse_regvar(int t);
-ST_FUNC void asm_compute_constraints(ASMOperand *operands, int nb_operands, int nb_outputs, const uint8_t *clobber_regs, int *pout_reg);
-ST_FUNC void subst_asm_operand(CString *add_str, SValue *sv, int modifier);
-ST_FUNC void asm_gen_code(ASMOperand *operands, int nb_operands, int nb_outputs, int is_output, uint8_t *clobber_regs, int out_reg);
-ST_FUNC void asm_clobber(uint8_t *clobber_regs, const char *str);
-#endif
-
-/* ------------ tccpe.c -------------- */
-#ifdef TCC_TARGET_PE
-ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename);
-ST_FUNC int pe_output_file(TCCState * s1, const char *filename);
-ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value);
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
-ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2);
-#endif
-#ifdef TCC_TARGET_X86_64
-ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack);
-#endif
-PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp);
-/* symbol properties stored in Elf32_Sym->st_other */
-# define ST_PE_EXPORT 0x10
-# define ST_PE_IMPORT 0x20
-# define ST_PE_STDCALL 0x40
-#endif
-#define ST_ASM_SET 0x04
-
-/* ------------ tccmacho.c ----------------- */
-#ifdef TCC_TARGET_MACHO
-ST_FUNC int macho_output_file(TCCState * s1, const char *filename);
-ST_FUNC int macho_load_dll(TCCState *s1, int fd, const char *filename, int lev);
-ST_FUNC int macho_load_tbd(TCCState *s1, int fd, const char *filename, int lev);
-#ifdef TCC_IS_NATIVE
-ST_FUNC void tcc_add_macos_sdkpath(TCCState* s);
-ST_FUNC const char* macho_tbd_soname(const char* filename);
-#endif
-#endif
-/* ------------ tccrun.c ----------------- */
-#ifdef TCC_IS_NATIVE
-#ifdef CONFIG_TCC_STATIC
-#define RTLD_LAZY 0x001
-#define RTLD_NOW 0x002
-#define RTLD_GLOBAL 0x100
-#define RTLD_DEFAULT NULL
-/* dummy function for profiling */
-ST_FUNC void *dlopen(const char *filename, int flag);
-ST_FUNC void dlclose(void *p);
-ST_FUNC const char *dlerror(void);
-ST_FUNC void *dlsym(void *handle, const char *symbol);
-#endif
-ST_FUNC void tcc_run_free(TCCState *s1);
-#endif
-
-/* ------------ tcctools.c ----------------- */
-#if 0 /* included in tcc.c */
-ST_FUNC int tcc_tool_ar(TCCState *s, int argc, char **argv);
-#ifdef TCC_TARGET_PE
-ST_FUNC int tcc_tool_impdef(TCCState *s, int argc, char **argv);
-#endif
-ST_FUNC int tcc_tool_cross(TCCState *s, char **argv, int option);
-ST_FUNC int gen_makedeps(TCCState *s, const char *target, const char *filename);
-#endif
-
-/* ------------ tccdbg.c ------------ */
-
-ST_FUNC void tcc_debug_new(TCCState *s);
-
-ST_FUNC void tcc_debug_start(TCCState *s1);
-ST_FUNC void tcc_debug_end(TCCState *s1);
-ST_FUNC void tcc_debug_bincl(TCCState *s1);
-ST_FUNC void tcc_debug_eincl(TCCState *s1);
-ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename);
-
-ST_FUNC void tcc_debug_line(TCCState *s1);
-ST_FUNC void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e);
-ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym);
-ST_FUNC void tcc_debug_prolog_epilog(TCCState *s1, int value);
-ST_FUNC void tcc_debug_funcend(TCCState *s1, int size);
-ST_FUNC void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind, int sym_type);
-ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym);
-ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value);
-ST_FUNC void tcc_debug_fix_anon(TCCState *s1, CType *t);
-
-ST_FUNC void tcc_tcov_start(TCCState *s1);
-ST_FUNC void tcc_tcov_end(TCCState *s1);
-ST_FUNC void tcc_tcov_check_line(TCCState *s1, int start);
-ST_FUNC void tcc_tcov_block_end(TCCState *s1, int line);
-ST_FUNC void tcc_tcov_block_begin(TCCState *s1);
-ST_FUNC void tcc_tcov_reset_ind(TCCState *s1);
-
-#define stab_section s1->stab_section
-#define stabstr_section stab_section->link
-#define tcov_section s1->tcov_section
-#define dwarf_info_section s1->dwarf_info_section
-#define dwarf_abbrev_section s1->dwarf_abbrev_section
-#define dwarf_line_section s1->dwarf_line_section
-#define dwarf_aranges_section s1->dwarf_aranges_section
-#define dwarf_str_section s1->dwarf_str_section
-#define dwarf_line_str_section s1->dwarf_line_str_section
-
-/* default dwarf version for "-g". use 0 to emit stab debug infos */
-#ifndef DWARF_VERSION
-# define DWARF_VERSION 0
-#endif
-
-/* default dwarf version for "-gdwarf" */
-#ifdef TCC_TARGET_MACHO
-# define DEFAULT_DWARF_VERSION 2
-#else
-# define DEFAULT_DWARF_VERSION 5
-#endif
-
-#if defined TCC_TARGET_PE
-# define R_DATA_32DW 'Z' /* fake code to avoid DLL relocs */
-#elif defined TCC_TARGET_X86_64
-# define R_DATA_32DW R_X86_64_32
-#else
-# define R_DATA_32DW R_DATA_32
-#endif
-
-/********************************************************/
-#if CONFIG_TCC_SEMLOCK
-#if defined _WIN32
-typedef struct { int init; CRITICAL_SECTION cr; } TCCSem;
-#elif defined __APPLE__
-#include <dispatch/dispatch.h>
-typedef struct { int init; dispatch_semaphore_t sem; } TCCSem;
-#else
-#include <semaphore.h>
-typedef struct { int init; sem_t sem; } TCCSem;
-#endif
-ST_FUNC void wait_sem(TCCSem *p);
-ST_FUNC void post_sem(TCCSem *p);
-#define TCC_SEM(s) TCCSem s
-#define WAIT_SEM wait_sem
-#define POST_SEM post_sem
-#else
-#define TCC_SEM(s)
-#define WAIT_SEM(p)
-#define POST_SEM(p)
-#endif
-
-/********************************************************/
-#undef ST_DATA
-#if ONE_SOURCE
-#define ST_DATA static
-#else
-#define ST_DATA
-#endif
-/********************************************************/
-
-#define text_section TCC_STATE_VAR(text_section)
-#define data_section TCC_STATE_VAR(data_section)
-#define rodata_section TCC_STATE_VAR(rodata_section)
-#define bss_section TCC_STATE_VAR(bss_section)
-#define common_section TCC_STATE_VAR(common_section)
-#define cur_text_section TCC_STATE_VAR(cur_text_section)
-#define bounds_section TCC_STATE_VAR(bounds_section)
-#define lbounds_section TCC_STATE_VAR(lbounds_section)
-#define symtab_section TCC_STATE_VAR(symtab_section)
-#define gnu_ext TCC_STATE_VAR(gnu_ext)
-#define tcc_error_noabort TCC_SET_STATE(_tcc_error_noabort)
-#define tcc_error TCC_SET_STATE(_tcc_error)
-#define tcc_warning TCC_SET_STATE(_tcc_warning)
-
-#define total_idents TCC_STATE_VAR(total_idents)
-#define total_lines TCC_STATE_VAR(total_lines)
-#define total_bytes TCC_STATE_VAR(total_bytes)
-
-PUB_FUNC void tcc_enter_state(TCCState *s1);
-PUB_FUNC void tcc_exit_state(TCCState *s1);
-
-/* conditional warning depending on switch */
-#define tcc_warning_c(sw) TCC_SET_STATE((\
- tcc_state->warn_num = offsetof(TCCState, sw) \
- - offsetof(TCCState, warn_none), _tcc_warning))
-
-/********************************************************/
-#endif /* _TCC_H */
-
-#undef TCC_STATE_VAR
-#undef TCC_SET_STATE
-
-#ifdef USING_GLOBALS
-# define TCC_STATE_VAR(sym) tcc_state->sym
-# define TCC_SET_STATE(fn) fn
-# undef USING_GLOBALS
-# undef _tcc_error
-#else
-# define TCC_STATE_VAR(sym) s1->sym
-# define TCC_SET_STATE(fn) (tcc_enter_state(s1),fn)
-# define _tcc_error use_tcc_error_noabort
-#endif
diff --git a/tinycc/tccasm.c b/tinycc/tccasm.c
deleted file mode 100644
index fcae05e..0000000
--- a/tinycc/tccasm.c
+++ /dev/null
@@ -1,1363 +0,0 @@
-/*
- * GAS like assembler for TCC
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define USING_GLOBALS
-#include "tcc.h"
-#ifdef CONFIG_TCC_ASM
-
-static Section *last_text_section; /* to handle .previous asm directive */
-static int asmgoto_n;
-
-static int asm_get_prefix_name(TCCState *s1, const char *prefix, unsigned int n)
-{
- char buf[64];
- snprintf(buf, sizeof(buf), "%s%u", prefix, n);
- return tok_alloc_const(buf);
-}
-
-ST_FUNC int asm_get_local_label_name(TCCState *s1, unsigned int n)
-{
- return asm_get_prefix_name(s1, "L..", n);
-}
-
-static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global);
-static Sym* asm_new_label(TCCState *s1, int label, int is_local);
-static Sym* asm_new_label1(TCCState *s1, int label, int is_local, int sh_num, int value);
-
-/* If a C name has an _ prepended then only asm labels that start
- with _ are representable in C, by removing the first _. ASM names
- without _ at the beginning don't correspond to C names, but we use
- the global C symbol table to track ASM names as well, so we need to
- transform those into ones that don't conflict with a C name,
- so prepend a '.' for them, but force the ELF asm name to be set. */
-static int asm2cname(int v, int *addeddot)
-{
- const char *name;
- *addeddot = 0;
- if (!tcc_state->leading_underscore)
- return v;
- name = get_tok_str(v, NULL);
- if (!name)
- return v;
- if (name[0] == '_') {
- v = tok_alloc_const(name + 1);
- } else if (!strchr(name, '.')) {
- char newname[256];
- snprintf(newname, sizeof newname, ".%s", name);
- v = tok_alloc_const(newname);
- *addeddot = 1;
- }
- return v;
-}
-
-static Sym *asm_label_find(int v)
-{
- Sym *sym;
- int addeddot;
- v = asm2cname(v, &addeddot);
- sym = sym_find(v);
- while (sym && sym->sym_scope && !(sym->type.t & VT_STATIC))
- sym = sym->prev_tok;
- return sym;
-}
-
-static Sym *asm_label_push(int v)
-{
- int addeddot, v2 = asm2cname(v, &addeddot);
- /* We always add VT_EXTERN, for sym definition that's tentative
- (for .set, removed for real defs), for mere references it's correct
- as is. */
- Sym *sym = global_identifier_push(v2, VT_ASM | VT_EXTERN | VT_STATIC, 0);
- if (addeddot)
- sym->asm_label = v;
- return sym;
-}
-
-/* Return a symbol we can use inside the assembler, having name NAME.
- Symbols from asm and C source share a namespace. If we generate
- an asm symbol it's also a (file-global) C symbol, but it's
- either not accessible by name (like "L.123"), or its type information
- is such that it's not usable without a proper C declaration.
-
- Sometimes we need symbols accessible by name from asm, which
- are anonymous in C, in this case CSYM can be used to transfer
- all information from that symbol to the (possibly newly created)
- asm symbol. */
-ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
-{
- Sym *sym = asm_label_find(name);
- if (!sym) {
- sym = asm_label_push(name);
- if (csym)
- sym->c = csym->c;
- }
- return sym;
-}
-
-static Sym* asm_section_sym(TCCState *s1, Section *sec)
-{
- char buf[100]; int label; Sym *sym;
- snprintf(buf, sizeof buf, "L.%s", sec->name);
- label = tok_alloc_const(buf);
- sym = asm_label_find(label);
- return sym ? sym : asm_new_label1(s1, label, 1, sec->sh_num, 0);
-}
-
-/* We do not use the C expression parser to handle symbols. Maybe the
- C expression parser could be tweaked to do so. */
-
-static void asm_expr_unary(TCCState *s1, ExprValue *pe)
-{
- Sym *sym;
- int op, label;
- uint64_t n;
- const char *p;
-
- switch(tok) {
- case TOK_PPNUM:
- p = tokc.str.data;
- n = strtoull(p, (char **)&p, 0);
- if (*p == 'b' || *p == 'f') {
- /* backward or forward label */
- label = asm_get_local_label_name(s1, n);
- sym = asm_label_find(label);
- if (*p == 'b') {
- /* backward : find the last corresponding defined label */
- if (sym && (!sym->c || elfsym(sym)->st_shndx == SHN_UNDEF))
- sym = sym->prev_tok;
- if (!sym)
- tcc_error("local label '%d' not found backward", (int)n);
- } else {
- /* forward */
- if (!sym || (sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)) {
- /* if the last label is defined, then define a new one */
- sym = asm_label_push(label);
- }
- }
- pe->v = 0;
- pe->sym = sym;
- pe->pcrel = 0;
- } else if (*p == '\0') {
- pe->v = n;
- pe->sym = NULL;
- pe->pcrel = 0;
- } else {
- tcc_error("invalid number syntax");
- }
- next();
- break;
- case '+':
- next();
- asm_expr_unary(s1, pe);
- break;
- case '-':
- case '~':
- op = tok;
- next();
- asm_expr_unary(s1, pe);
- if (pe->sym)
- tcc_error("invalid operation with label");
- if (op == '-')
- pe->v = -pe->v;
- else
- pe->v = ~pe->v;
- break;
- case TOK_CCHAR:
- case TOK_LCHAR:
- pe->v = tokc.i;
- pe->sym = NULL;
- pe->pcrel = 0;
- next();
- break;
- case '(':
- next();
- asm_expr(s1, pe);
- skip(')');
- break;
- case '.':
- pe->v = ind;
- pe->sym = asm_section_sym(s1, cur_text_section);
- pe->pcrel = 0;
- next();
- break;
- default:
- if (tok >= TOK_IDENT) {
- ElfSym *esym;
- /* label case : if the label was not found, add one */
- sym = get_asm_sym(tok, NULL);
- esym = elfsym(sym);
- if (esym && esym->st_shndx == SHN_ABS) {
- /* if absolute symbol, no need to put a symbol value */
- pe->v = esym->st_value;
- pe->sym = NULL;
- pe->pcrel = 0;
- } else {
- pe->v = 0;
- pe->sym = sym;
- pe->pcrel = 0;
- }
- next();
- } else {
- tcc_error("bad expression syntax [%s]", get_tok_str(tok, &tokc));
- }
- break;
- }
-}
-
-static void asm_expr_prod(TCCState *s1, ExprValue *pe)
-{
- int op;
- ExprValue e2;
-
- asm_expr_unary(s1, pe);
- for(;;) {
- op = tok;
- if (op != '*' && op != '/' && op != '%' &&
- op != TOK_SHL && op != TOK_SAR)
- break;
- next();
- asm_expr_unary(s1, &e2);
- if (pe->sym || e2.sym)
- tcc_error("invalid operation with label");
- switch(op) {
- case '*':
- pe->v *= e2.v;
- break;
- case '/':
- if (e2.v == 0) {
- div_error:
- tcc_error("division by zero");
- }
- pe->v /= e2.v;
- break;
- case '%':
- if (e2.v == 0)
- goto div_error;
- pe->v %= e2.v;
- break;
- case TOK_SHL:
- pe->v <<= e2.v;
- break;
- default:
- case TOK_SAR:
- pe->v >>= e2.v;
- break;
- }
- }
-}
-
-static void asm_expr_logic(TCCState *s1, ExprValue *pe)
-{
- int op;
- ExprValue e2;
-
- asm_expr_prod(s1, pe);
- for(;;) {
- op = tok;
- if (op != '&' && op != '|' && op != '^')
- break;
- next();
- asm_expr_prod(s1, &e2);
- if (pe->sym || e2.sym)
- tcc_error("invalid operation with label");
- switch(op) {
- case '&':
- pe->v &= e2.v;
- break;
- case '|':
- pe->v |= e2.v;
- break;
- default:
- case '^':
- pe->v ^= e2.v;
- break;
- }
- }
-}
-
-static inline void asm_expr_sum(TCCState *s1, ExprValue *pe)
-{
- int op;
- ExprValue e2;
-
- asm_expr_logic(s1, pe);
- for(;;) {
- op = tok;
- if (op != '+' && op != '-')
- break;
- next();
- asm_expr_logic(s1, &e2);
- if (op == '+') {
- if (pe->sym != NULL && e2.sym != NULL)
- goto cannot_relocate;
- pe->v += e2.v;
- if (pe->sym == NULL && e2.sym != NULL)
- pe->sym = e2.sym;
- } else {
- pe->v -= e2.v;
- /* NOTE: we are less powerful than gas in that case
- because we store only one symbol in the expression */
- if (!e2.sym) {
- /* OK */
- } else if (pe->sym == e2.sym) {
- /* OK */
- pe->sym = NULL; /* same symbols can be subtracted to NULL */
- } else {
- ElfSym *esym1, *esym2;
- esym1 = elfsym(pe->sym);
- esym2 = elfsym(e2.sym);
- if (esym1 && esym1->st_shndx == esym2->st_shndx
- && esym1->st_shndx != SHN_UNDEF) {
- /* we also accept defined symbols in the same section */
- pe->v += esym1->st_value - esym2->st_value;
- pe->sym = NULL;
- } else if (esym2->st_shndx == cur_text_section->sh_num) {
- /* When subtracting a defined symbol in current section
- this actually makes the value PC-relative. */
- pe->v -= esym2->st_value - ind - 4;
- pe->pcrel = 1;
- e2.sym = NULL;
- } else {
-cannot_relocate:
- tcc_error("invalid operation with label");
- }
- }
- }
- }
-}
-
-static inline void asm_expr_cmp(TCCState *s1, ExprValue *pe)
-{
- int op;
- ExprValue e2;
-
- asm_expr_sum(s1, pe);
- for(;;) {
- op = tok;
- if (op != TOK_EQ && op != TOK_NE
- && (op > TOK_GT || op < TOK_ULE))
- break;
- next();
- asm_expr_sum(s1, &e2);
- if (pe->sym || e2.sym)
- tcc_error("invalid operation with label");
- switch(op) {
- case TOK_EQ:
- pe->v = pe->v == e2.v;
- break;
- case TOK_NE:
- pe->v = pe->v != e2.v;
- break;
- case TOK_LT:
- pe->v = (int64_t)pe->v < (int64_t)e2.v;
- break;
- case TOK_GE:
- pe->v = (int64_t)pe->v >= (int64_t)e2.v;
- break;
- case TOK_LE:
- pe->v = (int64_t)pe->v <= (int64_t)e2.v;
- break;
- case TOK_GT:
- pe->v = (int64_t)pe->v > (int64_t)e2.v;
- break;
- default:
- break;
- }
- /* GAS compare results are -1/0 not 1/0. */
- pe->v = -(int64_t)pe->v;
- }
-}
-
-ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe)
-{
- asm_expr_cmp(s1, pe);
-}
-
-ST_FUNC int asm_int_expr(TCCState *s1)
-{
- ExprValue e;
- asm_expr(s1, &e);
- if (e.sym)
- expect("constant");
- return e.v;
-}
-
-static Sym* asm_new_label1(TCCState *s1, int label, int is_local,
- int sh_num, int value)
-{
- Sym *sym;
- ElfSym *esym;
-
- sym = asm_label_find(label);
- if (sym) {
- esym = elfsym(sym);
- /* A VT_EXTERN symbol, even if it has a section is considered
- overridable. This is how we "define" .set targets. Real
- definitions won't have VT_EXTERN set. */
- if (esym && esym->st_shndx != SHN_UNDEF) {
- /* the label is already defined */
- if (IS_ASM_SYM(sym)
- && (is_local == 1 || (sym->type.t & VT_EXTERN)))
- goto new_label;
- if (!(sym->type.t & VT_EXTERN))
- tcc_error("assembler label '%s' already defined",
- get_tok_str(label, NULL));
- }
- } else {
- new_label:
- sym = asm_label_push(label);
- }
- if (!sym->c)
- put_extern_sym2(sym, SHN_UNDEF, 0, 0, 1);
- esym = elfsym(sym);
- esym->st_shndx = sh_num;
- esym->st_value = value;
- if (is_local != 2)
- sym->type.t &= ~VT_EXTERN;
- return sym;
-}
-
-static Sym* asm_new_label(TCCState *s1, int label, int is_local)
-{
- return asm_new_label1(s1, label, is_local, cur_text_section->sh_num, ind);
-}
-
-/* Set the value of LABEL to that of some expression (possibly
- involving other symbols). LABEL can be overwritten later still. */
-static Sym* set_symbol(TCCState *s1, int label)
-{
- long n;
- ExprValue e;
- Sym *sym;
- ElfSym *esym;
- next();
- asm_expr(s1, &e);
- n = e.v;
- esym = elfsym(e.sym);
- if (esym)
- n += esym->st_value;
- sym = asm_new_label1(s1, label, 2, esym ? esym->st_shndx : SHN_ABS, n);
- elfsym(sym)->st_other |= ST_ASM_SET;
- return sym;
-}
-
-static void use_section1(TCCState *s1, Section *sec)
-{
- cur_text_section->data_offset = ind;
- cur_text_section = sec;
- ind = cur_text_section->data_offset;
-}
-
-static void use_section(TCCState *s1, const char *name)
-{
- Section *sec;
- sec = find_section(s1, name);
- use_section1(s1, sec);
-}
-
-static void push_section(TCCState *s1, const char *name)
-{
- Section *sec = find_section(s1, name);
- sec->prev = cur_text_section;
- use_section1(s1, sec);
-}
-
-static void pop_section(TCCState *s1)
-{
- Section *prev = cur_text_section->prev;
- if (!prev)
- tcc_error(".popsection without .pushsection");
- cur_text_section->prev = NULL;
- use_section1(s1, prev);
-}
-
-static void asm_parse_directive(TCCState *s1, int global)
-{
- int n, offset, v, size, tok1;
- Section *sec;
- uint8_t *ptr;
-
- /* assembler directive */
- sec = cur_text_section;
- switch(tok) {
- case TOK_ASMDIR_align:
- case TOK_ASMDIR_balign:
- case TOK_ASMDIR_p2align:
- case TOK_ASMDIR_skip:
- case TOK_ASMDIR_space:
- tok1 = tok;
- next();
- n = asm_int_expr(s1);
- if (tok1 == TOK_ASMDIR_p2align)
- {
- if (n < 0 || n > 30)
- tcc_error("invalid p2align, must be between 0 and 30");
- n = 1 << n;
- tok1 = TOK_ASMDIR_align;
- }
- if (tok1 == TOK_ASMDIR_align || tok1 == TOK_ASMDIR_balign) {
- if (n < 0 || (n & (n-1)) != 0)
- tcc_error("alignment must be a positive power of two");
- offset = (ind + n - 1) & -n;
- size = offset - ind;
- /* the section must have a compatible alignment */
- if (sec->sh_addralign < n)
- sec->sh_addralign = n;
- } else {
- if (n < 0)
- n = 0;
- size = n;
- }
- v = 0;
- if (tok == ',') {
- next();
- v = asm_int_expr(s1);
- }
- zero_pad:
- if (sec->sh_type != SHT_NOBITS) {
- sec->data_offset = ind;
- ptr = section_ptr_add(sec, size);
- memset(ptr, v, size);
- }
- ind += size;
- break;
- case TOK_ASMDIR_quad:
-#ifdef TCC_TARGET_X86_64
- size = 8;
- goto asm_data;
-#else
- next();
- for(;;) {
- uint64_t vl;
- const char *p;
-
- p = tokc.str.data;
- if (tok != TOK_PPNUM) {
- error_constant:
- tcc_error("64 bit constant");
- }
- vl = strtoll(p, (char **)&p, 0);
- if (*p != '\0')
- goto error_constant;
- next();
- if (sec->sh_type != SHT_NOBITS) {
- /* XXX: endianness */
- gen_le32(vl);
- gen_le32(vl >> 32);
- } else {
- ind += 8;
- }
- if (tok != ',')
- break;
- next();
- }
- break;
-#endif
- case TOK_ASMDIR_byte:
- size = 1;
- goto asm_data;
- case TOK_ASMDIR_word:
- case TOK_ASMDIR_short:
- size = 2;
- goto asm_data;
- case TOK_ASMDIR_long:
- case TOK_ASMDIR_int:
- size = 4;
- asm_data:
- next();
- for(;;) {
- ExprValue e;
- asm_expr(s1, &e);
- if (sec->sh_type != SHT_NOBITS) {
- if (size == 4) {
- gen_expr32(&e);
-#ifdef TCC_TARGET_X86_64
- } else if (size == 8) {
- gen_expr64(&e);
-#endif
- } else {
- if (e.sym)
- expect("constant");
- if (size == 1)
- g(e.v);
- else
- gen_le16(e.v);
- }
- } else {
- ind += size;
- }
- if (tok != ',')
- break;
- next();
- }
- break;
- case TOK_ASMDIR_fill:
- {
- int repeat, size, val, i, j;
- uint8_t repeat_buf[8];
- next();
- repeat = asm_int_expr(s1);
- if (repeat < 0) {
- tcc_error("repeat < 0; .fill ignored");
- break;
- }
- size = 1;
- val = 0;
- if (tok == ',') {
- next();
- size = asm_int_expr(s1);
- if (size < 0) {
- tcc_error("size < 0; .fill ignored");
- break;
- }
- if (size > 8)
- size = 8;
- if (tok == ',') {
- next();
- val = asm_int_expr(s1);
- }
- }
- /* XXX: endianness */
- repeat_buf[0] = val;
- repeat_buf[1] = val >> 8;
- repeat_buf[2] = val >> 16;
- repeat_buf[3] = val >> 24;
- repeat_buf[4] = 0;
- repeat_buf[5] = 0;
- repeat_buf[6] = 0;
- repeat_buf[7] = 0;
- for(i = 0; i < repeat; i++) {
- for(j = 0; j < size; j++) {
- g(repeat_buf[j]);
- }
- }
- }
- break;
- case TOK_ASMDIR_rept:
- {
- int repeat;
- TokenString *init_str;
- next();
- repeat = asm_int_expr(s1);
- init_str = tok_str_alloc();
- while (next(), tok != TOK_ASMDIR_endr) {
- if (tok == CH_EOF)
- tcc_error("we at end of file, .endr not found");
- tok_str_add_tok(init_str);
- }
- tok_str_add(init_str, -1);
- tok_str_add(init_str, 0);
- begin_macro(init_str, 1);
- while (repeat-- > 0) {
- tcc_assemble_internal(s1, (parse_flags & PARSE_FLAG_PREPROCESS),
- global);
- macro_ptr = init_str->str;
- }
- end_macro();
- next();
- break;
- }
- case TOK_ASMDIR_org:
- {
- unsigned long n;
- ExprValue e;
- ElfSym *esym;
- next();
- asm_expr(s1, &e);
- n = e.v;
- esym = elfsym(e.sym);
- if (esym) {
- if (esym->st_shndx != cur_text_section->sh_num)
- expect("constant or same-section symbol");
- n += esym->st_value;
- }
- if (n < ind)
- tcc_error("attempt to .org backwards");
- v = 0;
- size = n - ind;
- goto zero_pad;
- }
- break;
- case TOK_ASMDIR_set:
- next();
- tok1 = tok;
- next();
- /* Also accept '.set stuff', but don't do anything with this.
- It's used in GAS to set various features like '.set mips16'. */
- if (tok == ',')
- set_symbol(s1, tok1);
- break;
- case TOK_ASMDIR_globl:
- case TOK_ASMDIR_global:
- case TOK_ASMDIR_weak:
- case TOK_ASMDIR_hidden:
- tok1 = tok;
- do {
- Sym *sym;
- next();
- sym = get_asm_sym(tok, NULL);
- if (tok1 != TOK_ASMDIR_hidden)
- sym->type.t &= ~VT_STATIC;
- if (tok1 == TOK_ASMDIR_weak)
- sym->a.weak = 1;
- else if (tok1 == TOK_ASMDIR_hidden)
- sym->a.visibility = STV_HIDDEN;
- update_storage(sym);
- next();
- } while (tok == ',');
- break;
- case TOK_ASMDIR_string:
- case TOK_ASMDIR_ascii:
- case TOK_ASMDIR_asciz:
- {
- const uint8_t *p;
- int i, size, t;
-
- t = tok;
- next();
- for(;;) {
- if (tok != TOK_STR)
- expect("string constant");
- p = tokc.str.data;
- size = tokc.str.size;
- if (t == TOK_ASMDIR_ascii && size > 0)
- size--;
- for(i = 0; i < size; i++)
- g(p[i]);
- next();
- if (tok == ',') {
- next();
- } else if (tok != TOK_STR) {
- break;
- }
- }
- }
- break;
- case TOK_ASMDIR_text:
- case TOK_ASMDIR_data:
- case TOK_ASMDIR_bss:
- {
- char sname[64];
- tok1 = tok;
- n = 0;
- next();
- if (tok != ';' && tok != TOK_LINEFEED) {
- n = asm_int_expr(s1);
- next();
- }
- if (n)
- sprintf(sname, "%s%d", get_tok_str(tok1, NULL), n);
- else
- sprintf(sname, "%s", get_tok_str(tok1, NULL));
- use_section(s1, sname);
- }
- break;
- case TOK_ASMDIR_file:
- {
- char filename[512];
-
- filename[0] = '\0';
- next();
- if (tok == TOK_STR)
- pstrcat(filename, sizeof(filename), tokc.str.data);
- else
- pstrcat(filename, sizeof(filename), get_tok_str(tok, NULL));
- tcc_warning_c(warn_unsupported)("ignoring .file %s", filename);
- next();
- }
- break;
- case TOK_ASMDIR_ident:
- {
- char ident[256];
-
- ident[0] = '\0';
- next();
- if (tok == TOK_STR)
- pstrcat(ident, sizeof(ident), tokc.str.data);
- else
- pstrcat(ident, sizeof(ident), get_tok_str(tok, NULL));
- tcc_warning_c(warn_unsupported)("ignoring .ident %s", ident);
- next();
- }
- break;
- case TOK_ASMDIR_size:
- {
- Sym *sym;
-
- next();
- sym = asm_label_find(tok);
- if (!sym) {
- tcc_error("label not found: %s", get_tok_str(tok, NULL));
- }
- /* XXX .size name,label2-label1 */
- tcc_warning_c(warn_unsupported)("ignoring .size %s,*", get_tok_str(tok, NULL));
- next();
- skip(',');
- while (tok != TOK_LINEFEED && tok != ';' && tok != CH_EOF) {
- next();
- }
- }
- break;
- case TOK_ASMDIR_type:
- {
- Sym *sym;
- const char *newtype;
-
- next();
- sym = get_asm_sym(tok, NULL);
- next();
- skip(',');
- if (tok == TOK_STR) {
- newtype = tokc.str.data;
- } else {
- if (tok == '@' || tok == '%')
- next();
- newtype = get_tok_str(tok, NULL);
- }
-
- if (!strcmp(newtype, "function") || !strcmp(newtype, "STT_FUNC")) {
- sym->type.t = (sym->type.t & ~VT_BTYPE) | VT_FUNC;
- } else
- tcc_warning_c(warn_unsupported)("change type of '%s' from 0x%x to '%s' ignored",
- get_tok_str(sym->v, NULL), sym->type.t, newtype);
-
- next();
- }
- break;
- case TOK_ASMDIR_pushsection:
- case TOK_ASMDIR_section:
- {
- char sname[256];
- int old_nb_section = s1->nb_sections;
-
- tok1 = tok;
- /* XXX: support more options */
- next();
- sname[0] = '\0';
- while (tok != ';' && tok != TOK_LINEFEED && tok != ',') {
- if (tok == TOK_STR)
- pstrcat(sname, sizeof(sname), tokc.str.data);
- else
- pstrcat(sname, sizeof(sname), get_tok_str(tok, NULL));
- next();
- }
- if (tok == ',') {
- /* skip section options */
- next();
- if (tok != TOK_STR)
- expect("string constant");
- next();
- if (tok == ',') {
- next();
- if (tok == '@' || tok == '%')
- next();
- next();
- }
- }
- last_text_section = cur_text_section;
- if (tok1 == TOK_ASMDIR_section)
- use_section(s1, sname);
- else
- push_section(s1, sname);
- /* If we just allocated a new section reset its alignment to
- 1. new_section normally acts for GCC compatibility and
- sets alignment to PTR_SIZE. The assembler behaves different. */
- if (old_nb_section != s1->nb_sections)
- cur_text_section->sh_addralign = 1;
- }
- break;
- case TOK_ASMDIR_previous:
- {
- Section *sec;
- next();
- if (!last_text_section)
- tcc_error("no previous section referenced");
- sec = cur_text_section;
- use_section1(s1, last_text_section);
- last_text_section = sec;
- }
- break;
- case TOK_ASMDIR_popsection:
- next();
- pop_section(s1);
- break;
-#ifdef TCC_TARGET_I386
- case TOK_ASMDIR_code16:
- {
- next();
- s1->seg_size = 16;
- }
- break;
- case TOK_ASMDIR_code32:
- {
- next();
- s1->seg_size = 32;
- }
- break;
-#endif
-#ifdef TCC_TARGET_X86_64
- /* added for compatibility with GAS */
- case TOK_ASMDIR_code64:
- next();
- break;
-#endif
- default:
- tcc_error("unknown assembler directive '.%s'", get_tok_str(tok, NULL));
- break;
- }
-}
-
-
-/* assemble a file */
-static int tcc_assemble_internal(TCCState *s1, int do_preprocess, int global)
-{
- int opcode;
- int saved_parse_flags = parse_flags;
-
- parse_flags = PARSE_FLAG_ASM_FILE | PARSE_FLAG_TOK_STR;
- if (do_preprocess)
- parse_flags |= PARSE_FLAG_PREPROCESS;
- for(;;) {
- next();
- if (tok == TOK_EOF)
- break;
- parse_flags |= PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
- redo:
- if (tok == '#') {
- /* horrible gas comment */
- while (tok != TOK_LINEFEED)
- next();
- } else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) {
- asm_parse_directive(s1, global);
- } else if (tok == TOK_PPNUM) {
- const char *p;
- int n;
- p = tokc.str.data;
- n = strtoul(p, (char **)&p, 10);
- if (*p != '\0')
- expect("':'");
- /* new local label */
- asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
- next();
- skip(':');
- goto redo;
- } else if (tok >= TOK_IDENT) {
- /* instruction or label */
- opcode = tok;
- next();
- if (tok == ':') {
- /* new label */
- asm_new_label(s1, opcode, 0);
- next();
- goto redo;
- } else if (tok == '=') {
- set_symbol(s1, opcode);
- goto redo;
- } else {
- asm_opcode(s1, opcode);
- }
- }
- /* end of line */
- if (tok != ';' && tok != TOK_LINEFEED)
- expect("end of line");
- parse_flags &= ~PARSE_FLAG_LINEFEED; /* XXX: suppress that hack */
- }
-
- parse_flags = saved_parse_flags;
- return 0;
-}
-
-/* Assemble the current file */
-ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
-{
- int ret;
- tcc_debug_start(s1);
- /* default section is text */
- cur_text_section = text_section;
- ind = cur_text_section->data_offset;
- nocode_wanted = 0;
- ret = tcc_assemble_internal(s1, do_preprocess, 1);
- cur_text_section->data_offset = ind;
- tcc_debug_end(s1);
- return ret;
-}
-
-/********************************************************************/
-/* GCC inline asm support */
-
-/* assemble the string 'str' in the current C compilation unit without
- C preprocessing. NOTE: str is modified by modifying the '\0' at the
- end */
-static void tcc_assemble_inline(TCCState *s1, char *str, int len, int global)
-{
- const int *saved_macro_ptr = macro_ptr;
- int dotid = set_idnum('.', IS_ID);
- int dolid = set_idnum('$', 0);
-
- tcc_open_bf(s1, ":asm:", len);
- memcpy(file->buffer, str, len);
- macro_ptr = NULL;
- tcc_assemble_internal(s1, 0, global);
- tcc_close();
-
- set_idnum('$', dolid);
- set_idnum('.', dotid);
- macro_ptr = saved_macro_ptr;
-}
-
-/* find a constraint by its number or id (gcc 3 extended
- syntax). return -1 if not found. Return in *pp in char after the
- constraint */
-ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands,
- const char *name, const char **pp)
-{
- int index;
- TokenSym *ts;
- const char *p;
-
- if (isnum(*name)) {
- index = 0;
- while (isnum(*name)) {
- index = (index * 10) + (*name) - '0';
- name++;
- }
- if ((unsigned)index >= nb_operands)
- index = -1;
- } else if (*name == '[') {
- name++;
- p = strchr(name, ']');
- if (p) {
- ts = tok_alloc(name, p - name);
- for(index = 0; index < nb_operands; index++) {
- if (operands[index].id == ts->tok)
- goto found;
- }
- index = -1;
- found:
- name = p + 1;
- } else {
- index = -1;
- }
- } else {
- index = -1;
- }
- if (pp)
- *pp = name;
- return index;
-}
-
-static void subst_asm_operands(ASMOperand *operands, int nb_operands,
- CString *out_str, const char *str)
-{
- int c, index, modifier;
- ASMOperand *op;
- SValue sv;
-
- for(;;) {
- c = *str++;
- if (c == '%') {
- if (*str == '%') {
- str++;
- goto add_char;
- }
- modifier = 0;
- if (*str == 'c' || *str == 'n' ||
- *str == 'b' || *str == 'w' || *str == 'h' || *str == 'k' ||
- *str == 'q' || *str == 'l' ||
- /* P in GCC would add "@PLT" to symbol refs in PIC mode,
- and make literal operands not be decorated with '$'. */
- *str == 'P')
- modifier = *str++;
- index = find_constraint(operands, nb_operands, str, &str);
- if (index < 0)
- tcc_error("invalid operand reference after %%");
- op = &operands[index];
- if (modifier == 'l') {
- cstr_cat(out_str, get_tok_str(op->is_label, NULL), -1);
- } else {
- sv = *op->vt;
- if (op->reg >= 0) {
- sv.r = op->reg;
- if ((op->vt->r & VT_VALMASK) == VT_LLOCAL && op->is_memory)
- sv.r |= VT_LVAL;
- }
- subst_asm_operand(out_str, &sv, modifier);
- }
- } else {
- add_char:
- cstr_ccat(out_str, c);
- if (c == '\0')
- break;
- }
- }
-}
-
-
-static void parse_asm_operands(ASMOperand *operands, int *nb_operands_ptr,
- int is_output)
-{
- ASMOperand *op;
- int nb_operands;
- char* astr;
-
- if (tok != ':') {
- nb_operands = *nb_operands_ptr;
- for(;;) {
- if (nb_operands >= MAX_ASM_OPERANDS)
- tcc_error("too many asm operands");
- op = &operands[nb_operands++];
- op->id = 0;
- if (tok == '[') {
- next();
- if (tok < TOK_IDENT)
- expect("identifier");
- op->id = tok;
- next();
- skip(']');
- }
- astr = parse_mult_str("string constant")->data;
- pstrcpy(op->constraint, sizeof op->constraint, astr);
- skip('(');
- gexpr();
- if (is_output) {
- if (!(vtop->type.t & VT_ARRAY))
- test_lvalue();
- } else {
- /* we want to avoid LLOCAL case, except when the 'm'
- constraint is used. Note that it may come from
- register storage, so we need to convert (reg)
- case */
- if ((vtop->r & VT_LVAL) &&
- ((vtop->r & VT_VALMASK) == VT_LLOCAL ||
- (vtop->r & VT_VALMASK) < VT_CONST) &&
- !strchr(op->constraint, 'm')) {
- gv(RC_INT);
- }
- }
- op->vt = vtop;
- skip(')');
- if (tok == ',') {
- next();
- } else {
- break;
- }
- }
- *nb_operands_ptr = nb_operands;
- }
-}
-
-/* parse the GCC asm() instruction */
-ST_FUNC void asm_instr(void)
-{
- CString astr, *astr1;
-
- ASMOperand operands[MAX_ASM_OPERANDS];
- int nb_outputs, nb_operands, i, must_subst, out_reg, nb_labels;
- uint8_t clobber_regs[NB_ASM_REGS];
- Section *sec;
-
- /* since we always generate the asm() instruction, we can ignore
- volatile */
- while (tok == TOK_VOLATILE1 || tok == TOK_VOLATILE2 || tok == TOK_VOLATILE3
- || tok == TOK_GOTO) {
- next();
- }
-
- astr1 = parse_asm_str();
- cstr_new_s(&astr);
- cstr_cat(&astr, astr1->data, astr1->size);
-
- nb_operands = 0;
- nb_outputs = 0;
- nb_labels = 0;
- must_subst = 0;
- memset(clobber_regs, 0, sizeof(clobber_regs));
- if (tok == ':') {
- next();
- must_subst = 1;
- /* output args */
- parse_asm_operands(operands, &nb_operands, 1);
- nb_outputs = nb_operands;
- if (tok == ':') {
- next();
- if (tok != ')') {
- /* input args */
- parse_asm_operands(operands, &nb_operands, 0);
- if (tok == ':') {
- /* clobber list */
- /* XXX: handle registers */
- next();
- for(;;) {
- if (tok == ':')
- break;
- if (tok != TOK_STR)
- expect("string constant");
- asm_clobber(clobber_regs, tokc.str.data);
- next();
- if (tok == ',') {
- next();
- } else {
- break;
- }
- }
- }
- if (tok == ':') {
- /* goto labels */
- next();
- for (;;) {
- Sym *csym;
- int asmname;
- if (nb_operands + nb_labels >= MAX_ASM_OPERANDS)
- tcc_error("too many asm operands");
- if (tok < TOK_UIDENT)
- expect("label identifier");
- operands[nb_operands + nb_labels++].id = tok;
-
- csym = label_find(tok);
- if (!csym) {
- csym = label_push(&global_label_stack, tok,
- LABEL_FORWARD);
- } else {
- if (csym->r == LABEL_DECLARED)
- csym->r = LABEL_FORWARD;
- }
- next();
- asmname = asm_get_prefix_name(tcc_state, "LG.",
- ++asmgoto_n);
- if (!csym->c)
- put_extern_sym2(csym, SHN_UNDEF, 0, 0, 1);
- get_asm_sym(asmname, csym);
- operands[nb_operands + nb_labels - 1].is_label = asmname;
-
- if (tok != ',')
- break;
- next();
- }
- }
- }
- }
- }
- skip(')');
- /* NOTE: we do not eat the ';' so that we can restore the current
- token after the assembler parsing */
- if (tok != ';')
- expect("';'");
-
- /* save all values in the memory */
- save_regs(0);
-
- /* compute constraints */
- asm_compute_constraints(operands, nb_operands, nb_outputs,
- clobber_regs, &out_reg);
-
- /* substitute the operands in the asm string. No substitution is
- done if no operands (GCC behaviour) */
-#ifdef ASM_DEBUG
- printf("asm: \"%s\"\n", (char *)astr.data);
-#endif
- if (must_subst) {
- cstr_reset(astr1);
- cstr_cat(astr1, astr.data, astr.size);
- cstr_reset(&astr);
- subst_asm_operands(operands, nb_operands + nb_labels, &astr, astr1->data);
- }
-
-#ifdef ASM_DEBUG
- printf("subst_asm: \"%s\"\n", (char *)astr.data);
-#endif
-
- /* generate loads */
- asm_gen_code(operands, nb_operands, nb_outputs, 0,
- clobber_regs, out_reg);
-
- /* We don't allow switching section within inline asm to
- bleed out to surrounding code. */
- sec = cur_text_section;
- /* assemble the string with tcc internal assembler */
- tcc_assemble_inline(tcc_state, astr.data, astr.size - 1, 0);
- cstr_free_s(&astr);
- if (sec != cur_text_section) {
- tcc_warning("inline asm tries to change current section");
- use_section1(tcc_state, sec);
- }
-
- /* restore the current C token */
- next();
-
- /* store the output values if needed */
- asm_gen_code(operands, nb_operands, nb_outputs, 1,
- clobber_regs, out_reg);
-
- /* free everything */
- for(i=0;i<nb_operands;i++) {
- vpop();
- }
-
-}
-
-ST_FUNC void asm_global_instr(void)
-{
- CString *astr;
- int saved_nocode_wanted = nocode_wanted;
-
- /* Global asm blocks are always emitted. */
- nocode_wanted = 0;
- next();
- astr = parse_asm_str();
- skip(')');
- /* NOTE: we do not eat the ';' so that we can restore the current
- token after the assembler parsing */
- if (tok != ';')
- expect("';'");
-
-#ifdef ASM_DEBUG
- printf("asm_global: \"%s\"\n", (char *)astr.data);
-#endif
- cur_text_section = text_section;
- ind = cur_text_section->data_offset;
-
- /* assemble the string with tcc internal assembler */
- tcc_assemble_inline(tcc_state, astr->data, astr->size - 1, 1);
-
- cur_text_section->data_offset = ind;
-
- /* restore the current C token */
- next();
-
- nocode_wanted = saved_nocode_wanted;
-}
-
-/********************************************************/
-#else
-ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
-{
- tcc_error("asm not supported");
-}
-
-ST_FUNC void asm_instr(void)
-{
- tcc_error("inline asm() not supported");
-}
-
-ST_FUNC void asm_global_instr(void)
-{
- tcc_error("inline asm() not supported");
-}
-#endif /* CONFIG_TCC_ASM */
diff --git a/tinycc/tcccoff.c b/tinycc/tcccoff.c
deleted file mode 100644
index 56064cd..0000000
--- a/tinycc/tcccoff.c
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
- * COFF file handling for TCC
- *
- * Copyright (c) 2003, 2004 TK
- * Copyright (c) 2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "tcc.h"
-
-/* XXX: this file uses tcc_error() to the effect of exit(1) */
-#undef _tcc_error
-
-#define MAXNSCNS 255 /* MAXIMUM NUMBER OF SECTIONS */
-#define MAX_STR_TABLE 1000000
-AOUTHDR o_filehdr; /* OPTIONAL (A.OUT) FILE HEADER */
-
-SCNHDR section_header[MAXNSCNS];
-
-#define MAX_FUNCS 1000
-#define MAX_FUNC_NAME_LENGTH 128
-
-int nFuncs;
-char Func[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
-char AssociatedFile[MAX_FUNCS][MAX_FUNC_NAME_LENGTH];
-int LineNoFilePtr[MAX_FUNCS];
-int EndAddress[MAX_FUNCS];
-int LastLineNo[MAX_FUNCS];
-int FuncEntries[MAX_FUNCS];
-
-int OutputTheSection(Section * sect);
-short int GetCoffFlags(const char *s);
-void SortSymbolTable(TCCState *s1);
-Section *FindSection(TCCState * s1, const char *sname);
-
-int C67_main_entry_point;
-
-int FindCoffSymbolIndex(TCCState * s1, const char *func_name);
-int nb_syms;
-
-typedef struct {
- long tag;
- long size;
- long fileptr;
- long nextsym;
- short int dummy;
-} AUXFUNC;
-
-typedef struct {
- long regmask;
- unsigned short lineno;
- unsigned short nentries;
- int localframe;
- int nextentry;
- short int dummy;
-} AUXBF;
-
-typedef struct {
- long dummy;
- unsigned short lineno;
- unsigned short dummy1;
- int dummy2;
- int dummy3;
- unsigned short dummy4;
-} AUXEF;
-
-ST_FUNC int tcc_output_coff(TCCState *s1, FILE *f)
-{
- Section *tcc_sect;
- SCNHDR *coff_sec;
- int file_pointer;
- char *Coff_str_table, *pCoff_str_table;
- int CoffTextSectionNo, coff_nb_syms;
- FILHDR file_hdr; /* FILE HEADER STRUCTURE */
- Section *stext, *sdata, *sbss;
- int i, NSectionsToOutput = 0;
-
- Coff_str_table = pCoff_str_table = NULL;
-
- stext = FindSection(s1, ".text");
- sdata = FindSection(s1, ".data");
- sbss = FindSection(s1, ".bss");
-
- nb_syms = symtab_section->data_offset / sizeof(Elf32_Sym);
- coff_nb_syms = FindCoffSymbolIndex(s1, "XXXXXXXXXX1");
-
- file_hdr.f_magic = COFF_C67_MAGIC; /* magic number */
- file_hdr.f_timdat = 0; /* time & date stamp */
- file_hdr.f_opthdr = sizeof(AOUTHDR); /* sizeof(optional hdr) */
- file_hdr.f_flags = 0x1143; /* flags (copied from what code composer does) */
- file_hdr.f_TargetID = 0x99; /* for C6x = 0x0099 */
-
- o_filehdr.magic = 0x0108; /* see magic.h */
- o_filehdr.vstamp = 0x0190; /* version stamp */
- o_filehdr.tsize = stext->data_offset; /* text size in bytes, padded to FW bdry */
- o_filehdr.dsize = sdata->data_offset; /* initialized data " " */
- o_filehdr.bsize = sbss->data_offset; /* uninitialized data " " */
- o_filehdr.entrypt = C67_main_entry_point; /* entry pt. */
- o_filehdr.text_start = stext->sh_addr; /* base of text used for this file */
- o_filehdr.data_start = sdata->sh_addr; /* base of data used for this file */
-
-
- // create all the section headers
-
- file_pointer = FILHSZ + sizeof(AOUTHDR);
-
- CoffTextSectionNo = -1;
-
- for (i = 1; i < s1->nb_sections; i++) {
- coff_sec = &section_header[i];
- tcc_sect = s1->sections[i];
-
- if (OutputTheSection(tcc_sect)) {
- NSectionsToOutput++;
-
- if (CoffTextSectionNo == -1 && tcc_sect == stext)
- CoffTextSectionNo = NSectionsToOutput; // rem which coff sect number the .text sect is
-
- strcpy(coff_sec->s_name, tcc_sect->name); /* section name */
-
- coff_sec->s_paddr = tcc_sect->sh_addr; /* physical address */
- coff_sec->s_vaddr = tcc_sect->sh_addr; /* virtual address */
- coff_sec->s_size = tcc_sect->data_offset; /* section size */
- coff_sec->s_scnptr = 0; /* file ptr to raw data for section */
- coff_sec->s_relptr = 0; /* file ptr to relocation */
- coff_sec->s_lnnoptr = 0; /* file ptr to line numbers */
- coff_sec->s_nreloc = 0; /* number of relocation entries */
- coff_sec->s_flags = GetCoffFlags(coff_sec->s_name); /* flags */
- coff_sec->s_reserved = 0; /* reserved byte */
- coff_sec->s_page = 0; /* memory page id */
-
- file_pointer += sizeof(SCNHDR);
- }
- }
-
- file_hdr.f_nscns = NSectionsToOutput; /* number of sections */
-
- // now loop through and determine file pointer locations
- // for the raw data
-
-
- for (i = 1; i < s1->nb_sections; i++) {
- coff_sec = &section_header[i];
- tcc_sect = s1->sections[i];
-
- if (OutputTheSection(tcc_sect)) {
- // put raw data
- coff_sec->s_scnptr = file_pointer; /* file ptr to raw data for section */
- file_pointer += coff_sec->s_size;
- }
- }
-
- // now loop through and determine file pointer locations
- // for the relocation data
-
- for (i = 1; i < s1->nb_sections; i++) {
- coff_sec = &section_header[i];
- tcc_sect = s1->sections[i];
-
- if (OutputTheSection(tcc_sect)) {
- // put relocations data
- if (coff_sec->s_nreloc > 0) {
- coff_sec->s_relptr = file_pointer; /* file ptr to relocation */
- file_pointer += coff_sec->s_nreloc * sizeof(struct reloc);
- }
- }
- }
-
- // now loop through and determine file pointer locations
- // for the line number data
-
- for (i = 1; i < s1->nb_sections; i++) {
- coff_sec = &section_header[i];
- tcc_sect = s1->sections[i];
-
- coff_sec->s_nlnno = 0;
- coff_sec->s_lnnoptr = 0;
-
- if (s1->do_debug && tcc_sect == stext) {
- // count how many line nos data
-
- // also find association between source file name and function
- // so we can sort the symbol table
-
-
- Stab_Sym *sym, *sym_end;
- char func_name[MAX_FUNC_NAME_LENGTH],
- last_func_name[MAX_FUNC_NAME_LENGTH];
- unsigned long func_addr, last_pc, pc;
- const char *incl_files[INCLUDE_STACK_SIZE];
- int incl_index, len, last_line_num;
- const char *str, *p;
-
- coff_sec->s_lnnoptr = file_pointer; /* file ptr to linno */
-
-
- func_name[0] = '\0';
- func_addr = 0;
- incl_index = 0;
- last_func_name[0] = '\0';
- last_pc = 0xffffffff;
- last_line_num = 1;
- sym = (Stab_Sym *) stab_section->data + 1;
- sym_end =
- (Stab_Sym *) (stab_section->data +
- stab_section->data_offset);
-
- nFuncs = 0;
- while (sym < sym_end) {
- switch (sym->n_type) {
- /* function start or end */
- case N_FUN:
- if (sym->n_strx == 0) {
- // end of function
-
- coff_sec->s_nlnno++;
- file_pointer += LINESZ;
-
- pc = sym->n_value + func_addr;
- func_name[0] = '\0';
- func_addr = 0;
- EndAddress[nFuncs] = pc;
- FuncEntries[nFuncs] =
- (file_pointer -
- LineNoFilePtr[nFuncs]) / LINESZ - 1;
- LastLineNo[nFuncs++] = last_line_num + 1;
- } else {
- // beginning of function
-
- LineNoFilePtr[nFuncs] = file_pointer;
- coff_sec->s_nlnno++;
- file_pointer += LINESZ;
-
- str =
- (const char *) stabstr_section->data +
- sym->n_strx;
-
- p = strchr(str, ':');
- if (!p) {
- pstrcpy(func_name, sizeof(func_name), str);
- pstrcpy(Func[nFuncs], sizeof(func_name), str);
- } else {
- len = p - str;
- if (len > sizeof(func_name) - 1)
- len = sizeof(func_name) - 1;
- memcpy(func_name, str, len);
- memcpy(Func[nFuncs], str, len);
- func_name[len] = '\0';
- }
-
- // save the file that it came in so we can sort later
- pstrcpy(AssociatedFile[nFuncs], sizeof(func_name),
- incl_files[incl_index - 1]);
-
- func_addr = sym->n_value;
- }
- break;
-
- /* line number info */
- case N_SLINE:
- pc = sym->n_value + func_addr;
-
- last_pc = pc;
- last_line_num = sym->n_desc;
-
- /* XXX: slow! */
- strcpy(last_func_name, func_name);
-
- coff_sec->s_nlnno++;
- file_pointer += LINESZ;
- break;
- /* include files */
- case N_BINCL:
- str =
- (const char *) stabstr_section->data + sym->n_strx;
- add_incl:
- if (incl_index < INCLUDE_STACK_SIZE) {
- incl_files[incl_index++] = str;
- }
- break;
- case N_EINCL:
- if (incl_index > 1)
- incl_index--;
- break;
- case N_SO:
- if (sym->n_strx == 0) {
- incl_index = 0; /* end of translation unit */
- } else {
- str =
- (const char *) stabstr_section->data +
- sym->n_strx;
- /* do not add path */
- len = strlen(str);
- if (len > 0 && str[len - 1] != '/')
- goto add_incl;
- }
- break;
- }
- sym++;
- }
- }
-
- }
-
- file_hdr.f_symptr = file_pointer; /* file pointer to symtab */
-
- if (s1->do_debug)
- file_hdr.f_nsyms = coff_nb_syms; /* number of symtab entries */
- else
- file_hdr.f_nsyms = 0;
-
- file_pointer += file_hdr.f_nsyms * SYMNMLEN;
-
- // OK now we are all set to write the file
-
-
- fwrite(&file_hdr, FILHSZ, 1, f);
- fwrite(&o_filehdr, sizeof(o_filehdr), 1, f);
-
- // write section headers
- for (i = 1; i < s1->nb_sections; i++) {
- coff_sec = &section_header[i];
- tcc_sect = s1->sections[i];
-
- if (OutputTheSection(tcc_sect)) {
- fwrite(coff_sec, sizeof(SCNHDR), 1, f);
- }
- }
-
- // write raw data
- for (i = 1; i < s1->nb_sections; i++) {
- coff_sec = &section_header[i];
- tcc_sect = s1->sections[i];
-
- if (OutputTheSection(tcc_sect)) {
- fwrite(tcc_sect->data, tcc_sect->data_offset, 1, f);
- }
- }
-
- // write relocation data
- for (i = 1; i < s1->nb_sections; i++) {
- coff_sec = &section_header[i];
- tcc_sect = s1->sections[i];
-
- if (OutputTheSection(tcc_sect)) {
- // put relocations data
- if (coff_sec->s_nreloc > 0) {
- fwrite(tcc_sect->reloc,
- coff_sec->s_nreloc * sizeof(struct reloc), 1, f);
- }
- }
- }
-
-
- // group the symbols in order of filename, func1, func2, etc
- // finally global symbols
-
- if (s1->do_debug)
- SortSymbolTable(s1);
-
- // write line no data
-
- for (i = 1; i < s1->nb_sections; i++) {
- coff_sec = &section_header[i];
- tcc_sect = s1->sections[i];
-
- if (s1->do_debug && tcc_sect == stext) {
- // count how many line nos data
-
-
- Stab_Sym *sym, *sym_end;
- char func_name[128], last_func_name[128];
- unsigned long func_addr, last_pc, pc;
- const char *incl_files[INCLUDE_STACK_SIZE];
- int incl_index, len, last_line_num;
- const char *str, *p;
-
- LINENO CoffLineNo;
-
- func_name[0] = '\0';
- func_addr = 0;
- incl_index = 0;
- last_func_name[0] = '\0';
- last_pc = 0;
- last_line_num = 1;
- sym = (Stab_Sym *) stab_section->data + 1;
- sym_end =
- (Stab_Sym *) (stab_section->data +
- stab_section->data_offset);
-
- while (sym < sym_end) {
- switch (sym->n_type) {
- /* function start or end */
- case N_FUN:
- if (sym->n_strx == 0) {
- // end of function
-
- CoffLineNo.l_addr.l_paddr = last_pc;
- CoffLineNo.l_lnno = last_line_num + 1;
- fwrite(&CoffLineNo, 6, 1, f);
-
- pc = sym->n_value + func_addr;
- func_name[0] = '\0';
- func_addr = 0;
- } else {
- // beginning of function
-
- str =
- (const char *) stabstr_section->data +
- sym->n_strx;
-
-
- p = strchr(str, ':');
- if (!p) {
- pstrcpy(func_name, sizeof(func_name), str);
- } else {
- len = p - str;
- if (len > sizeof(func_name) - 1)
- len = sizeof(func_name) - 1;
- memcpy(func_name, str, len);
- func_name[len] = '\0';
- }
- func_addr = sym->n_value;
- last_pc = func_addr;
- last_line_num = -1;
-
- // output a function begin
-
- CoffLineNo.l_addr.l_symndx =
- FindCoffSymbolIndex(s1, func_name);
- CoffLineNo.l_lnno = 0;
-
- fwrite(&CoffLineNo, 6, 1, f);
- }
- break;
-
- /* line number info */
- case N_SLINE:
- pc = sym->n_value + func_addr;
-
-
- /* XXX: slow! */
- strcpy(last_func_name, func_name);
-
- // output a line reference
-
- CoffLineNo.l_addr.l_paddr = last_pc;
-
- if (last_line_num == -1) {
- CoffLineNo.l_lnno = sym->n_desc;
- } else {
- CoffLineNo.l_lnno = last_line_num + 1;
- }
-
- fwrite(&CoffLineNo, 6, 1, f);
-
- last_pc = pc;
- last_line_num = sym->n_desc;
-
- break;
-
- /* include files */
- case N_BINCL:
- str =
- (const char *) stabstr_section->data + sym->n_strx;
- add_incl2:
- if (incl_index < INCLUDE_STACK_SIZE) {
- incl_files[incl_index++] = str;
- }
- break;
- case N_EINCL:
- if (incl_index > 1)
- incl_index--;
- break;
- case N_SO:
- if (sym->n_strx == 0) {
- incl_index = 0; /* end of translation unit */
- } else {
- str =
- (const char *) stabstr_section->data +
- sym->n_strx;
- /* do not add path */
- len = strlen(str);
- if (len > 0 && str[len - 1] != '/')
- goto add_incl2;
- }
- break;
- }
- sym++;
- }
- }
- }
-
- // write symbol table
- if (s1->do_debug) {
- int k;
- struct syment csym;
- AUXFUNC auxfunc;
- AUXBF auxbf;
- AUXEF auxef;
- int i;
- Elf32_Sym *p;
- const char *name;
- int nstr;
- int n = 0;
-
- Coff_str_table = (char *) tcc_malloc(MAX_STR_TABLE);
- pCoff_str_table = Coff_str_table;
- nstr = 0;
-
- p = (Elf32_Sym *) symtab_section->data;
-
-
- for (i = 0; i < nb_syms; i++) {
-
- name = symtab_section->link->data + p->st_name;
-
- for (k = 0; k < 8; k++)
- csym._n._n_name[k] = 0;
-
- if (strlen(name) <= 8) {
- strcpy(csym._n._n_name, name);
- } else {
- if (pCoff_str_table - Coff_str_table + strlen(name) >
- MAX_STR_TABLE - 1)
- tcc_error("String table too large");
-
- csym._n._n_n._n_zeroes = 0;
- csym._n._n_n._n_offset =
- pCoff_str_table - Coff_str_table + 4;
-
- strcpy(pCoff_str_table, name);
- pCoff_str_table += strlen(name) + 1; // skip over null
- nstr++;
- }
-
- if (p->st_info == 4) {
- // put a filename symbol
- csym.n_value = 33; // ?????
- csym.n_scnum = N_DEBUG;
- csym.n_type = 0;
- csym.n_sclass = C_FILE;
- csym.n_numaux = 0;
- fwrite(&csym, 18, 1, f);
- n++;
-
- } else if (p->st_info == 0x12) {
- // find the function data
-
- for (k = 0; k < nFuncs; k++) {
- if (strcmp(name, Func[k]) == 0)
- break;
- }
-
- if (k >= nFuncs) {
- tcc_error("debug info can't find function: %s", name);
- }
- // put a Function Name
-
- csym.n_value = p->st_value; // physical address
- csym.n_scnum = CoffTextSectionNo;
- csym.n_type = MKTYPE(T_INT, DT_FCN, 0, 0, 0, 0, 0);
- csym.n_sclass = C_EXT;
- csym.n_numaux = 1;
- fwrite(&csym, 18, 1, f);
-
- // now put aux info
-
- auxfunc.tag = 0;
- auxfunc.size = EndAddress[k] - p->st_value;
- auxfunc.fileptr = LineNoFilePtr[k];
- auxfunc.nextsym = n + 6; // tktk
- auxfunc.dummy = 0;
- fwrite(&auxfunc, 18, 1, f);
-
- // put a .bf
-
- strcpy(csym._n._n_name, ".bf");
- csym.n_value = p->st_value; // physical address
- csym.n_scnum = CoffTextSectionNo;
- csym.n_type = 0;
- csym.n_sclass = C_FCN;
- csym.n_numaux = 1;
- fwrite(&csym, 18, 1, f);
-
- // now put aux info
-
- auxbf.regmask = 0;
- auxbf.lineno = 0;
- auxbf.nentries = FuncEntries[k];
- auxbf.localframe = 0;
- auxbf.nextentry = n + 6;
- auxbf.dummy = 0;
- fwrite(&auxbf, 18, 1, f);
-
- // put a .ef
-
- strcpy(csym._n._n_name, ".ef");
- csym.n_value = EndAddress[k]; // physical address
- csym.n_scnum = CoffTextSectionNo;
- csym.n_type = 0;
- csym.n_sclass = C_FCN;
- csym.n_numaux = 1;
- fwrite(&csym, 18, 1, f);
-
- // now put aux info
-
- auxef.dummy = 0;
- auxef.lineno = LastLineNo[k];
- auxef.dummy1 = 0;
- auxef.dummy2 = 0;
- auxef.dummy3 = 0;
- auxef.dummy4 = 0;
- fwrite(&auxef, 18, 1, f);
-
- n += 6;
-
- } else {
- // try an put some type info
-
- if ((p->st_other & VT_BTYPE) == VT_DOUBLE) {
- csym.n_type = T_DOUBLE; // int
- csym.n_sclass = C_EXT;
- } else if ((p->st_other & VT_BTYPE) == VT_FLOAT) {
- csym.n_type = T_FLOAT;
- csym.n_sclass = C_EXT;
- } else if ((p->st_other & VT_BTYPE) == VT_INT) {
- csym.n_type = T_INT; // int
- csym.n_sclass = C_EXT;
- } else if ((p->st_other & VT_BTYPE) == VT_SHORT) {
- csym.n_type = T_SHORT;
- csym.n_sclass = C_EXT;
- } else if ((p->st_other & VT_BTYPE) == VT_BYTE) {
- csym.n_type = T_CHAR;
- csym.n_sclass = C_EXT;
- } else {
- csym.n_type = T_INT; // just mark as a label
- csym.n_sclass = C_LABEL;
- }
-
-
- csym.n_value = p->st_value;
- csym.n_scnum = 2;
- csym.n_numaux = 1;
- fwrite(&csym, 18, 1, f);
-
- auxfunc.tag = 0;
- auxfunc.size = 0x20;
- auxfunc.fileptr = 0;
- auxfunc.nextsym = 0;
- auxfunc.dummy = 0;
- fwrite(&auxfunc, 18, 1, f);
- n++;
- n++;
-
- }
-
- p++;
- }
- }
-
- if (s1->do_debug) {
- // write string table
-
- // first write the size
- i = pCoff_str_table - Coff_str_table;
- fwrite(&i, 4, 1, f);
-
- // then write the strings
- fwrite(Coff_str_table, i, 1, f);
-
- tcc_free(Coff_str_table);
- }
-
- return 0;
-}
-
-
-
-// group the symbols in order of filename, func1, func2, etc
-// finally global symbols
-
-void SortSymbolTable(TCCState *s1)
-{
- int i, j, k, n = 0;
- Elf32_Sym *p, *p2, *NewTable;
- char *name, *name2;
-
- NewTable = (Elf32_Sym *) tcc_malloc(nb_syms * sizeof(Elf32_Sym));
-
- p = (Elf32_Sym *) symtab_section->data;
-
-
- // find a file symbol, copy it over
- // then scan the whole symbol list and copy any function
- // symbols that match the file association
-
- for (i = 0; i < nb_syms; i++) {
- if (p->st_info == 4) {
- name = (char *) symtab_section->link->data + p->st_name;
-
- // this is a file symbol, copy it over
-
- NewTable[n++] = *p;
-
- p2 = (Elf32_Sym *) symtab_section->data;
-
- for (j = 0; j < nb_syms; j++) {
- if (p2->st_info == 0x12) {
- // this is a func symbol
-
- name2 =
- (char *) symtab_section->link->data + p2->st_name;
-
- // find the function data index
-
- for (k = 0; k < nFuncs; k++) {
- if (strcmp(name2, Func[k]) == 0)
- break;
- }
-
- if (k >= nFuncs) {
- tcc_error("debug (sort) info can't find function: %s", name2);
- }
-
- if (strcmp(AssociatedFile[k], name) == 0) {
- // yes they match copy it over
-
- NewTable[n++] = *p2;
- }
- }
- p2++;
- }
- }
- p++;
- }
-
- // now all the filename and func symbols should have been copied over
- // copy all the rest over (all except file and funcs)
-
- p = (Elf32_Sym *) symtab_section->data;
- for (i = 0; i < nb_syms; i++) {
- if (p->st_info != 4 && p->st_info != 0x12) {
- NewTable[n++] = *p;
- }
- p++;
- }
-
- if (n != nb_syms)
- tcc_error("Internal Compiler error, debug info");
-
- // copy it all back
-
- p = (Elf32_Sym *) symtab_section->data;
- for (i = 0; i < nb_syms; i++) {
- *p++ = NewTable[i];
- }
-
- tcc_free(NewTable);
-}
-
-
-int FindCoffSymbolIndex(TCCState *s1, const char *func_name)
-{
- int i, n = 0;
- Elf32_Sym *p;
- char *name;
-
- p = (Elf32_Sym *) symtab_section->data;
-
- for (i = 0; i < nb_syms; i++) {
-
- name = (char *) symtab_section->link->data + p->st_name;
-
- if (p->st_info == 4) {
- // put a filename symbol
- n++;
- } else if (p->st_info == 0x12) {
-
- if (strcmp(func_name, name) == 0)
- return n;
-
- n += 6;
-
- // put a Function Name
-
- // now put aux info
-
- // put a .bf
-
- // now put aux info
-
- // put a .ef
-
- // now put aux info
-
- } else {
- n += 2;
- }
-
- p++;
- }
-
- return n; // total number of symbols
-}
-
-int OutputTheSection(Section * sect)
-{
- const char *s = sect->name;
-
- if (!strcmp(s, ".text"))
- return 1;
- else if (!strcmp(s, ".data"))
- return 1;
- else
- return 0;
-}
-
-short int GetCoffFlags(const char *s)
-{
- if (!strcmp(s, ".text"))
- return STYP_TEXT | STYP_DATA | STYP_ALIGN | 0x400;
- else if (!strcmp(s, ".data"))
- return STYP_DATA;
- else if (!strcmp(s, ".bss"))
- return STYP_BSS;
- else if (!strcmp(s, ".stack"))
- return STYP_BSS | STYP_ALIGN | 0x200;
- else if (!strcmp(s, ".cinit"))
- return STYP_COPY | STYP_DATA | STYP_ALIGN | 0x200;
- else
- return 0;
-}
-
-Section *FindSection(TCCState * s1, const char *sname)
-{
- Section *s;
- int i;
-
- for (i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
-
- if (!strcmp(sname, s->name))
- return s;
- }
-
- tcc_error("could not find section %s", sname);
- return 0;
-}
-
-ST_FUNC int tcc_load_coff(TCCState * s1, int fd)
-{
-// tktk TokenSym *ts;
-
- FILE *f;
- unsigned int str_size;
- char *Coff_str_table, *name;
- int i, k;
- struct syment csym;
- char name2[9];
- FILHDR file_hdr; /* FILE HEADER STRUCTURE */
-
- f = fdopen(fd, "rb");
- if (!f) {
- tcc_error("Unable to open .out file for input");
- }
-
- if (fread(&file_hdr, FILHSZ, 1, f) != 1)
- tcc_error("error reading .out file for input");
-
- if (fread(&o_filehdr, sizeof(o_filehdr), 1, f) != 1)
- tcc_error("error reading .out file for input");
-
- // first read the string table
-
- if (fseek(f, file_hdr.f_symptr + file_hdr.f_nsyms * SYMESZ, SEEK_SET))
- tcc_error("error reading .out file for input");
-
- if (fread(&str_size, sizeof(int), 1, f) != 1)
- tcc_error("error reading .out file for input");
-
-
- Coff_str_table = (char *) tcc_malloc(str_size);
-
- if (fread(Coff_str_table, str_size - 4, 1, f) != 1)
- tcc_error("error reading .out file for input");
-
- // read/process all the symbols
-
- // seek back to symbols
-
- if (fseek(f, file_hdr.f_symptr, SEEK_SET))
- tcc_error("error reading .out file for input");
-
- for (i = 0; i < file_hdr.f_nsyms; i++) {
- if (fread(&csym, SYMESZ, 1, f) != 1)
- tcc_error("error reading .out file for input");
-
- if (csym._n._n_n._n_zeroes == 0) {
- name = Coff_str_table + csym._n._n_n._n_offset - 4;
- } else {
- name = csym._n._n_name;
-
- if (name[7] != 0) {
- for (k = 0; k < 8; k++)
- name2[k] = name[k];
-
- name2[8] = 0;
-
- name = name2;
- }
- }
-// if (strcmp("_DAC_Buffer",name)==0) // tktk
-// name[0]=0;
-
- if (((csym.n_type & 0x30) == 0x20 && csym.n_sclass == 0x2) || ((csym.n_type & 0x30) == 0x30 && csym.n_sclass == 0x2) || (csym.n_type == 0x4 && csym.n_sclass == 0x2) || (csym.n_type == 0x8 && csym.n_sclass == 0x2) || // structures
- (csym.n_type == 0x18 && csym.n_sclass == 0x2) || // pointer to structure
- (csym.n_type == 0x7 && csym.n_sclass == 0x2) || // doubles
- (csym.n_type == 0x6 && csym.n_sclass == 0x2)) // floats
- {
- // strip off any leading underscore (except for other main routine)
-
- if (name[0] == '_' && strcmp(name, "_main") != 0)
- name++;
-
- tcc_add_symbol(s1, name, (void*)(uintptr_t)csym.n_value);
- }
- // skip any aux records
-
- if (csym.n_numaux == 1) {
- if (fread(&csym, SYMESZ, 1, f) != 1)
- tcc_error("error reading .out file for input");
- i++;
- }
- }
-
- return 0;
-}
diff --git a/tinycc/tccdbg.c b/tinycc/tccdbg.c
deleted file mode 100644
index 18c2cb1..0000000
--- a/tinycc/tccdbg.c
+++ /dev/null
@@ -1,2176 +0,0 @@
-/*
- * TCC - Tiny C Compiler
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "tcc.h"
-
-/* stab debug support */
-
-static const struct {
- int type;
- int size;
- int encoding;
- const char *name;
-} default_debug[] = {
- { VT_INT, 4, DW_ATE_signed, "int:t1=r1;-2147483648;2147483647;" },
- { VT_BYTE, 1, DW_ATE_signed_char, "char:t2=r2;0;127;" },
-#if LONG_SIZE == 4
- { VT_LONG | VT_INT, 4, DW_ATE_signed, "long int:t3=r3;-2147483648;2147483647;" },
-#else
- { VT_LLONG | VT_LONG, 8, DW_ATE_signed, "long int:t3=r3;-9223372036854775808;9223372036854775807;" },
-#endif
- { VT_INT | VT_UNSIGNED, 4, DW_ATE_unsigned, "unsigned int:t4=r4;0;037777777777;" },
-#if LONG_SIZE == 4
- { VT_LONG | VT_INT | VT_UNSIGNED, 4, DW_ATE_unsigned, "long unsigned int:t5=r5;0;037777777777;" },
-#else
- /* use octal instead of -1 so size_t works (-gstabs+ in gcc) */
- { VT_LLONG | VT_LONG | VT_UNSIGNED, 8, DW_ATE_unsigned, "long unsigned int:t5=r5;0;01777777777777777777777;" },
-#endif
- { VT_QLONG, 16, DW_ATE_signed, "__int128:t6=r6;0;-1;" },
- { VT_QLONG | VT_UNSIGNED, 16, DW_ATE_unsigned, "__int128 unsigned:t7=r7;0;-1;" },
- { VT_LLONG, 8, DW_ATE_signed, "long long int:t8=r8;-9223372036854775808;9223372036854775807;" },
- { VT_LLONG | VT_UNSIGNED, 8, DW_ATE_unsigned, "long long unsigned int:t9=r9;0;01777777777777777777777;" },
- { VT_SHORT, 2, DW_ATE_signed, "short int:t10=r10;-32768;32767;" },
- { VT_SHORT | VT_UNSIGNED, 2, DW_ATE_unsigned, "short unsigned int:t11=r11;0;65535;" },
- { VT_BYTE | VT_DEFSIGN, 1, DW_ATE_signed_char, "signed char:t12=r12;-128;127;" },
- { VT_BYTE | VT_DEFSIGN | VT_UNSIGNED, 1, DW_ATE_unsigned_char, "unsigned char:t13=r13;0;255;" },
- { VT_FLOAT, 4, DW_ATE_float, "float:t14=r1;4;0;" },
- { VT_DOUBLE, 8, DW_ATE_float, "double:t15=r1;8;0;" },
-#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE
- { VT_DOUBLE | VT_LONG, 8, DW_ATE_float, "long double:t16=r1;8;0;" },
-#else
- { VT_LDOUBLE, 16, DW_ATE_float, "long double:t16=r1;16;0;" },
-#endif
- { -1, -1, -1, "_Float32:t17=r1;4;0;" },
- { -1, -1, -1, "_Float64:t18=r1;8;0;" },
- { -1, -1, -1, "_Float128:t19=r1;16;0;" },
- { -1, -1, -1, "_Float32x:t20=r1;8;0;" },
- { -1, -1, -1, "_Float64x:t21=r1;16;0;" },
- { -1, -1, -1, "_Decimal32:t22=r1;4;0;" },
- { -1, -1, -1, "_Decimal64:t23=r1;8;0;" },
- { -1, -1, -1, "_Decimal128:t24=r1;16;0;" },
- /* if default char is unsigned */
- { VT_BYTE | VT_UNSIGNED, 1, DW_ATE_unsigned_char, "unsigned char:t25=r25;0;255;" },
- /* boolean type */
- { VT_BOOL, 1, DW_ATE_boolean, "bool:t26=r26;0;255;" },
-#if LONG_SIZE == 4
- { VT_VOID, 1, DW_ATE_unsigned_char, "void:t27=27" },
-#else
- /* bitfields use these */
- { VT_LONG | VT_INT, 8, DW_ATE_signed, "long int:t27=r27;-9223372036854775808;9223372036854775807;" },
- { VT_LONG | VT_INT | VT_UNSIGNED, 8, DW_ATE_unsigned, "long unsigned int:t28=r28;0;01777777777777777777777;" },
- { VT_VOID, 1, DW_ATE_unsigned_char, "void:t29=29" },
-#endif
-};
-
-#define N_DEFAULT_DEBUG (sizeof (default_debug) / sizeof (default_debug[0]))
-
-/* dwarf debug */
-
-#define DWARF_LINE_BASE -5
-#define DWARF_LINE_RANGE 14
-#define DWARF_OPCODE_BASE 13
-
-#if defined TCC_TARGET_ARM64
-#define DWARF_MIN_INSTR_LEN 4
-#elif defined TCC_TARGET_ARM
-#define DWARF_MIN_INSTR_LEN 2
-#else
-#define DWARF_MIN_INSTR_LEN 1
-#endif
-
-#define DWARF_ABBREV_COMPILE_UNIT 1
-#define DWARF_ABBREV_BASE_TYPE 2
-#define DWARF_ABBREV_VARIABLE_EXTERNAL 3
-#define DWARF_ABBREV_VARIABLE_STATIC 4
-#define DWARF_ABBREV_VARIABLE_LOCAL 5
-#define DWARF_ABBREV_FORMAL_PARAMETER 6
-#define DWARF_ABBREV_POINTER 7
-#define DWARF_ABBREV_ARRAY_TYPE 8
-#define DWARF_ABBREV_SUBRANGE_TYPE 9
-#define DWARF_ABBREV_TYPEDEF 10
-#define DWARF_ABBREV_ENUMERATOR_SIGNED 11
-#define DWARF_ABBREV_ENUMERATOR_UNSIGNED 12
-#define DWARF_ABBREV_ENUMERATION_TYPE 13
-#define DWARF_ABBREV_MEMBER 14
-#define DWARF_ABBREV_MEMBER_BF 15
-#define DWARF_ABBREV_STRUCTURE_TYPE 16
-#define DWARF_ABBREV_STRUCTURE_EMPTY_TYPE 17
-#define DWARF_ABBREV_UNION_TYPE 18
-#define DWARF_ABBREV_UNION_EMPTY_TYPE 19
-#define DWARF_ABBREV_SUBPROGRAM_EXTERNAL 20
-#define DWARF_ABBREV_SUBPROGRAM_STATIC 21
-#define DWARF_ABBREV_LEXICAL_BLOCK 22
-#define DWARF_ABBREV_LEXICAL_EMPTY_BLOCK 23
-#define DWARF_ABBREV_SUBROUTINE_TYPE 24
-#define DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE 25
-#define DWARF_ABBREV_FORMAL_PARAMETER2 26
-
-/* all entries should have been generated with dwarf_uleb128 except
- has_children. All values are currently below 128 so this currently
- works. */
-static const unsigned char dwarf_abbrev_init[] = {
- DWARF_ABBREV_COMPILE_UNIT, DW_TAG_compile_unit, 1,
- DW_AT_producer, DW_FORM_strp,
- DW_AT_language, DW_FORM_data1,
- DW_AT_name, DW_FORM_line_strp,
- DW_AT_comp_dir, DW_FORM_line_strp,
- DW_AT_low_pc, DW_FORM_addr,
-#if PTR_SIZE == 4
- DW_AT_high_pc, DW_FORM_data4,
-#else
- DW_AT_high_pc, DW_FORM_data8,
-#endif
- DW_AT_stmt_list, DW_FORM_sec_offset,
- 0, 0,
- DWARF_ABBREV_BASE_TYPE, DW_TAG_base_type, 0,
- DW_AT_byte_size, DW_FORM_udata,
- DW_AT_encoding, DW_FORM_data1,
- DW_AT_name, DW_FORM_strp,
- 0, 0,
- DWARF_ABBREV_VARIABLE_EXTERNAL, DW_TAG_variable, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_external, DW_FORM_flag,
- DW_AT_location, DW_FORM_exprloc,
- 0, 0,
- DWARF_ABBREV_VARIABLE_STATIC, DW_TAG_variable, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_location, DW_FORM_exprloc,
- 0, 0,
- DWARF_ABBREV_VARIABLE_LOCAL, DW_TAG_variable, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_location, DW_FORM_exprloc,
- 0, 0,
- DWARF_ABBREV_FORMAL_PARAMETER, DW_TAG_formal_parameter, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_location, DW_FORM_exprloc,
- 0, 0,
- DWARF_ABBREV_POINTER, DW_TAG_pointer_type, 0,
- DW_AT_byte_size, DW_FORM_data1,
- DW_AT_type, DW_FORM_ref4,
- 0, 0,
- DWARF_ABBREV_ARRAY_TYPE, DW_TAG_array_type, 1,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_sibling, DW_FORM_ref4,
- 0, 0,
- DWARF_ABBREV_SUBRANGE_TYPE, DW_TAG_subrange_type, 0,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_upper_bound, DW_FORM_udata,
- 0, 0,
- DWARF_ABBREV_TYPEDEF, DW_TAG_typedef, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- DW_AT_type, DW_FORM_ref4,
- 0, 0,
- DWARF_ABBREV_ENUMERATOR_SIGNED, DW_TAG_enumerator, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_const_value, DW_FORM_sdata,
- 0, 0,
- DWARF_ABBREV_ENUMERATOR_UNSIGNED, DW_TAG_enumerator, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_const_value, DW_FORM_udata,
- 0, 0,
- DWARF_ABBREV_ENUMERATION_TYPE, DW_TAG_enumeration_type, 1,
- DW_AT_name, DW_FORM_strp,
- DW_AT_encoding, DW_FORM_data1,
- DW_AT_byte_size, DW_FORM_data1,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- DW_AT_sibling, DW_FORM_ref4,
- 0, 0,
- DWARF_ABBREV_MEMBER, DW_TAG_member, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_data_member_location, DW_FORM_udata,
- 0, 0,
- DWARF_ABBREV_MEMBER_BF, DW_TAG_member, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_bit_size, DW_FORM_udata,
- DW_AT_data_bit_offset, DW_FORM_udata,
- 0, 0,
- DWARF_ABBREV_STRUCTURE_TYPE, DW_TAG_structure_type, 1,
- DW_AT_name, DW_FORM_strp,
- DW_AT_byte_size, DW_FORM_udata,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- DW_AT_sibling, DW_FORM_ref4,
- 0, 0,
- DWARF_ABBREV_STRUCTURE_EMPTY_TYPE, DW_TAG_structure_type, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_byte_size, DW_FORM_udata,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- 0, 0,
- DWARF_ABBREV_UNION_TYPE, DW_TAG_union_type, 1,
- DW_AT_name, DW_FORM_strp,
- DW_AT_byte_size, DW_FORM_udata,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- DW_AT_sibling, DW_FORM_ref4,
- 0, 0,
- DWARF_ABBREV_UNION_EMPTY_TYPE, DW_TAG_union_type, 0,
- DW_AT_name, DW_FORM_strp,
- DW_AT_byte_size, DW_FORM_udata,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- 0, 0,
- DWARF_ABBREV_SUBPROGRAM_EXTERNAL, DW_TAG_subprogram, 1,
- DW_AT_external, DW_FORM_flag,
- DW_AT_name, DW_FORM_strp,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_low_pc, DW_FORM_addr,
-#if PTR_SIZE == 4
- DW_AT_high_pc, DW_FORM_data4,
-#else
- DW_AT_high_pc, DW_FORM_data8,
-#endif
- DW_AT_sibling, DW_FORM_ref4,
- DW_AT_frame_base, DW_FORM_exprloc,
- 0, 0,
- DWARF_ABBREV_SUBPROGRAM_STATIC, DW_TAG_subprogram, 1,
- DW_AT_name, DW_FORM_strp,
- DW_AT_decl_file, DW_FORM_udata,
- DW_AT_decl_line, DW_FORM_udata,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_low_pc, DW_FORM_addr,
-#if PTR_SIZE == 4
- DW_AT_high_pc, DW_FORM_data4,
-#else
- DW_AT_high_pc, DW_FORM_data8,
-#endif
- DW_AT_sibling, DW_FORM_ref4,
- DW_AT_frame_base, DW_FORM_exprloc,
- 0, 0,
- DWARF_ABBREV_LEXICAL_BLOCK, DW_TAG_lexical_block, 1,
- DW_AT_low_pc, DW_FORM_addr,
-#if PTR_SIZE == 4
- DW_AT_high_pc, DW_FORM_data4,
-#else
- DW_AT_high_pc, DW_FORM_data8,
-#endif
- 0, 0,
- DWARF_ABBREV_LEXICAL_EMPTY_BLOCK, DW_TAG_lexical_block, 0,
- DW_AT_low_pc, DW_FORM_addr,
-#if PTR_SIZE == 4
- DW_AT_high_pc, DW_FORM_data4,
-#else
- DW_AT_high_pc, DW_FORM_data8,
-#endif
- 0, 0,
- DWARF_ABBREV_SUBROUTINE_TYPE, DW_TAG_subroutine_type, 1,
- DW_AT_type, DW_FORM_ref4,
- DW_AT_sibling, DW_FORM_ref4,
- 0, 0,
- DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE, DW_TAG_subroutine_type, 0,
- DW_AT_type, DW_FORM_ref4,
- 0, 0,
- DWARF_ABBREV_FORMAL_PARAMETER2, DW_TAG_formal_parameter, 0,
- DW_AT_type, DW_FORM_ref4,
- 0, 0,
- 0
-};
-
-static const unsigned char dwarf_line_opcodes[] = {
- 0 ,1 ,1 ,1 ,1 ,0 ,0 ,0 ,1 ,0 ,0 ,1
-};
-
-/* ------------------------------------------------------------------------- */
-/* debug state */
-
-struct _tccdbg {
-
- int last_line_num, new_file;
- int section_sym;
-
- int debug_next_type;
-
- struct _debug_hash {
- int debug_type;
- Sym *type;
- } *debug_hash;
-
- struct _debug_anon_hash {
- Sym *type;
- int n_debug_type;
- int *debug_type;
- } *debug_anon_hash;
-
- int n_debug_hash;
- int n_debug_anon_hash;
-
- struct _debug_info {
- int start;
- int end;
- int n_sym;
- struct debug_sym {
- int type;
- unsigned long value;
- char *str;
- Section *sec;
- int sym_index;
- int info;
- int file;
- int line;
- } *sym;
- struct _debug_info *child, *next, *last, *parent;
- } *debug_info, *debug_info_root;
-
- struct {
- int info;
- int abbrev;
- int line;
- int str;
- int line_str;
- } dwarf_sym;
-
- struct {
- int start;
- int dir_size;
- char **dir_table;
- int filename_size;
- struct dwarf_filename_struct {
- int dir_entry;
- char *name;
- } *filename_table;
- int line_size;
- int line_max_size;
- unsigned char *line_data;
- int cur_file;
- int last_file;
- int last_pc;
- int last_line;
- } dwarf_line;
-
- struct {
- int start;
- Sym *func;
- int line;
- int base_type_used[N_DEFAULT_DEBUG];
- } dwarf_info;
-
- /* test coverage */
- struct {
- unsigned long offset;
- unsigned long last_file_name;
- unsigned long last_func_name;
- int ind;
- int line;
- } tcov_data;
-
-};
-
-#define last_line_num s1->dState->last_line_num
-#define new_file s1->dState->new_file
-#define section_sym s1->dState->section_sym
-#define debug_next_type s1->dState->debug_next_type
-#define debug_hash s1->dState->debug_hash
-#define debug_anon_hash s1->dState->debug_anon_hash
-#define n_debug_hash s1->dState->n_debug_hash
-#define n_debug_anon_hash s1->dState->n_debug_anon_hash
-#define debug_info s1->dState->debug_info
-#define debug_info_root s1->dState->debug_info_root
-#define dwarf_sym s1->dState->dwarf_sym
-#define dwarf_line s1->dState->dwarf_line
-#define dwarf_info s1->dState->dwarf_info
-#define tcov_data s1->dState->tcov_data
-
-/* ------------------------------------------------------------------------- */
-static void put_stabs(TCCState *s1, const char *str, int type, int other,
- int desc, unsigned long value);
-
-ST_FUNC void tcc_debug_new(TCCState *s1)
-{
- int shf = 0;
- if (!s1->dState)
- s1->dState = tcc_mallocz(sizeof *s1->dState);
-#ifdef CONFIG_TCC_BACKTRACE
- /* include stab info with standalone backtrace support */
- if (s1->do_backtrace
- && (s1->output_type & (TCC_OUTPUT_EXE | TCC_OUTPUT_DLL)))
- shf = SHF_ALLOC | SHF_WRITE; // SHF_WRITE needed for musl/SELINUX
-#endif
- if (s1->dwarf) {
- s1->dwlo = s1->nb_sections;
- dwarf_info_section =
- new_section(s1, ".debug_info", SHT_PROGBITS, shf);
- dwarf_abbrev_section =
- new_section(s1, ".debug_abbrev", SHT_PROGBITS, shf);
- dwarf_line_section =
- new_section(s1, ".debug_line", SHT_PROGBITS, shf);
- dwarf_aranges_section =
- new_section(s1, ".debug_aranges", SHT_PROGBITS, shf);
- shf |= SHF_MERGE | SHF_STRINGS;
- dwarf_str_section =
- new_section(s1, ".debug_str", SHT_PROGBITS, shf);
- dwarf_str_section->sh_entsize = 1;
- dwarf_info_section->sh_addralign =
- dwarf_abbrev_section->sh_addralign =
- dwarf_line_section->sh_addralign =
- dwarf_aranges_section->sh_addralign =
- dwarf_str_section->sh_addralign = 1;
- if (s1->dwarf >= 5) {
- dwarf_line_str_section =
- new_section(s1, ".debug_line_str", SHT_PROGBITS, shf);
- dwarf_line_str_section->sh_entsize = 1;
- dwarf_line_str_section->sh_addralign = 1;
- }
- s1->dwhi = s1->nb_sections;
- }
- else
- {
- stab_section = new_section(s1, ".stab", SHT_PROGBITS, shf);
- stab_section->sh_entsize = sizeof(Stab_Sym);
- stab_section->sh_addralign = sizeof ((Stab_Sym*)0)->n_value;
- stab_section->link = new_section(s1, ".stabstr", SHT_STRTAB, shf);
- /* put first entry */
- put_stabs(s1, "", 0, 0, 0, 0);
- }
-}
-
-/* put stab debug information */
-static void put_stabs(TCCState *s1, const char *str, int type, int other, int desc,
- unsigned long value)
-{
- Stab_Sym *sym;
-
- unsigned offset;
- if (type == N_SLINE
- && (offset = stab_section->data_offset)
- && (sym = (Stab_Sym*)(stab_section->data + offset) - 1)
- && sym->n_type == type
- && sym->n_value == value) {
- /* just update line_number in previous entry */
- sym->n_desc = desc;
- return;
- }
-
- sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
- if (str) {
- sym->n_strx = put_elf_str(stab_section->link, str);
- } else {
- sym->n_strx = 0;
- }
- sym->n_type = type;
- sym->n_other = other;
- sym->n_desc = desc;
- sym->n_value = value;
-}
-
-static void put_stabs_r(TCCState *s1, const char *str, int type, int other, int desc,
- unsigned long value, Section *sec, int sym_index)
-{
- put_elf_reloc(symtab_section, stab_section,
- stab_section->data_offset + 8,
- sizeof ((Stab_Sym*)0)->n_value == PTR_SIZE ? R_DATA_PTR : R_DATA_32,
- sym_index);
- put_stabs(s1, str, type, other, desc, value);
-}
-
-static void put_stabn(TCCState *s1, int type, int other, int desc, int value)
-{
- put_stabs(s1, NULL, type, other, desc, value);
-}
-
-/* ------------------------------------------------------------------------- */
-#define dwarf_data1(s,data) \
- { unsigned char *p = section_ptr_add((s), 1); *p = (data); }
-#define dwarf_data2(s,data) \
- write16le(section_ptr_add((s), 2), (data))
-#define dwarf_data4(s,data) \
- write32le(section_ptr_add((s), 4), (data))
-#define dwarf_data8(s,data) \
- write64le(section_ptr_add((s), 8), (data))
-
-static int dwarf_get_section_sym(Section *s)
-{
- TCCState *s1 = s->s1;
- return put_elf_sym(symtab_section, 0, 0,
- ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
- s->sh_num, NULL);
-}
-
-static void dwarf_reloc(Section *s, int sym, int rel)
-{
- TCCState *s1 = s->s1;
- put_elf_reloca(symtab_section, s, s->data_offset, rel, sym, 0);
-}
-
-static void dwarf_string(Section *s, Section *dw, int sym, const char *str)
-{
- TCCState *s1 = s->s1;
- int offset, len;
- char *ptr;
-
- len = strlen(str) + 1;
- offset = dw->data_offset;
- ptr = section_ptr_add(dw, len);
- memmove(ptr, str, len);
- put_elf_reloca(symtab_section, s, s->data_offset, R_DATA_32DW, sym,
- PTR_SIZE == 4 ? 0 : offset);
- dwarf_data4(s, PTR_SIZE == 4 ? offset : 0);
-}
-
-static void dwarf_strp(Section *s, const char *str)
-{
- TCCState *s1 = s->s1;
- dwarf_string(s, dwarf_str_section, dwarf_sym.str, str);
-}
-
-static void dwarf_line_strp(Section *s, const char *str)
-{
- TCCState *s1 = s->s1;
- dwarf_string(s, dwarf_line_str_section, dwarf_sym.line_str, str);
-}
-
-static void dwarf_line_op(TCCState *s1, unsigned char op)
-{
- if (dwarf_line.line_size >= dwarf_line.line_max_size) {
- dwarf_line.line_max_size += 1024;
- dwarf_line.line_data =
- (unsigned char *)tcc_realloc(dwarf_line.line_data,
- dwarf_line.line_max_size);
- }
- dwarf_line.line_data[dwarf_line.line_size++] = op;
-}
-
-static void dwarf_file(TCCState *s1)
-{
- int i, j;
- char *filename;
- int index_offset = s1->dwarf < 5;
-
- if (!strcmp(file->filename, "<command line>")) {
- dwarf_line.cur_file = 1;
- return;
- }
- filename = strrchr(file->filename, '/');
- if (filename == NULL) {
- for (i = 1; i < dwarf_line.filename_size; i++)
- if (dwarf_line.filename_table[i].dir_entry == 0 &&
- strcmp(dwarf_line.filename_table[i].name,
- file->filename) == 0) {
- dwarf_line.cur_file = i + index_offset;
- return;
- }
- i = -index_offset;
- filename = file->filename;
- }
- else {
- char *undo = filename;
- char *dir = file->filename;
-
- *filename++ = '\0';
- for (i = 0; i < dwarf_line.dir_size; i++)
- if (strcmp(dwarf_line.dir_table[i], dir) == 0) {
- for (j = 1; j < dwarf_line.filename_size; j++)
- if (dwarf_line.filename_table[j].dir_entry - index_offset
- == i &&
- strcmp(dwarf_line.filename_table[j].name,
- filename) == 0) {
- *undo = '/';
- dwarf_line.cur_file = j + index_offset;
- return;
- }
- break;
- }
- if (i == dwarf_line.dir_size) {
- dwarf_line.dir_size++;
- dwarf_line.dir_table =
- (char **) tcc_realloc(dwarf_line.dir_table,
- dwarf_line.dir_size *
- sizeof (char *));
- dwarf_line.dir_table[i] = tcc_strdup(dir);
- }
- *undo = '/';
- }
- dwarf_line.filename_table =
- (struct dwarf_filename_struct *)
- tcc_realloc(dwarf_line.filename_table,
- (dwarf_line.filename_size + 1) *
- sizeof (struct dwarf_filename_struct));
- dwarf_line.filename_table[dwarf_line.filename_size].dir_entry =
- i + index_offset;
- dwarf_line.filename_table[dwarf_line.filename_size].name =
- tcc_strdup(filename);
- dwarf_line.cur_file = dwarf_line.filename_size++ + index_offset;
- return;
-}
-
-#if 0
-static int dwarf_uleb128_size (unsigned long long value)
-{
- int size = 0;
-
- do {
- value >>= 7;
- size++;
- } while (value != 0);
- return size;
-}
-#endif
-
-static int dwarf_sleb128_size (long long value)
-{
- int size = 0;
- long long end = value >> 63;
- unsigned char last = end & 0x40;
- unsigned char byte;
-
- do {
- byte = value & 0x7f;
- value >>= 7;
- size++;
- } while (value != end || (byte & 0x40) != last);
- return size;
-}
-
-static void dwarf_uleb128 (Section *s, unsigned long long value)
-{
- do {
- unsigned char byte = value & 0x7f;
-
- value >>= 7;
- dwarf_data1(s, byte | (value ? 0x80 : 0));
- } while (value != 0);
-}
-
-static void dwarf_sleb128 (Section *s, long long value)
-{
- int more;
- long long end = value >> 63;
- unsigned char last = end & 0x40;
-
- do {
- unsigned char byte = value & 0x7f;
-
- value >>= 7;
- more = value != end || (byte & 0x40) != last;
- dwarf_data1(s, byte | (0x80 * more));
- } while (more);
-}
-
-static void dwarf_uleb128_op (TCCState *s1, unsigned long long value)
-{
- do {
- unsigned char byte = value & 0x7f;
-
- value >>= 7;
- dwarf_line_op(s1, byte | (value ? 0x80 : 0));
- } while (value != 0);
-}
-
-static void dwarf_sleb128_op (TCCState *s1, long long value)
-{
- int more;
- long long end = value >> 63;
- unsigned char last = end & 0x40;
-
- do {
- unsigned char byte = value & 0x7f;
-
- value >>= 7;
- more = value != end || (byte & 0x40) != last;
- dwarf_line_op(s1, byte | (0x80 * more));
- } while (more);
-}
-
-/* start of translation unit info */
-ST_FUNC void tcc_debug_start(TCCState *s1)
-{
- int i;
- char buf[512];
- char *filename;
-
- /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
- symbols can be safely used */
- filename = file->prev ? file->prev->filename : file->filename;
- put_elf_sym(symtab_section, 0, 0,
- ELFW(ST_INFO)(STB_LOCAL, STT_FILE), 0,
- SHN_ABS, filename);
-
- if (s1->do_debug) {
-
- new_file = last_line_num = 0;
- debug_next_type = N_DEFAULT_DEBUG;
- debug_hash = NULL;
- debug_anon_hash = NULL;
- n_debug_hash = 0;
- n_debug_anon_hash = 0;
-
- getcwd(buf, sizeof(buf));
-#ifdef _WIN32
- normalize_slashes(buf);
-#endif
-
- if (s1->dwarf) {
- int start_abbrev;
- unsigned char *ptr;
- char *undo;
-
- /* dwarf_abbrev */
- start_abbrev = dwarf_abbrev_section->data_offset;
- ptr = section_ptr_add(dwarf_abbrev_section, sizeof(dwarf_abbrev_init));
- memcpy(ptr, dwarf_abbrev_init, sizeof(dwarf_abbrev_init));
-
- if (s1->dwarf < 5) {
- while (*ptr) {
- ptr += 3;
- while (*ptr) {
- if (ptr[1] == DW_FORM_line_strp)
- ptr[1] = DW_FORM_strp;
- if (s1->dwarf < 4) {
- /* These are compatable for DW_TAG_compile_unit
- DW_AT_stmt_list. */
- if (ptr[1] == DW_FORM_sec_offset)
- ptr[1] = DW_FORM_data4;
- /* This code uses only size < 0x80 so these are
- compatible. */
- if (ptr[1] == DW_FORM_exprloc)
- ptr[1] = DW_FORM_block1;
- }
- ptr += 2;
- }
- ptr += 2;
- }
- }
-
- dwarf_sym.info = dwarf_get_section_sym(dwarf_info_section);
- dwarf_sym.abbrev = dwarf_get_section_sym(dwarf_abbrev_section);
- dwarf_sym.line = dwarf_get_section_sym(dwarf_line_section);
- dwarf_sym.str = dwarf_get_section_sym(dwarf_str_section);
- if (tcc_state->dwarf >= 5)
- dwarf_sym.line_str = dwarf_get_section_sym(dwarf_line_str_section);
- else {
- dwarf_line_str_section = dwarf_str_section;
- dwarf_sym.line_str = dwarf_sym.str;
- }
- section_sym = dwarf_get_section_sym(text_section);
-
- /* dwarf_info */
- dwarf_info.start = dwarf_info_section->data_offset;
- dwarf_data4(dwarf_info_section, 0); // size
- dwarf_data2(dwarf_info_section, s1->dwarf); // version
- if (s1->dwarf >= 5) {
- dwarf_data1(dwarf_info_section, DW_UT_compile); // unit type
- dwarf_data1(dwarf_info_section, PTR_SIZE);
- dwarf_reloc(dwarf_info_section, dwarf_sym.abbrev, R_DATA_32DW);
- dwarf_data4(dwarf_info_section, start_abbrev);
- }
- else {
- dwarf_reloc(dwarf_info_section, dwarf_sym.abbrev, R_DATA_32DW);
- dwarf_data4(dwarf_info_section, start_abbrev);
- dwarf_data1(dwarf_info_section, PTR_SIZE);
- }
-
- dwarf_data1(dwarf_info_section, DWARF_ABBREV_COMPILE_UNIT);
- dwarf_strp(dwarf_info_section, "tcc " TCC_VERSION);
- dwarf_data1(dwarf_info_section, DW_LANG_C11);
- dwarf_line_strp(dwarf_info_section, filename);
- dwarf_line_strp(dwarf_info_section, buf);
- dwarf_reloc(dwarf_info_section, section_sym, R_DATA_PTR);
-#if PTR_SIZE == 4
- dwarf_data4(dwarf_info_section, ind); // low pc
- dwarf_data4(dwarf_info_section, 0); // high pc
-#else
- dwarf_data8(dwarf_info_section, ind); // low pc
- dwarf_data8(dwarf_info_section, 0); // high pc
-#endif
- dwarf_reloc(dwarf_info_section, dwarf_sym.line, R_DATA_32DW);
- dwarf_data4(dwarf_info_section, dwarf_line_section->data_offset); // stmt_list
-
- /* dwarf_line */
- dwarf_line.start = dwarf_line_section->data_offset;
- dwarf_data4(dwarf_line_section, 0); // length
- dwarf_data2(dwarf_line_section, s1->dwarf); // version
- if (s1->dwarf >= 5) {
- dwarf_data1(dwarf_line_section, PTR_SIZE); // address size
- dwarf_data1(dwarf_line_section, 0); // segment selector
- }
- dwarf_data4(dwarf_line_section, 0); // prologue Length
- dwarf_data1(dwarf_line_section, DWARF_MIN_INSTR_LEN);
- if (s1->dwarf >= 4)
- dwarf_data1(dwarf_line_section, 1); // maximum ops per instruction
- dwarf_data1(dwarf_line_section, 1); // Initial value of 'is_stmt'
- dwarf_data1(dwarf_line_section, DWARF_LINE_BASE);
- dwarf_data1(dwarf_line_section, DWARF_LINE_RANGE);
- dwarf_data1(dwarf_line_section, DWARF_OPCODE_BASE);
- ptr = section_ptr_add(dwarf_line_section, sizeof(dwarf_line_opcodes));
- memcpy(ptr, dwarf_line_opcodes, sizeof(dwarf_line_opcodes));
- undo = strrchr(filename, '/');
- if (undo)
- *undo = 0;
- dwarf_line.dir_size = 1 + (undo != NULL);
- dwarf_line.dir_table = (char **) tcc_malloc(sizeof (char *) *
- dwarf_line.dir_size);
- dwarf_line.dir_table[0] = tcc_strdup(buf);
- if (undo)
- dwarf_line.dir_table[1] = tcc_strdup(filename);
- dwarf_line.filename_size = 2;
- dwarf_line.filename_table =
- (struct dwarf_filename_struct *)
- tcc_malloc(2*sizeof (struct dwarf_filename_struct));
- dwarf_line.filename_table[0].dir_entry = 0;
- if (undo) {
- dwarf_line.filename_table[0].name = tcc_strdup(undo + 1);
- dwarf_line.filename_table[1].dir_entry = 1;
- dwarf_line.filename_table[1].name = tcc_strdup(undo + 1);
- *undo = '/';
- }
- else {
- dwarf_line.filename_table[0].name = tcc_strdup(filename);
- dwarf_line.filename_table[1].dir_entry = 0;
- dwarf_line.filename_table[1].name = tcc_strdup(filename);
- }
- dwarf_line.line_size = dwarf_line.line_max_size = 0;
- dwarf_line.line_data = NULL;
- dwarf_line.cur_file = 1;
- dwarf_line.last_file = 0;
- dwarf_line.last_pc = 0;
- dwarf_line.last_line = 1;
- dwarf_line_op(s1, 0); // extended
- dwarf_uleb128_op(s1, 1 + PTR_SIZE); // extended size
- dwarf_line_op(s1, DW_LNE_set_address);
- for (i = 0; i < PTR_SIZE; i++)
- dwarf_line_op(s1, 0);
- memset(&dwarf_info.base_type_used, 0, sizeof(dwarf_info.base_type_used));
- }
- else
- {
- /* file info: full path + filename */
- pstrcat(buf, sizeof(buf), "/");
- section_sym = put_elf_sym(symtab_section, 0, 0,
- ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
- text_section->sh_num, NULL);
- put_stabs_r(s1, buf, N_SO, 0, 0,
- text_section->data_offset, text_section, section_sym);
- put_stabs_r(s1, filename, N_SO, 0, 0,
- text_section->data_offset, text_section, section_sym);
- for (i = 0; i < N_DEFAULT_DEBUG; i++)
- put_stabs(s1, default_debug[i].name, N_LSYM, 0, 0, 0);
- }
- /* we're currently 'including' the <command line> */
- tcc_debug_bincl(s1);
- }
-}
-
-/* put end of translation unit info */
-ST_FUNC void tcc_debug_end(TCCState *s1)
-{
- if (!s1->do_debug || debug_next_type == 0)
- return;
-
- if (debug_info_root)
- tcc_debug_funcend(s1, 0); /* free stuff in case of errors */
-
- if (s1->dwarf) {
- int i, j;
- int start_aranges;
- unsigned char *ptr;
- int text_size = text_section->data_offset;
-
- /* dwarf_info */
- for (i = 0; i < n_debug_anon_hash; i++) {
- Sym *t = debug_anon_hash[i].type;
- int pos = dwarf_info_section->data_offset;
-
- dwarf_data1(dwarf_info_section,
- IS_UNION (t->type.t) ? DWARF_ABBREV_UNION_EMPTY_TYPE
- : DWARF_ABBREV_STRUCTURE_EMPTY_TYPE);
- dwarf_strp(dwarf_info_section,
- (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
- ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL));
- dwarf_uleb128(dwarf_info_section, 0);
- dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
- dwarf_uleb128(dwarf_info_section, file->line_num);
- for (j = 0; j < debug_anon_hash[i].n_debug_type; j++)
- write32le(dwarf_info_section->data +
- debug_anon_hash[i].debug_type[j],
- pos - dwarf_info.start);
- tcc_free (debug_anon_hash[i].debug_type);
- }
- tcc_free (debug_anon_hash);
- dwarf_data1(dwarf_info_section, 0);
- ptr = dwarf_info_section->data + dwarf_info.start;
- write32le(ptr, dwarf_info_section->data_offset - dwarf_info.start - 4);
- write32le(ptr + 25 + (s1->dwarf >= 5) + PTR_SIZE, text_size);
-
- /* dwarf_aranges */
- start_aranges = dwarf_aranges_section->data_offset;
- dwarf_data4(dwarf_aranges_section, 0); // size
- dwarf_data2(dwarf_aranges_section, 2); // version
- dwarf_reloc(dwarf_aranges_section, dwarf_sym.info, R_DATA_32DW);
- dwarf_data4(dwarf_aranges_section, 0); // dwarf_info
-#if PTR_SIZE == 4
- dwarf_data1(dwarf_aranges_section, 4); // address size
-#else
- dwarf_data1(dwarf_aranges_section, 8); // address size
-#endif
- dwarf_data1(dwarf_aranges_section, 0); // segment selector size
- dwarf_data4(dwarf_aranges_section, 0); // padding
- dwarf_reloc(dwarf_aranges_section, section_sym, R_DATA_PTR);
-#if PTR_SIZE == 4
- dwarf_data4(dwarf_aranges_section, 0); // Begin
- dwarf_data4(dwarf_aranges_section, text_size); // End
- dwarf_data4(dwarf_aranges_section, 0); // End list
- dwarf_data4(dwarf_aranges_section, 0); // End list
-#else
- dwarf_data8(dwarf_aranges_section, 0); // Begin
- dwarf_data8(dwarf_aranges_section, text_size); // End
- dwarf_data8(dwarf_aranges_section, 0); // End list
- dwarf_data8(dwarf_aranges_section, 0); // End list
-#endif
- ptr = dwarf_aranges_section->data + start_aranges;
- write32le(ptr, dwarf_aranges_section->data_offset - start_aranges - 4);
-
- /* dwarf_line */
- if (s1->dwarf >= 5) {
- dwarf_data1(dwarf_line_section, 1); /* col */
- dwarf_uleb128(dwarf_line_section, DW_LNCT_path);
- dwarf_uleb128(dwarf_line_section, DW_FORM_line_strp);
- dwarf_uleb128(dwarf_line_section, dwarf_line.dir_size);
- for (i = 0; i < dwarf_line.dir_size; i++)
- dwarf_line_strp(dwarf_line_section, dwarf_line.dir_table[i]);
- dwarf_data1(dwarf_line_section, 2); /* col */
- dwarf_uleb128(dwarf_line_section, DW_LNCT_path);
- dwarf_uleb128(dwarf_line_section, DW_FORM_line_strp);
- dwarf_uleb128(dwarf_line_section, DW_LNCT_directory_index);
- dwarf_uleb128(dwarf_line_section, DW_FORM_udata);
- dwarf_uleb128(dwarf_line_section, dwarf_line.filename_size);
- for (i = 0; i < dwarf_line.filename_size; i++) {
- dwarf_line_strp(dwarf_line_section,
- dwarf_line.filename_table[i].name);
- dwarf_uleb128(dwarf_line_section,
- dwarf_line.filename_table[i].dir_entry);
- }
- }
- else {
- int len;
-
- for (i = 0; i < dwarf_line.dir_size; i++) {
- len = strlen(dwarf_line.dir_table[i]) + 1;
- ptr = section_ptr_add(dwarf_line_section, len);
- memmove(ptr, dwarf_line.dir_table[i], len);
- }
- dwarf_data1(dwarf_line_section, 0); /* end dir */
- for (i = 0; i < dwarf_line.filename_size; i++) {
- len = strlen(dwarf_line.filename_table[i].name) + 1;
- ptr = section_ptr_add(dwarf_line_section, len);
- memmove(ptr, dwarf_line.filename_table[i].name, len);
- dwarf_uleb128(dwarf_line_section,
- dwarf_line.filename_table[i].dir_entry);
- dwarf_uleb128(dwarf_line_section, 0); /* time */
- dwarf_uleb128(dwarf_line_section, 0); /* size */
- }
- dwarf_data1(dwarf_line_section, 0); /* end file */
- }
- for (i = 0; i < dwarf_line.dir_size; i++)
- tcc_free(dwarf_line.dir_table[i]);
- tcc_free(dwarf_line.dir_table);
- for (i = 0; i < dwarf_line.filename_size; i++)
- tcc_free(dwarf_line.filename_table[i].name);
- tcc_free(dwarf_line.filename_table);
-
- dwarf_line_op(s1, 0); // extended
- dwarf_uleb128_op(s1, 1); // extended size
- dwarf_line_op(s1, DW_LNE_end_sequence);
- i = (s1->dwarf >= 5) * 2;
- write32le(&dwarf_line_section->data[dwarf_line.start + 6 + i],
- dwarf_line_section->data_offset - dwarf_line.start - (10 + i));
- section_ptr_add(dwarf_line_section, 3);
- dwarf_reloc(dwarf_line_section, section_sym, R_DATA_PTR);
- ptr = section_ptr_add(dwarf_line_section, dwarf_line.line_size - 3);
- memmove(ptr - 3, dwarf_line.line_data, dwarf_line.line_size);
- tcc_free(dwarf_line.line_data);
- write32le(dwarf_line_section->data + dwarf_line.start,
- dwarf_line_section->data_offset - dwarf_line.start - 4);
- }
- else
- {
- put_stabs_r(s1, NULL, N_SO, 0, 0,
- text_section->data_offset, text_section, section_sym);
- }
- tcc_free(debug_hash);
- debug_next_type = 0;
-}
-
-static BufferedFile* put_new_file(TCCState *s1)
-{
- BufferedFile *f = file;
- /* use upper file if from inline ":asm:" */
- if (f->filename[0] == ':')
- f = f->prev;
- if (f && new_file) {
- new_file = last_line_num = 0;
- if (s1->dwarf)
- dwarf_file(s1);
- else
- put_stabs_r(s1, f->filename, N_SOL, 0, 0, ind, text_section, section_sym);
- }
- return f;
-}
-
-/* put alternative filename */
-ST_FUNC void tcc_debug_putfile(TCCState *s1, const char *filename)
-{
- if (0 == strcmp(file->filename, filename))
- return;
- pstrcpy(file->filename, sizeof(file->filename), filename);
- if (!s1->do_debug)
- return;
- if (s1->dwarf)
- dwarf_file(s1);
- new_file = 1;
-}
-
-/* begin of #include */
-ST_FUNC void tcc_debug_bincl(TCCState *s1)
-{
- if (!s1->do_debug)
- return;
- if (s1->dwarf)
- dwarf_file(s1);
- else
- put_stabs(s1, file->filename, N_BINCL, 0, 0, 0);
- new_file = 1;
-}
-
-/* end of #include */
-ST_FUNC void tcc_debug_eincl(TCCState *s1)
-{
- if (!s1->do_debug)
- return;
- if (s1->dwarf)
- dwarf_file(s1);
- else
- put_stabn(s1, N_EINCL, 0, 0, 0);
- new_file = 1;
-}
-
-/* generate line number info */
-ST_FUNC void tcc_debug_line(TCCState *s1)
-{
- BufferedFile *f;
-
- if (!s1->do_debug)
- return;
- if (cur_text_section != text_section)
- return;
- f = put_new_file(s1);
- if (!f)
- return;
- if (last_line_num == f->line_num)
- return;
- last_line_num = f->line_num;
-
- if (s1->dwarf) {
- int len_pc = (ind - dwarf_line.last_pc) / DWARF_MIN_INSTR_LEN;
- int len_line = f->line_num - dwarf_line.last_line;
- int n = len_pc * DWARF_LINE_RANGE + len_line + DWARF_OPCODE_BASE - DWARF_LINE_BASE;
-
- if (dwarf_line.cur_file != dwarf_line.last_file) {
- dwarf_line.last_file = dwarf_line.cur_file;
- dwarf_line_op(s1, DW_LNS_set_file);
- dwarf_uleb128_op(s1, dwarf_line.cur_file);
- }
- if (len_pc &&
- len_line >= DWARF_LINE_BASE && len_line <= (DWARF_OPCODE_BASE + DWARF_LINE_BASE) &&
- n >= DWARF_OPCODE_BASE && n <= 255)
- dwarf_line_op(s1, n);
- else {
- if (len_pc) {
- n = len_pc * DWARF_LINE_RANGE + 0 + DWARF_OPCODE_BASE - DWARF_LINE_BASE;
- if (n >= DWARF_OPCODE_BASE && n <= 255)
- dwarf_line_op(s1, n);
- else {
- dwarf_line_op(s1, DW_LNS_advance_pc);
- dwarf_uleb128_op(s1, len_pc);
- }
- }
- if (len_line) {
- n = 0 * DWARF_LINE_RANGE + len_line + DWARF_OPCODE_BASE - DWARF_LINE_BASE;
- if (len_line >= DWARF_LINE_BASE && len_line <= (DWARF_OPCODE_BASE + DWARF_LINE_BASE) &&
- n >= DWARF_OPCODE_BASE && n <= 255)
- dwarf_line_op(s1, n);
- else {
- dwarf_line_op(s1, DW_LNS_advance_line);
- dwarf_sleb128_op(s1, len_line);
- }
- }
- }
- dwarf_line.last_pc = ind;
- dwarf_line.last_line = f->line_num;
- }
- else
- {
- if (func_ind != -1) {
- put_stabn(s1, N_SLINE, 0, f->line_num, ind - func_ind);
- } else {
- /* from tcc_assemble */
- put_stabs_r(s1, NULL, N_SLINE, 0, f->line_num, ind, text_section, section_sym);
- }
- }
-}
-
-static void tcc_debug_stabs (TCCState *s1, const char *str, int type, unsigned long value,
- Section *sec, int sym_index, int info)
-{
- struct debug_sym *s;
-
- if (debug_info) {
- debug_info->sym =
- (struct debug_sym *)tcc_realloc (debug_info->sym,
- sizeof(struct debug_sym) *
- (debug_info->n_sym + 1));
- s = debug_info->sym + debug_info->n_sym++;
- s->type = type;
- s->value = value;
- s->str = tcc_strdup(str);
- s->sec = sec;
- s->sym_index = sym_index;
- s->info = info;
- s->file = dwarf_line.cur_file;
- s->line = file->line_num;
- }
- else if (sec)
- put_stabs_r (s1, str, type, 0, 0, value, sec, sym_index);
- else
- put_stabs (s1, str, type, 0, 0, value);
-}
-
-ST_FUNC void tcc_debug_stabn(TCCState *s1, int type, int value)
-{
- if (!s1->do_debug)
- return;
- if (type == N_LBRAC) {
- struct _debug_info *info =
- (struct _debug_info *) tcc_mallocz(sizeof (*info));
-
- info->start = value;
- info->parent = debug_info;
- if (debug_info) {
- if (debug_info->child) {
- if (debug_info->child->last)
- debug_info->child->last->next = info;
- else
- debug_info->child->next = info;
- debug_info->child->last = info;
- }
- else
- debug_info->child = info;
- }
- else
- debug_info_root = info;
- debug_info = info;
- }
- else {
- debug_info->end = value;
- debug_info = debug_info->parent;
- }
-}
-
-static int tcc_debug_find(TCCState *s1, Sym *t, int dwarf)
-{
- int i;
-
- if (!debug_info && dwarf &&
- (t->type.t & VT_BTYPE) == VT_STRUCT && t->c == -1) {
- for (i = 0; i < n_debug_anon_hash; i++)
- if (t == debug_anon_hash[i].type)
- return 0;
- debug_anon_hash = (struct _debug_anon_hash *)
- tcc_realloc (debug_anon_hash,
- (n_debug_anon_hash + 1) * sizeof(*debug_anon_hash));
- debug_anon_hash[n_debug_anon_hash].n_debug_type = 0;
- debug_anon_hash[n_debug_anon_hash].debug_type = NULL;
- debug_anon_hash[n_debug_anon_hash++].type = t;
- return 0;
- }
- for (i = 0; i < n_debug_hash; i++)
- if (t == debug_hash[i].type)
- return debug_hash[i].debug_type;
- return -1;
-}
-
-static int tcc_get_dwarf_info(TCCState *s1, Sym *s);
-
-static void tcc_debug_check_anon(TCCState *s1, Sym *t, int debug_type)
-{
- int i;
-
- if (!debug_info && (t->type.t & VT_BTYPE) == VT_STRUCT && t->type.ref->c == -1)
- for (i = 0; i < n_debug_anon_hash; i++)
- if (t->type.ref == debug_anon_hash[i].type) {
- debug_anon_hash[i].debug_type =
- tcc_realloc(debug_anon_hash[i].debug_type,
- (debug_anon_hash[i].n_debug_type + 1) * sizeof(int));
- debug_anon_hash[i].debug_type[debug_anon_hash[i].n_debug_type++] =
- debug_type;
- }
-}
-
-ST_FUNC void tcc_debug_fix_anon(TCCState *s1, CType *t)
-{
- int i, j, debug_type;
-
- if (!s1->do_debug || !s1->dwarf || debug_info)
- return;
- if ((t->t & VT_BTYPE) == VT_STRUCT && t->ref->c != -1)
- for (i = 0; i < n_debug_anon_hash; i++)
- if (t->ref == debug_anon_hash[i].type) {
- Sym sym = {0}; sym .type = *t ;
-
- /* Trick to not hash this struct */
- debug_info = (struct _debug_info *) t;
- debug_type = tcc_get_dwarf_info(s1, &sym);
- debug_info = NULL;
- for (j = 0; j < debug_anon_hash[i].n_debug_type; j++)
- write32le(dwarf_info_section->data +
- debug_anon_hash[i].debug_type[j],
- debug_type - dwarf_info.start);
- tcc_free(debug_anon_hash[i].debug_type);
- n_debug_anon_hash--;
- for (; i < n_debug_anon_hash; i++)
- debug_anon_hash[i] = debug_anon_hash[i + 1];
- }
-}
-
-static int tcc_debug_add(TCCState *s1, Sym *t, int dwarf)
-{
- int offset = dwarf ? dwarf_info_section->data_offset : ++debug_next_type;
- debug_hash = (struct _debug_hash *)
- tcc_realloc (debug_hash,
- (n_debug_hash + 1) * sizeof(*debug_hash));
- debug_hash[n_debug_hash].debug_type = offset;
- debug_hash[n_debug_hash++].type = t;
- return offset;
-}
-
-static void tcc_debug_remove(TCCState *s1, Sym *t)
-{
- int i;
-
- for (i = 0; i < n_debug_hash; i++)
- if (t == debug_hash[i].type) {
- n_debug_hash--;
- for (; i < n_debug_hash; i++)
- debug_hash[i] = debug_hash[i+1];
- }
-}
-
-#define STRUCT_NODEBUG(s) \
- (s->a.nodebug || \
- ((s->v & ~SYM_FIELD) >= SYM_FIRST_ANOM && \
- ((s->type.t & VT_BTYPE) == VT_BYTE || \
- (s->type.t & VT_BTYPE) == VT_BOOL || \
- (s->type.t & VT_BTYPE) == VT_SHORT || \
- (s->type.t & VT_BTYPE) == VT_INT || \
- (s->type.t & VT_BTYPE) == VT_LLONG)))
-
-static void tcc_get_debug_info(TCCState *s1, Sym *s, CString *result)
-{
- int type;
- int n = 0;
- int debug_type = -1;
- Sym *t = s;
- CString str;
-
- for (;;) {
- type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE | VT_VLA);
- if ((type & VT_BTYPE) != VT_BYTE)
- type &= ~VT_DEFSIGN;
- if (type == VT_PTR || type == (VT_PTR | VT_ARRAY))
- n++, t = t->type.ref;
- else
- break;
- }
- if ((type & VT_BTYPE) == VT_STRUCT) {
- Sym *e = t;
-
- t = t->type.ref;
- debug_type = tcc_debug_find(s1, t, 0);
- if (debug_type == -1) {
- debug_type = tcc_debug_add(s1, t, 0);
- cstr_new (&str);
- cstr_printf (&str, "%s:T%d=%c%d",
- (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
- ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL),
- debug_type,
- IS_UNION (t->type.t) ? 'u' : 's',
- t->c);
- while (t->next) {
- int pos, size, align;
-
- t = t->next;
- if (STRUCT_NODEBUG(t))
- continue;
- cstr_printf (&str, "%s:",
- get_tok_str(t->v & ~SYM_FIELD, NULL));
- tcc_get_debug_info (s1, t, &str);
- if (t->type.t & VT_BITFIELD) {
- pos = t->c * 8 + BIT_POS(t->type.t);
- size = BIT_SIZE(t->type.t);
- }
- else {
- pos = t->c * 8;
- size = type_size(&t->type, &align) * 8;
- }
- cstr_printf (&str, ",%d,%d;", pos, size);
- }
- cstr_printf (&str, ";");
- tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0);
- cstr_free (&str);
- if (debug_info)
- tcc_debug_remove(s1, e);
- }
- }
- else if (IS_ENUM(type)) {
- Sym *e = t = t->type.ref;
-
- debug_type = tcc_debug_find(s1, t, 0);
- if (debug_type == -1) {
- debug_type = tcc_debug_add(s1, t, 0);
- cstr_new (&str);
- cstr_printf (&str, "%s:T%d=e",
- (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
- ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL),
- debug_type);
- while (t->next) {
- t = t->next;
- cstr_printf (&str, "%s:",
- (t->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
- ? "" : get_tok_str(t->v & ~SYM_FIELD, NULL));
- cstr_printf (&str, e->type.t & VT_UNSIGNED ? "%u," : "%d,",
- (int)t->enum_val);
- }
- cstr_printf (&str, ";");
- tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0);
- cstr_free (&str);
- if (debug_info)
- tcc_debug_remove(s1, e);
- }
- }
- else if ((type & VT_BTYPE) != VT_FUNC) {
- type &= ~VT_STRUCT_MASK;
- for (debug_type = 1; debug_type <= N_DEFAULT_DEBUG; debug_type++)
- if (default_debug[debug_type - 1].type == type)
- break;
- if (debug_type > N_DEFAULT_DEBUG)
- return;
- }
- if (n > 0)
- cstr_printf (result, "%d=", ++debug_next_type);
- t = s;
- for (;;) {
- type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE | VT_VLA);
- if ((type & VT_BTYPE) != VT_BYTE)
- type &= ~VT_DEFSIGN;
- if (type == VT_PTR)
- cstr_printf (result, "%d=*", ++debug_next_type);
- else if (type == (VT_PTR | VT_ARRAY))
- cstr_printf (result, "%d=ar1;0;%d;",
- ++debug_next_type, t->type.ref->c - 1);
- else if (type == VT_FUNC) {
- cstr_printf (result, "%d=f", ++debug_next_type);
- tcc_get_debug_info (s1, t->type.ref, result);
- return;
- }
- else
- break;
- t = t->type.ref;
- }
- cstr_printf (result, "%d", debug_type);
-}
-
-static int tcc_get_dwarf_info(TCCState *s1, Sym *s)
-{
- int type;
- int debug_type = -1;
- Sym *e, *t = s;
- int i;
- int last_pos = -1;
- int retval;
-
- if (new_file)
- put_new_file(s1);
- for (;;) {
- type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE | VT_VLA);
- if ((type & VT_BTYPE) != VT_BYTE)
- type &= ~VT_DEFSIGN;
- if (type == VT_PTR || type == (VT_PTR | VT_ARRAY))
- t = t->type.ref;
- else
- break;
- }
- if ((type & VT_BTYPE) == VT_STRUCT) {
- t = t->type.ref;
- debug_type = tcc_debug_find(s1, t, 1);
- if (debug_type == -1) {
- int pos_sib = 0, i, *pos_type;
-
- debug_type = tcc_debug_add(s1, t, 1);
- e = t;
- i = 0;
- while (e->next) {
- e = e->next;
- if (STRUCT_NODEBUG(e))
- continue;
- i++;
- }
- pos_type = (int *) tcc_malloc(i * sizeof(int));
- dwarf_data1(dwarf_info_section,
- IS_UNION (t->type.t)
- ? t->next ? DWARF_ABBREV_UNION_TYPE
- : DWARF_ABBREV_UNION_EMPTY_TYPE
- : t->next ? DWARF_ABBREV_STRUCTURE_TYPE
- : DWARF_ABBREV_STRUCTURE_EMPTY_TYPE);
- dwarf_strp(dwarf_info_section,
- (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
- ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL));
- dwarf_uleb128(dwarf_info_section, t->c);
- dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
- dwarf_uleb128(dwarf_info_section, file->line_num);
- if (t->next) {
- pos_sib = dwarf_info_section->data_offset;
- dwarf_data4(dwarf_info_section, 0);
- }
- e = t;
- i = 0;
- while (e->next) {
- e = e->next;
- if (STRUCT_NODEBUG(e))
- continue;
- dwarf_data1(dwarf_info_section,
- e->type.t & VT_BITFIELD ? DWARF_ABBREV_MEMBER_BF
- : DWARF_ABBREV_MEMBER);
- dwarf_strp(dwarf_info_section,
- get_tok_str(e->v & ~SYM_FIELD, NULL));
- dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
- dwarf_uleb128(dwarf_info_section, file->line_num);
- pos_type[i++] = dwarf_info_section->data_offset;
- dwarf_data4(dwarf_info_section, 0);
- if (e->type.t & VT_BITFIELD) {
- int pos = e->c * 8 + BIT_POS(e->type.t);
- int size = BIT_SIZE(e->type.t);
-
- dwarf_uleb128(dwarf_info_section, size);
- dwarf_uleb128(dwarf_info_section, pos);
- }
- else
- dwarf_uleb128(dwarf_info_section, e->c);
- }
- if (t->next) {
- dwarf_data1(dwarf_info_section, 0);
- write32le(dwarf_info_section->data + pos_sib,
- dwarf_info_section->data_offset - dwarf_info.start);
- }
- e = t;
- i = 0;
- while (e->next) {
- e = e->next;
- if (STRUCT_NODEBUG(e))
- continue;
- type = tcc_get_dwarf_info(s1, e);
- tcc_debug_check_anon(s1, e, pos_type[i]);
- write32le(dwarf_info_section->data + pos_type[i++],
- type - dwarf_info.start);
- }
- tcc_free(pos_type);
- if (debug_info)
- tcc_debug_remove(s1, t);
- }
- }
- else if (IS_ENUM(type)) {
- t = t->type.ref;
- debug_type = tcc_debug_find(s1, t, 1);
- if (debug_type == -1) {
- int pos_sib, pos_type;
- Sym sym = {0}; sym.type.t = VT_INT | (type & VT_UNSIGNED);
-
- pos_type = tcc_get_dwarf_info(s1, &sym);
- debug_type = tcc_debug_add(s1, t, 1);
- dwarf_data1(dwarf_info_section, DWARF_ABBREV_ENUMERATION_TYPE);
- dwarf_strp(dwarf_info_section,
- (t->v & ~SYM_STRUCT) >= SYM_FIRST_ANOM
- ? "" : get_tok_str(t->v & ~SYM_STRUCT, NULL));
- dwarf_data1(dwarf_info_section,
- type & VT_UNSIGNED ? DW_ATE_unsigned : DW_ATE_signed );
- dwarf_data1(dwarf_info_section, 4);
- dwarf_data4(dwarf_info_section, pos_type - dwarf_info.start);
- dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
- dwarf_uleb128(dwarf_info_section, file->line_num);
- pos_sib = dwarf_info_section->data_offset;
- dwarf_data4(dwarf_info_section, 0);
- e = t;
- while (e->next) {
- e = e->next;
- dwarf_data1(dwarf_info_section,
- type & VT_UNSIGNED ? DWARF_ABBREV_ENUMERATOR_UNSIGNED
- : DWARF_ABBREV_ENUMERATOR_SIGNED);
- dwarf_strp(dwarf_info_section,
- (e->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
- ? "" : get_tok_str(e->v & ~SYM_FIELD, NULL));
- if (type & VT_UNSIGNED)
- dwarf_uleb128(dwarf_info_section, e->enum_val);
- else
- dwarf_sleb128(dwarf_info_section, e->enum_val);
- }
- dwarf_data1(dwarf_info_section, 0);
- write32le(dwarf_info_section->data + pos_sib,
- dwarf_info_section->data_offset - dwarf_info.start);
- if (debug_info)
- tcc_debug_remove(s1, t);
- }
- }
- else if ((type & VT_BTYPE) != VT_FUNC) {
- type &= ~VT_STRUCT_MASK;
- for (i = 1; i <= N_DEFAULT_DEBUG; i++)
- if (default_debug[i - 1].type == type)
- break;
- if (i > N_DEFAULT_DEBUG)
- return 0;
- debug_type = dwarf_info.base_type_used[i - 1];
- if (debug_type == 0) {
- char name[100];
-
- debug_type = dwarf_info_section->data_offset;
- dwarf_data1(dwarf_info_section, DWARF_ABBREV_BASE_TYPE);
- dwarf_uleb128(dwarf_info_section, default_debug[i - 1].size);
- dwarf_data1(dwarf_info_section, default_debug[i - 1].encoding);
- strncpy(name, default_debug[i - 1].name, sizeof(name) -1);
- *strchr(name, ':') = 0;
- dwarf_strp(dwarf_info_section, name);
- dwarf_info.base_type_used[i - 1] = debug_type;
- }
- }
- retval = debug_type;
- e = NULL;
- t = s;
- for (;;) {
- type = t->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE | VT_VLA);
- if ((type & VT_BTYPE) != VT_BYTE)
- type &= ~VT_DEFSIGN;
- if (type == VT_PTR) {
- i = dwarf_info_section->data_offset;
- if (retval == debug_type)
- retval = i;
- dwarf_data1(dwarf_info_section, DWARF_ABBREV_POINTER);
- dwarf_data1(dwarf_info_section, PTR_SIZE);
- if (last_pos != -1) {
- tcc_debug_check_anon(s1, e, last_pos);
- write32le(dwarf_info_section->data + last_pos,
- i - dwarf_info.start);
- }
- last_pos = dwarf_info_section->data_offset;
- e = t->type.ref;
- dwarf_data4(dwarf_info_section, 0);
- }
- else if (type == (VT_PTR | VT_ARRAY)) {
- int sib_pos, sub_type;
-#if LONG_SIZE == 4
- Sym sym = {0}; sym.type.t = VT_LONG | VT_INT | VT_UNSIGNED;
-#else
- Sym sym = {0}; sym.type.t = VT_LLONG | VT_LONG | VT_UNSIGNED;
-#endif
-
- sub_type = tcc_get_dwarf_info(s1, &sym);
- i = dwarf_info_section->data_offset;
- if (retval == debug_type)
- retval = i;
- dwarf_data1(dwarf_info_section, DWARF_ABBREV_ARRAY_TYPE);
- if (last_pos != -1) {
- tcc_debug_check_anon(s1, e, last_pos);
- write32le(dwarf_info_section->data + last_pos,
- i - dwarf_info.start);
- }
- last_pos = dwarf_info_section->data_offset;
- e = t->type.ref;
- dwarf_data4(dwarf_info_section, 0);
- sib_pos = dwarf_info_section->data_offset;
- dwarf_data4(dwarf_info_section, 0);
- for (;;) {
- dwarf_data1(dwarf_info_section, DWARF_ABBREV_SUBRANGE_TYPE);
- dwarf_data4(dwarf_info_section, sub_type - dwarf_info.start);
- dwarf_uleb128(dwarf_info_section, t->type.ref->c - 1);
- s = t->type.ref;
- type = s->type.t & ~(VT_STORAGE | VT_CONSTANT | VT_VOLATILE);
- if (type != (VT_PTR | VT_ARRAY))
- break;
- t = s;
- }
- dwarf_data1(dwarf_info_section, 0);
- write32le(dwarf_info_section->data + sib_pos,
- dwarf_info_section->data_offset - dwarf_info.start);
- }
- else if (type == VT_FUNC) {
- int sib_pos = 0, *pos_type;
- Sym *f;
-
- i = dwarf_info_section->data_offset;
- debug_type = tcc_get_dwarf_info(s1, t->type.ref);
- if (retval == debug_type)
- retval = i;
- dwarf_data1(dwarf_info_section,
- t->type.ref->next ? DWARF_ABBREV_SUBROUTINE_TYPE
- : DWARF_ABBREV_SUBROUTINE_EMPTY_TYPE);
- if (last_pos != -1) {
- tcc_debug_check_anon(s1, e, last_pos);
- write32le(dwarf_info_section->data + last_pos,
- i - dwarf_info.start);
- }
- last_pos = dwarf_info_section->data_offset;
- e = t->type.ref;
- dwarf_data4(dwarf_info_section, 0);
- if (t->type.ref->next) {
- sib_pos = dwarf_info_section->data_offset;
- dwarf_data4(dwarf_info_section, 0);
- }
- f = t->type.ref;
- i = 0;
- while (f->next) {
- f = f->next;
- i++;
- }
- pos_type = (int *) tcc_malloc(i * sizeof(int));
- f = t->type.ref;
- i = 0;
- while (f->next) {
- f = f->next;
- dwarf_data1(dwarf_info_section, DWARF_ABBREV_FORMAL_PARAMETER2);
- pos_type[i++] = dwarf_info_section->data_offset;
- dwarf_data4(dwarf_info_section, 0);
- }
- if (t->type.ref->next) {
- dwarf_data1(dwarf_info_section, 0);
- write32le(dwarf_info_section->data + sib_pos,
- dwarf_info_section->data_offset - dwarf_info.start);
- }
- f = t->type.ref;
- i = 0;
- while (f->next) {
- f = f->next;
- type = tcc_get_dwarf_info(s1, f);
- tcc_debug_check_anon(s1, f, pos_type[i]);
- write32le(dwarf_info_section->data + pos_type[i++],
- type - dwarf_info.start);
- }
- tcc_free(pos_type);
- }
- else {
- if (last_pos != -1) {
- tcc_debug_check_anon(s1, e, last_pos);
- write32le(dwarf_info_section->data + last_pos,
- debug_type - dwarf_info.start);
- }
- break;
- }
- t = t->type.ref;
- }
- return retval;
-}
-
-static void tcc_debug_finish (TCCState *s1, struct _debug_info *cur)
-{
- while (cur) {
- struct _debug_info *next = cur->next;
- int i;
-
- if (s1->dwarf) {
-
- for (i = cur->n_sym - 1; i >= 0; i--) {
- struct debug_sym *s = &cur->sym[i];
-
- dwarf_data1(dwarf_info_section,
- s->type == N_PSYM
- ? DWARF_ABBREV_FORMAL_PARAMETER
- : s->type == N_GSYM
- ? DWARF_ABBREV_VARIABLE_EXTERNAL
- : s->type == N_STSYM
- ? DWARF_ABBREV_VARIABLE_STATIC
- : DWARF_ABBREV_VARIABLE_LOCAL);
- dwarf_strp(dwarf_info_section, s->str);
- if (s->type == N_GSYM || s->type == N_STSYM) {
- dwarf_uleb128(dwarf_info_section, s->file);
- dwarf_uleb128(dwarf_info_section, s->line);
- }
- dwarf_data4(dwarf_info_section, s->info - dwarf_info.start);
- if (s->type == N_GSYM || s->type == N_STSYM) {
- /* global/static */
- if (s->type == N_GSYM)
- dwarf_data1(dwarf_info_section, 1);
- dwarf_data1(dwarf_info_section, PTR_SIZE + 1);
- dwarf_data1(dwarf_info_section, DW_OP_addr);
- if (s->type == N_STSYM)
- dwarf_reloc(dwarf_info_section, section_sym, R_DATA_PTR);
-#if PTR_SIZE == 4
- dwarf_data4(dwarf_info_section, s->value);
-#else
- dwarf_data8(dwarf_info_section, s->value);
-#endif
- }
- else {
- /* param/local */
- dwarf_data1(dwarf_info_section, dwarf_sleb128_size(s->value) + 1);
- dwarf_data1(dwarf_info_section, DW_OP_fbreg);
- dwarf_sleb128(dwarf_info_section, s->value);
- }
- tcc_free (s->str);
- }
- tcc_free (cur->sym);
- dwarf_data1(dwarf_info_section,
- cur->child ? DWARF_ABBREV_LEXICAL_BLOCK
- : DWARF_ABBREV_LEXICAL_EMPTY_BLOCK);
- dwarf_reloc(dwarf_info_section, section_sym, R_DATA_PTR);
-#if PTR_SIZE == 4
- dwarf_data4(dwarf_info_section, func_ind + cur->start);
- dwarf_data4(dwarf_info_section, cur->end - cur->start);
-#else
- dwarf_data8(dwarf_info_section, func_ind + cur->start);
- dwarf_data8(dwarf_info_section, cur->end - cur->start);
-#endif
- tcc_debug_finish (s1, cur->child);
- if (cur->child)
- dwarf_data1(dwarf_info_section, 0);
- }
- else
- {
- for (i = 0; i < cur->n_sym; i++) {
- struct debug_sym *s = &cur->sym[i];
-
- if (s->sec)
- put_stabs_r(s1, s->str, s->type, 0, 0, s->value,
- s->sec, s->sym_index);
- else
- put_stabs(s1, s->str, s->type, 0, 0, s->value);
- tcc_free (s->str);
- }
- tcc_free (cur->sym);
- put_stabn(s1, N_LBRAC, 0, 0, cur->start);
- tcc_debug_finish (s1, cur->child);
- put_stabn(s1, N_RBRAC, 0, 0, cur->end);
- }
- tcc_free (cur);
- cur = next;
- }
-}
-
-ST_FUNC void tcc_add_debug_info(TCCState *s1, int param, Sym *s, Sym *e)
-{
- CString debug_str;
- if (!s1->do_debug)
- return;
- cstr_new (&debug_str);
- for (; s != e; s = s->prev) {
- if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL)
- continue;
- if (s1->dwarf) {
- tcc_debug_stabs(s1, get_tok_str(s->v, NULL),
- param ? N_PSYM : N_LSYM, s->c, NULL, 0,
- tcc_get_dwarf_info(s1, s));
- }
- else
- {
- cstr_reset (&debug_str);
- cstr_printf (&debug_str, "%s:%s", get_tok_str(s->v, NULL),
- param ? "p" : "");
- tcc_get_debug_info(s1, s, &debug_str);
- tcc_debug_stabs(s1, debug_str.data, param ? N_PSYM : N_LSYM,
- s->c, NULL, 0, 0);
- }
- }
- cstr_free (&debug_str);
-}
-
-/* put function symbol */
-ST_FUNC void tcc_debug_funcstart(TCCState *s1, Sym *sym)
-{
- CString debug_str;
- BufferedFile *f;
-
- if (!s1->do_debug)
- return;
- debug_info_root = NULL;
- debug_info = NULL;
- tcc_debug_stabn(s1, N_LBRAC, ind - func_ind);
- f = put_new_file(s1);
- if (!f)
- return;
-
- if (s1->dwarf) {
- tcc_debug_line(s1);
- dwarf_info.func = sym;
- dwarf_info.line = file->line_num;
- if (s1->do_backtrace) {
- int i, len;
-
- dwarf_line_op(s1, 0); // extended
- dwarf_uleb128_op(s1, strlen(funcname) + 2);
- dwarf_line_op(s1, DW_LNE_hi_user - 1);
- len = strlen(funcname) + 1;
- for (i = 0; i < len; i++)
- dwarf_line_op(s1, funcname[i]);
- }
- }
- else
- {
- cstr_new (&debug_str);
- cstr_printf(&debug_str, "%s:%c", funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
- tcc_get_debug_info(s1, sym->type.ref, &debug_str);
- put_stabs_r(s1, debug_str.data, N_FUN, 0, f->line_num, 0, cur_text_section, sym->c);
- cstr_free (&debug_str);
- tcc_debug_line(s1);
- }
-}
-
-ST_FUNC void tcc_debug_prolog_epilog(TCCState *s1, int value)
-{
- if (!s1->do_debug)
- return;
- if (s1->dwarf) {
- dwarf_line_op(s1, value == 0 ? DW_LNS_set_prologue_end
- : DW_LNS_set_epilogue_begin);
- }
-}
-
-/* put function size */
-ST_FUNC void tcc_debug_funcend(TCCState *s1, int size)
-{
- /* lldb does not like function end and next function start at same pc */
- int min_instr_len;
-
- if (!s1->do_debug)
- return;
- min_instr_len = dwarf_line.last_pc == ind ? 0 : DWARF_MIN_INSTR_LEN;
- ind -= min_instr_len;
- tcc_debug_line(s1);
- ind += min_instr_len;
- tcc_debug_stabn(s1, N_RBRAC, size);
- if (s1->dwarf) {
- int func_sib = 0;
- Sym *sym = dwarf_info.func;
- int n_debug_info = tcc_get_dwarf_info(s1, sym->type.ref);
-
- dwarf_data1(dwarf_info_section,
- sym->type.t & VT_STATIC ? DWARF_ABBREV_SUBPROGRAM_STATIC
- : DWARF_ABBREV_SUBPROGRAM_EXTERNAL);
- if ((sym->type.t & VT_STATIC) == 0)
- dwarf_data1(dwarf_info_section, 1);
- dwarf_strp(dwarf_info_section, funcname);
- dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
- dwarf_uleb128(dwarf_info_section, dwarf_info.line);
- tcc_debug_check_anon(s1, sym->type.ref, dwarf_info_section->data_offset);
- dwarf_data4(dwarf_info_section, n_debug_info - dwarf_info.start);
- dwarf_reloc(dwarf_info_section, section_sym, R_DATA_PTR);
-#if PTR_SIZE == 4
- dwarf_data4(dwarf_info_section, func_ind); // low_pc
- dwarf_data4(dwarf_info_section, size); // high_pc
-#else
- dwarf_data8(dwarf_info_section, func_ind); // low_pc
- dwarf_data8(dwarf_info_section, size); // high_pc
-#endif
- func_sib = dwarf_info_section->data_offset;
- dwarf_data4(dwarf_info_section, 0); // sibling
- dwarf_data1(dwarf_info_section, 1);
-#if defined(TCC_TARGET_I386)
- dwarf_data1(dwarf_info_section, DW_OP_reg5); // ebp
-#elif defined(TCC_TARGET_X86_64)
- dwarf_data1(dwarf_info_section, DW_OP_reg6); // rbp
-#elif defined TCC_TARGET_ARM
- dwarf_data1(dwarf_info_section, DW_OP_reg13); // sp
-#elif defined TCC_TARGET_ARM64
- dwarf_data1(dwarf_info_section, DW_OP_reg29); // reg 29
-#elif defined TCC_TARGET_RISCV64
- dwarf_data1(dwarf_info_section, DW_OP_reg8); // r8(s0)
-#else
- dwarf_data1(dwarf_info_section, DW_OP_call_frame_cfa);
-#endif
- tcc_debug_finish (s1, debug_info_root);
- dwarf_data1(dwarf_info_section, 0);
- write32le(dwarf_info_section->data + func_sib,
- dwarf_info_section->data_offset - dwarf_info.start);
- }
- else
- {
- tcc_debug_finish (s1, debug_info_root);
- }
- debug_info_root = 0;
-}
-
-
-ST_FUNC void tcc_debug_extern_sym(TCCState *s1, Sym *sym, int sh_num, int sym_bind, int sym_type)
-{
- if (!s1->do_debug)
- return;
- if (sym_type == STT_FUNC || sym->v >= SYM_FIRST_ANOM)
- return;
- if (s1->dwarf) {
- int debug_type;
-
- debug_type = tcc_get_dwarf_info(s1, sym);
- dwarf_data1(dwarf_info_section,
- sym_bind == STB_GLOBAL
- ? DWARF_ABBREV_VARIABLE_EXTERNAL
- : DWARF_ABBREV_VARIABLE_STATIC);
- dwarf_strp(dwarf_info_section, get_tok_str(sym->v, NULL));
- dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
- dwarf_uleb128(dwarf_info_section, file->line_num);
- tcc_debug_check_anon(s1, sym, dwarf_info_section->data_offset);
- dwarf_data4(dwarf_info_section, debug_type - dwarf_info.start);
- if (sym_bind == STB_GLOBAL)
- dwarf_data1(dwarf_info_section, 1);
- dwarf_data1(dwarf_info_section, PTR_SIZE + 1);
- dwarf_data1(dwarf_info_section, DW_OP_addr);
- greloca(dwarf_info_section, sym, dwarf_info_section->data_offset,
- R_DATA_PTR, 0);
-#if PTR_SIZE == 4
- dwarf_data4(dwarf_info_section, 0);
-#else
- dwarf_data8(dwarf_info_section, 0);
-#endif
- }
- else
- {
- Section *s = sh_num == SHN_COMMON ? common_section
- : s1->sections[sh_num];
- CString str;
-
- cstr_new (&str);
- cstr_printf (&str, "%s:%c",
- get_tok_str(sym->v, NULL),
- sym_bind == STB_GLOBAL ? 'G' : func_ind != -1 ? 'V' : 'S'
- );
- tcc_get_debug_info(s1, sym, &str);
- if (sym_bind == STB_GLOBAL)
- tcc_debug_stabs(s1, str.data, N_GSYM, 0, NULL, 0, 0);
- else
- tcc_debug_stabs(s1, str.data,
- (sym->type.t & VT_STATIC) && data_section == s
- ? N_STSYM : N_LCSYM, 0, s, sym->c, 0);
- cstr_free (&str);
- }
-}
-
-ST_FUNC void tcc_debug_typedef(TCCState *s1, Sym *sym)
-{
- if (!s1->do_debug)
- return;
- if (s1->dwarf) {
- int debug_type;
-
- debug_type = tcc_get_dwarf_info(s1, sym);
- if (debug_type != -1) {
- dwarf_data1(dwarf_info_section, DWARF_ABBREV_TYPEDEF);
- dwarf_strp(dwarf_info_section, get_tok_str(sym->v & ~SYM_FIELD, NULL));
- dwarf_uleb128(dwarf_info_section, dwarf_line.cur_file);
- dwarf_uleb128(dwarf_info_section, file->line_num);
- tcc_debug_check_anon(s1, sym, dwarf_info_section->data_offset);
- dwarf_data4(dwarf_info_section, debug_type - dwarf_info.start);
- }
- }
- else
- {
- CString str;
- cstr_new (&str);
- cstr_printf (&str, "%s:t",
- (sym->v & ~SYM_FIELD) >= SYM_FIRST_ANOM
- ? "" : get_tok_str(sym->v & ~SYM_FIELD, NULL));
- tcc_get_debug_info(s1, sym, &str);
- tcc_debug_stabs(s1, str.data, N_LSYM, 0, NULL, 0, 0);
- cstr_free (&str);
- }
-}
-
-/* ------------------------------------------------------------------------- */
-/* for section layout see lib/tcov.c */
-
-ST_FUNC void tcc_tcov_block_end(TCCState *s1, int line);
-
-ST_FUNC void tcc_tcov_block_begin(TCCState *s1)
-{
- SValue sv;
- void *ptr;
- unsigned long last_offset = tcov_data.offset;
-
- tcc_tcov_block_end (tcc_state, 0);
- if (s1->test_coverage == 0 || nocode_wanted)
- return;
-
- if (tcov_data.last_file_name == 0 ||
- strcmp ((const char *)(tcov_section->data + tcov_data.last_file_name),
- file->true_filename) != 0) {
- char wd[1024];
- CString cstr;
-
- if (tcov_data.last_func_name)
- section_ptr_add(tcov_section, 1);
- if (tcov_data.last_file_name)
- section_ptr_add(tcov_section, 1);
- tcov_data.last_func_name = 0;
- cstr_new (&cstr);
- if (file->true_filename[0] == '/') {
- tcov_data.last_file_name = tcov_section->data_offset;
- cstr_printf (&cstr, "%s", file->true_filename);
- }
- else {
- getcwd (wd, sizeof(wd));
- tcov_data.last_file_name = tcov_section->data_offset + strlen(wd) + 1;
- cstr_printf (&cstr, "%s/%s", wd, file->true_filename);
- }
- ptr = section_ptr_add(tcov_section, cstr.size + 1);
- strcpy((char *)ptr, cstr.data);
-#ifdef _WIN32
- normalize_slashes((char *)ptr);
-#endif
- cstr_free (&cstr);
- }
- if (tcov_data.last_func_name == 0 ||
- strcmp ((const char *)(tcov_section->data + tcov_data.last_func_name),
- funcname) != 0) {
- size_t len;
-
- if (tcov_data.last_func_name)
- section_ptr_add(tcov_section, 1);
- tcov_data.last_func_name = tcov_section->data_offset;
- len = strlen (funcname);
- ptr = section_ptr_add(tcov_section, len + 1);
- strcpy((char *)ptr, funcname);
- section_ptr_add(tcov_section, -tcov_section->data_offset & 7);
- ptr = section_ptr_add(tcov_section, 8);
- write64le (ptr, file->line_num);
- }
- if (ind == tcov_data.ind && tcov_data.line == file->line_num)
- tcov_data.offset = last_offset;
- else {
- Sym label = {0};
- label.type.t = VT_LLONG | VT_STATIC;
-
- ptr = section_ptr_add(tcov_section, 16);
- tcov_data.line = file->line_num;
- write64le (ptr, (tcov_data.line << 8) | 0xff);
- put_extern_sym(&label, tcov_section,
- ((unsigned char *)ptr - tcov_section->data) + 8, 0);
- sv.type = label.type;
- sv.r = VT_SYM | VT_LVAL | VT_CONST;
- sv.r2 = VT_CONST;
- sv.c.i = 0;
- sv.sym = &label;
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || \
- defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 || \
- defined TCC_TARGET_RISCV64
- gen_increment_tcov (&sv);
-#else
- vpushv(&sv);
- inc(0, TOK_INC);
- vpop();
-#endif
- tcov_data.offset = (unsigned char *)ptr - tcov_section->data;
- tcov_data.ind = ind;
- }
-}
-
-ST_FUNC void tcc_tcov_block_end(TCCState *s1, int line)
-{
- if (s1->test_coverage == 0)
- return;
- if (line == -1)
- line = tcov_data.line;
- if (tcov_data.offset) {
- void *ptr = tcov_section->data + tcov_data.offset;
- unsigned long long nline = line ? line : file->line_num;
-
- write64le (ptr, (read64le (ptr) & 0xfffffffffull) | (nline << 36));
- tcov_data.offset = 0;
- }
-}
-
-ST_FUNC void tcc_tcov_check_line(TCCState *s1, int start)
-{
- if (s1->test_coverage == 0)
- return;
- if (tcov_data.line != file->line_num) {
- if ((tcov_data.line + 1) != file->line_num) {
- tcc_tcov_block_end (s1, -1);
- if (start)
- tcc_tcov_block_begin (s1);
- }
- else
- tcov_data.line = file->line_num;
- }
-}
-
-ST_FUNC void tcc_tcov_start(TCCState *s1)
-{
- if (s1->test_coverage == 0)
- return;
- if (!s1->dState)
- s1->dState = tcc_mallocz(sizeof *s1->dState);
- memset (&tcov_data, 0, sizeof (tcov_data));
- if (tcov_section == NULL) {
- tcov_section = new_section(tcc_state, ".tcov", SHT_PROGBITS,
- SHF_ALLOC | SHF_WRITE);
- section_ptr_add(tcov_section, 4); // pointer to executable name
- }
-}
-
-ST_FUNC void tcc_tcov_end(TCCState *s1)
-{
- if (s1->test_coverage == 0)
- return;
- if (tcov_data.last_func_name)
- section_ptr_add(tcov_section, 1);
- if (tcov_data.last_file_name)
- section_ptr_add(tcov_section, 1);
-}
-
-ST_FUNC void tcc_tcov_reset_ind(TCCState *s1)
-{
- tcov_data.ind = 0;
-}
-
-/* ------------------------------------------------------------------------- */
-#undef last_line_num
-#undef new_file
-#undef section_sym
-#undef debug_next_type
-#undef debug_hash
-#undef n_debug_hash
-#undef debug_anon_hash
-#undef n_debug_anon_hash
-#undef debug_info
-#undef debug_info_root
-#undef dwarf_sym
-#undef dwarf_line
-#undef dwarf_info
-#undef tcov_data
diff --git a/tinycc/tccelf.c b/tinycc/tccelf.c
deleted file mode 100644
index b46ad4c..0000000
--- a/tinycc/tccelf.c
+++ /dev/null
@@ -1,3936 +0,0 @@
-/*
- * ELF file handling for TCC
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "tcc.h"
-
-/* Define this to get some debug output during relocation processing. */
-#undef DEBUG_RELOC
-
-/********************************************************/
-/* global variables */
-
-/* elf version information */
-struct sym_version {
- char *lib;
- char *version;
- int out_index;
- int prev_same_lib;
-};
-
-#define nb_sym_versions s1->nb_sym_versions
-#define sym_versions s1->sym_versions
-#define nb_sym_to_version s1->nb_sym_to_version
-#define sym_to_version s1->sym_to_version
-#define dt_verneednum s1->dt_verneednum
-#define versym_section s1->versym_section
-#define verneed_section s1->verneed_section
-
-/* special flag to indicate that the section should not be linked to the other ones */
-#define SHF_PRIVATE 0x80000000
-/* section is dynsymtab_section */
-#define SHF_DYNSYM 0x40000000
-
-#ifdef TCC_TARGET_PE
-static const int shf_RELRO = SHF_ALLOC;
-static const char rdata[] = ".rdata";
-#else
-static const int shf_RELRO = SHF_ALLOC | SHF_WRITE;
-static const char rdata[] = ".data.ro";
-#endif
-
-/* ------------------------------------------------------------------------- */
-
-ST_FUNC void tccelf_new(TCCState *s)
-{
- TCCState *s1 = s;
- /* no section zero */
- dynarray_add(&s->sections, &s->nb_sections, NULL);
-
- /* create standard sections */
- text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
- data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
- /* create ro data section (make ro after relocation done with GNU_RELRO) */
- rodata_section = new_section(s, rdata, SHT_PROGBITS, shf_RELRO);
- bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
- common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
- common_section->sh_num = SHN_COMMON;
-
- /* symbols are always generated for linking stage */
- symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
- ".strtab",
- ".hashtab", SHF_PRIVATE);
- s->symtab = symtab_section;
-
- /* private symbol table for dynamic symbols */
- s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE|SHF_DYNSYM,
- ".dynstrtab",
- ".dynhashtab", SHF_PRIVATE);
- get_sym_attr(s, 0, 1);
-}
-
-#ifdef CONFIG_TCC_BCHECK
-ST_FUNC void tccelf_bounds_new(TCCState *s)
-{
- TCCState *s1 = s;
- /* create bounds sections (make ro after relocation done with GNU_RELRO) */
- bounds_section = new_section(s, ".bounds", SHT_PROGBITS, shf_RELRO);
- lbounds_section = new_section(s, ".lbounds", SHT_PROGBITS, shf_RELRO);
-}
-#endif
-
-static void free_section(Section *s)
-{
- tcc_free(s->data);
-}
-
-ST_FUNC void tccelf_delete(TCCState *s1)
-{
- int i;
-
-#ifndef ELF_OBJ_ONLY
- /* free symbol versions */
- for (i = 0; i < nb_sym_versions; i++) {
- tcc_free(sym_versions[i].version);
- tcc_free(sym_versions[i].lib);
- }
- tcc_free(sym_versions);
- tcc_free(sym_to_version);
-#endif
-
- /* free all sections */
- for(i = 1; i < s1->nb_sections; i++)
- free_section(s1->sections[i]);
- dynarray_reset(&s1->sections, &s1->nb_sections);
-
- for(i = 0; i < s1->nb_priv_sections; i++)
- free_section(s1->priv_sections[i]);
- dynarray_reset(&s1->priv_sections, &s1->nb_priv_sections);
-
- /* free any loaded DLLs */
-#ifdef TCC_IS_NATIVE
- for ( i = 0; i < s1->nb_loaded_dlls; i++) {
- DLLReference *ref = s1->loaded_dlls[i];
- if ( ref->handle )
-# ifdef _WIN32
- FreeLibrary((HMODULE)ref->handle);
-# else
- dlclose(ref->handle);
-# endif
- }
-#endif
- /* free loaded dlls array */
- dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
- tcc_free(s1->sym_attrs);
-
- symtab_section = NULL; /* for tccrun.c:rt_printline() */
-}
-
-/* save section data state */
-ST_FUNC void tccelf_begin_file(TCCState *s1)
-{
- Section *s; int i;
- for (i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
- s->sh_offset = s->data_offset;
- }
- /* disable symbol hashing during compilation */
- s = s1->symtab, s->reloc = s->hash, s->hash = NULL;
-#if defined TCC_TARGET_X86_64 && defined TCC_TARGET_PE
- s1->uw_sym = 0;
-#endif
-}
-
-/* At the end of compilation, convert any UNDEF syms to global, and merge
- with previously existing symbols */
-ST_FUNC void tccelf_end_file(TCCState *s1)
-{
- Section *s = s1->symtab;
- int first_sym, nb_syms, *tr, i;
-
- first_sym = s->sh_offset / sizeof (ElfSym);
- nb_syms = s->data_offset / sizeof (ElfSym) - first_sym;
- s->data_offset = s->sh_offset;
- s->link->data_offset = s->link->sh_offset;
- s->hash = s->reloc, s->reloc = NULL;
- tr = tcc_mallocz(nb_syms * sizeof *tr);
-
- for (i = 0; i < nb_syms; ++i) {
- ElfSym *sym = (ElfSym*)s->data + first_sym + i;
- if (sym->st_shndx == SHN_UNDEF
- && ELFW(ST_BIND)(sym->st_info) == STB_LOCAL)
- sym->st_info = ELFW(ST_INFO)(STB_GLOBAL, ELFW(ST_TYPE)(sym->st_info));
- tr[i] = set_elf_sym(s, sym->st_value, sym->st_size, sym->st_info,
- sym->st_other, sym->st_shndx, (char*)s->link->data + sym->st_name);
- }
- /* now update relocations */
- for (i = 1; i < s1->nb_sections; i++) {
- Section *sr = s1->sections[i];
- if (sr->sh_type == SHT_RELX && sr->link == s) {
- ElfW_Rel *rel = (ElfW_Rel*)(sr->data + sr->sh_offset);
- ElfW_Rel *rel_end = (ElfW_Rel*)(sr->data + sr->data_offset);
- for (; rel < rel_end; ++rel) {
- int n = ELFW(R_SYM)(rel->r_info) - first_sym;
- if (n < 0) /* zero sym_index in reloc (can happen with asm) */
- continue;
- rel->r_info = ELFW(R_INFO)(tr[n], ELFW(R_TYPE)(rel->r_info));
- }
- }
- }
- tcc_free(tr);
-
- /* record text/data/bss output for -bench info */
- for (i = 0; i < 4; ++i) {
- s = s1->sections[i + 1];
- s1->total_output[i] += s->data_offset - s->sh_offset;
- }
-}
-
-ST_FUNC Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
-{
- Section *sec;
-
- sec = tcc_mallocz(sizeof(Section) + strlen(name));
- sec->s1 = s1;
- strcpy(sec->name, name);
- sec->sh_type = sh_type;
- sec->sh_flags = sh_flags;
- switch(sh_type) {
- case SHT_GNU_versym:
- sec->sh_addralign = 2;
- break;
- case SHT_HASH:
- case SHT_GNU_HASH:
- case SHT_REL:
- case SHT_RELA:
- case SHT_DYNSYM:
- case SHT_SYMTAB:
- case SHT_DYNAMIC:
- case SHT_GNU_verneed:
- case SHT_GNU_verdef:
- sec->sh_addralign = PTR_SIZE;
- break;
- case SHT_STRTAB:
- sec->sh_addralign = 1;
- break;
- default:
- sec->sh_addralign = PTR_SIZE; /* gcc/pcc default alignment */
- break;
- }
-
- if (sh_flags & SHF_PRIVATE) {
- dynarray_add(&s1->priv_sections, &s1->nb_priv_sections, sec);
- } else {
- sec->sh_num = s1->nb_sections;
- dynarray_add(&s1->sections, &s1->nb_sections, sec);
- }
-
- return sec;
-}
-
-ST_FUNC Section *new_symtab(TCCState *s1,
- const char *symtab_name, int sh_type, int sh_flags,
- const char *strtab_name,
- const char *hash_name, int hash_sh_flags)
-{
- Section *symtab, *strtab, *hash;
- int *ptr, nb_buckets;
-
- symtab = new_section(s1, symtab_name, sh_type, sh_flags);
- symtab->sh_entsize = sizeof(ElfW(Sym));
- strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
- put_elf_str(strtab, "");
- symtab->link = strtab;
- put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
-
- nb_buckets = 1;
-
- hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
- hash->sh_entsize = sizeof(int);
- symtab->hash = hash;
- hash->link = symtab;
-
- ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
- ptr[0] = nb_buckets;
- ptr[1] = 1;
- memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
- return symtab;
-}
-
-/* realloc section and set its content to zero */
-ST_FUNC void section_realloc(Section *sec, unsigned long new_size)
-{
- unsigned long size;
- unsigned char *data;
-
- size = sec->data_allocated;
- if (size == 0)
- size = 1;
- while (size < new_size)
- size = size * 2;
- data = tcc_realloc(sec->data, size);
- memset(data + sec->data_allocated, 0, size - sec->data_allocated);
- sec->data = data;
- sec->data_allocated = size;
-}
-
-/* reserve at least 'size' bytes aligned per 'align' in section
- 'sec' from current offset, and return the aligned offset */
-ST_FUNC size_t section_add(Section *sec, addr_t size, int align)
-{
- size_t offset, offset1;
-
- offset = (sec->data_offset + align - 1) & -align;
- offset1 = offset + size;
- if (sec->sh_type != SHT_NOBITS && offset1 > sec->data_allocated)
- section_realloc(sec, offset1);
- sec->data_offset = offset1;
- if (align > sec->sh_addralign)
- sec->sh_addralign = align;
- return offset;
-}
-
-/* reserve at least 'size' bytes in section 'sec' from
- sec->data_offset. */
-ST_FUNC void *section_ptr_add(Section *sec, addr_t size)
-{
- size_t offset = section_add(sec, size, 1);
- return sec->data + offset;
-}
-
-#ifndef ELF_OBJ_ONLY
-/* reserve at least 'size' bytes from section start */
-static void section_reserve(Section *sec, unsigned long size)
-{
- if (size > sec->data_allocated)
- section_realloc(sec, size);
- if (size > sec->data_offset)
- sec->data_offset = size;
-}
-#endif
-
-static Section *have_section(TCCState *s1, const char *name)
-{
- Section *sec;
- int i;
- for(i = 1; i < s1->nb_sections; i++) {
- sec = s1->sections[i];
- if (!strcmp(name, sec->name))
- return sec;
- }
- return NULL;
-}
-
-/* return a reference to a section, and create it if it does not
- exists */
-ST_FUNC Section *find_section(TCCState *s1, const char *name)
-{
- Section *sec = have_section(s1, name);
- if (sec)
- return sec;
- /* sections are created as PROGBITS */
- return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
-}
-
-/* ------------------------------------------------------------------------- */
-
-ST_FUNC int put_elf_str(Section *s, const char *sym)
-{
- int offset, len;
- char *ptr;
-
- len = strlen(sym) + 1;
- offset = s->data_offset;
- ptr = section_ptr_add(s, len);
- memmove(ptr, sym, len);
- return offset;
-}
-
-/* elf symbol hashing function */
-static ElfW(Word) elf_hash(const unsigned char *name)
-{
- ElfW(Word) h = 0, g;
-
- while (*name) {
- h = (h << 4) + *name++;
- g = h & 0xf0000000;
- if (g)
- h ^= g >> 24;
- h &= ~g;
- }
- return h;
-}
-
-/* rebuild hash table of section s */
-/* NOTE: we do factorize the hash table code to go faster */
-static void rebuild_hash(Section *s, unsigned int nb_buckets)
-{
- ElfW(Sym) *sym;
- int *ptr, *hash, nb_syms, sym_index, h;
- unsigned char *strtab;
-
- strtab = s->link->data;
- nb_syms = s->data_offset / sizeof(ElfW(Sym));
-
- if (!nb_buckets)
- nb_buckets = ((int*)s->hash->data)[0];
-
- s->hash->data_offset = 0;
- ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
- ptr[0] = nb_buckets;
- ptr[1] = nb_syms;
- ptr += 2;
- hash = ptr;
- memset(hash, 0, (nb_buckets + 1) * sizeof(int));
- ptr += nb_buckets + 1;
-
- sym = (ElfW(Sym) *)s->data + 1;
- for(sym_index = 1; sym_index < nb_syms; sym_index++) {
- if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
- h = elf_hash(strtab + sym->st_name) % nb_buckets;
- *ptr = hash[h];
- hash[h] = sym_index;
- } else {
- *ptr = 0;
- }
- ptr++;
- sym++;
- }
-}
-
-/* return the symbol number */
-ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
- int info, int other, int shndx, const char *name)
-{
- int name_offset, sym_index;
- int nbuckets, h;
- ElfW(Sym) *sym;
- Section *hs;
-
- sym = section_ptr_add(s, sizeof(ElfW(Sym)));
- if (name && name[0])
- name_offset = put_elf_str(s->link, name);
- else
- name_offset = 0;
- /* XXX: endianness */
- sym->st_name = name_offset;
- sym->st_value = value;
- sym->st_size = size;
- sym->st_info = info;
- sym->st_other = other;
- sym->st_shndx = shndx;
- sym_index = sym - (ElfW(Sym) *)s->data;
- hs = s->hash;
- if (hs) {
- int *ptr, *base;
- ptr = section_ptr_add(hs, sizeof(int));
- base = (int *)hs->data;
- /* only add global or weak symbols. */
- if (ELFW(ST_BIND)(info) != STB_LOCAL) {
- /* add another hashing entry */
- nbuckets = base[0];
- h = elf_hash((unsigned char *)s->link->data + name_offset) % nbuckets;
- *ptr = base[2 + h];
- base[2 + h] = sym_index;
- base[1]++;
- /* we resize the hash table */
- hs->nb_hashed_syms++;
- if (hs->nb_hashed_syms > 2 * nbuckets) {
- rebuild_hash(s, 2 * nbuckets);
- }
- } else {
- *ptr = 0;
- base[1]++;
- }
- }
- return sym_index;
-}
-
-ST_FUNC int find_elf_sym(Section *s, const char *name)
-{
- ElfW(Sym) *sym;
- Section *hs;
- int nbuckets, sym_index, h;
- const char *name1;
-
- hs = s->hash;
- if (!hs)
- return 0;
- nbuckets = ((int *)hs->data)[0];
- h = elf_hash((unsigned char *) name) % nbuckets;
- sym_index = ((int *)hs->data)[2 + h];
- while (sym_index != 0) {
- sym = &((ElfW(Sym) *)s->data)[sym_index];
- name1 = (char *) s->link->data + sym->st_name;
- if (!strcmp(name, name1))
- return sym_index;
- sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
- }
- return 0;
-}
-
-/* return elf symbol value, signal error if 'err' is nonzero, decorate
- name if FORC */
-ST_FUNC addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc)
-{
- int sym_index;
- ElfW(Sym) *sym;
- char buf[256];
- if (forc && s1->leading_underscore
-#ifdef TCC_TARGET_PE
- /* win32-32bit stdcall symbols always have _ already */
- && !strchr(name, '@')
-#endif
- ) {
- buf[0] = '_';
- pstrcpy(buf + 1, sizeof(buf) - 1, name);
- name = buf;
- }
- sym_index = find_elf_sym(s1->symtab, name);
- sym = &((ElfW(Sym) *)s1->symtab->data)[sym_index];
- if (!sym_index || sym->st_shndx == SHN_UNDEF) {
- if (err)
- tcc_error_noabort("%s not defined", name);
- return (addr_t)-1;
- }
- return sym->st_value;
-}
-
-/* return elf symbol value */
-LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
-{
- addr_t addr = get_sym_addr(s, name, 0, 1);
- return addr == -1 ? NULL : (void*)(uintptr_t)addr;
-}
-
-/* list elf symbol names and values */
-ST_FUNC void list_elf_symbols(TCCState *s, void *ctx,
- void (*symbol_cb)(void *ctx, const char *name, const void *val))
-{
- ElfW(Sym) *sym;
- Section *symtab;
- int sym_index, end_sym;
- const char *name;
- unsigned char sym_vis, sym_bind;
-
- symtab = s->symtab;
- end_sym = symtab->data_offset / sizeof (ElfSym);
- for (sym_index = 0; sym_index < end_sym; ++sym_index) {
- sym = &((ElfW(Sym) *)symtab->data)[sym_index];
- if (sym->st_value) {
- name = (char *) symtab->link->data + sym->st_name;
- sym_bind = ELFW(ST_BIND)(sym->st_info);
- sym_vis = ELFW(ST_VISIBILITY)(sym->st_other);
- if (sym_bind == STB_GLOBAL && sym_vis == STV_DEFAULT)
- symbol_cb(ctx, name, (void*)(uintptr_t)sym->st_value);
- }
- }
-}
-
-/* list elf symbol names and values */
-LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
- void (*symbol_cb)(void *ctx, const char *name, const void *val))
-{
- list_elf_symbols(s, ctx, symbol_cb);
-}
-
-#ifndef ELF_OBJ_ONLY
-static void
-version_add (TCCState *s1)
-{
- int i;
- ElfW(Sym) *sym;
- ElfW(Verneed) *vn = NULL;
- Section *symtab;
- int sym_index, end_sym, nb_versions = 2, nb_entries = 0;
- ElfW(Half) *versym;
- const char *name;
-
- if (0 == nb_sym_versions)
- return;
- versym_section = new_section(s1, ".gnu.version", SHT_GNU_versym, SHF_ALLOC);
- versym_section->sh_entsize = sizeof(ElfW(Half));
- versym_section->link = s1->dynsym;
-
- /* add needed symbols */
- symtab = s1->dynsym;
- end_sym = symtab->data_offset / sizeof (ElfSym);
- versym = section_ptr_add(versym_section, end_sym * sizeof(ElfW(Half)));
- for (sym_index = 1; sym_index < end_sym; ++sym_index) {
- int dllindex, verndx;
- sym = &((ElfW(Sym) *)symtab->data)[sym_index];
- if (sym->st_shndx != SHN_UNDEF)
- continue; /* defined symbol doesn't need library version */
- name = (char *) symtab->link->data + sym->st_name;
- dllindex = find_elf_sym(s1->dynsymtab_section, name);
- verndx = (dllindex && dllindex < nb_sym_to_version)
- ? sym_to_version[dllindex] : -1;
- if (verndx >= 0) {
- if (!sym_versions[verndx].out_index)
- sym_versions[verndx].out_index = nb_versions++;
- versym[sym_index] = sym_versions[verndx].out_index;
- }
- }
- /* generate verneed section, but not when it will be empty. Some
- dynamic linkers look at their contents even when DTVERNEEDNUM and
- section size is zero. */
- if (nb_versions > 2) {
- verneed_section = new_section(s1, ".gnu.version_r",
- SHT_GNU_verneed, SHF_ALLOC);
- verneed_section->link = s1->dynsym->link;
- for (i = nb_sym_versions; i-- > 0;) {
- struct sym_version *sv = &sym_versions[i];
- int n_same_libs = 0, prev;
- size_t vnofs;
- ElfW(Vernaux) *vna = 0;
- if (sv->out_index < 1)
- continue;
-
- /* make sure that a DT_NEEDED tag is put */
- /* abitest-tcc fails on older i386-linux with "ld-linux.so.2" DT_NEEDED
- ret_int_test... Inconsistency detected by ld.so: dl-minimal.c: 148:
- realloc: Assertion `ptr == alloc_last_block' failed! */
- if (strcmp(sv->lib, "ld-linux.so.2"))
- tcc_add_dllref(s1, sv->lib, 0);
-
- vnofs = section_add(verneed_section, sizeof(*vn), 1);
- vn = (ElfW(Verneed)*)(verneed_section->data + vnofs);
- vn->vn_version = 1;
- vn->vn_file = put_elf_str(verneed_section->link, sv->lib);
- vn->vn_aux = sizeof (*vn);
- do {
- prev = sv->prev_same_lib;
- if (sv->out_index > 0) {
- vna = section_ptr_add(verneed_section, sizeof(*vna));
- vna->vna_hash = elf_hash ((const unsigned char *)sv->version);
- vna->vna_flags = 0;
- vna->vna_other = sv->out_index;
- sv->out_index = -2;
- vna->vna_name = put_elf_str(verneed_section->link, sv->version);
- vna->vna_next = sizeof (*vna);
- n_same_libs++;
- }
- if (prev >= 0)
- sv = &sym_versions[prev];
- } while(prev >= 0);
- vna->vna_next = 0;
- vn = (ElfW(Verneed)*)(verneed_section->data + vnofs);
- vn->vn_cnt = n_same_libs;
- vn->vn_next = sizeof(*vn) + n_same_libs * sizeof(*vna);
- nb_entries++;
- }
- if (vn)
- vn->vn_next = 0;
- verneed_section->sh_info = nb_entries;
- }
- dt_verneednum = nb_entries;
-}
-#endif /* ndef ELF_OBJ_ONLY */
-
-/* add an elf symbol : check if it is already defined and patch
- it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
-ST_FUNC int set_elf_sym(Section *s, addr_t value, unsigned long size,
- int info, int other, int shndx, const char *name)
-{
- TCCState *s1 = s->s1;
- ElfW(Sym) *esym;
- int sym_bind, sym_index, sym_type, esym_bind;
- unsigned char sym_vis, esym_vis, new_vis;
-
- sym_bind = ELFW(ST_BIND)(info);
- sym_type = ELFW(ST_TYPE)(info);
- sym_vis = ELFW(ST_VISIBILITY)(other);
-
- if (sym_bind != STB_LOCAL) {
- /* we search global or weak symbols */
- sym_index = find_elf_sym(s, name);
- if (!sym_index)
- goto do_def;
- esym = &((ElfW(Sym) *)s->data)[sym_index];
- if (esym->st_value == value && esym->st_size == size && esym->st_info == info
- && esym->st_other == other && esym->st_shndx == shndx)
- return sym_index;
- if (esym->st_shndx != SHN_UNDEF) {
- esym_bind = ELFW(ST_BIND)(esym->st_info);
- /* propagate the most constraining visibility */
- /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
- esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
- if (esym_vis == STV_DEFAULT) {
- new_vis = sym_vis;
- } else if (sym_vis == STV_DEFAULT) {
- new_vis = esym_vis;
- } else {
- new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
- }
- esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
- | new_vis;
- if (shndx == SHN_UNDEF) {
- /* ignore adding of undefined symbol if the
- corresponding symbol is already defined */
- } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
- /* global overrides weak, so patch */
- goto do_patch;
- } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
- /* weak is ignored if already global */
- } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
- /* keep first-found weak definition, ignore subsequents */
- } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
- /* ignore hidden symbols after */
- } else if ((esym->st_shndx == SHN_COMMON
- || esym->st_shndx == bss_section->sh_num)
- && (shndx < SHN_LORESERVE
- && shndx != bss_section->sh_num)) {
- /* data symbol gets precedence over common/bss */
- goto do_patch;
- } else if (shndx == SHN_COMMON || shndx == bss_section->sh_num) {
- /* data symbol keeps precedence over common/bss */
- } else if (s->sh_flags & SHF_DYNSYM) {
- /* we accept that two DLL define the same symbol */
- } else if (esym->st_other & ST_ASM_SET) {
- /* If the existing symbol came from an asm .set
- we can override. */
- goto do_patch;
- } else {
-#if 0
- printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
- sym_bind, shndx, new_vis, esym_bind, esym->st_shndx, esym_vis);
-#endif
- tcc_error_noabort("'%s' defined twice", name);
- }
- } else {
- esym->st_other = other;
- do_patch:
- esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
- esym->st_shndx = shndx;
- s1->new_undef_sym = 1;
- esym->st_value = value;
- esym->st_size = size;
- }
- } else {
- do_def:
- sym_index = put_elf_sym(s, value, size,
- ELFW(ST_INFO)(sym_bind, sym_type), other,
- shndx, name);
- }
- return sym_index;
-}
-
-/* put relocation */
-ST_FUNC void put_elf_reloca(Section *symtab, Section *s, unsigned long offset,
- int type, int symbol, addr_t addend)
-{
- TCCState *s1 = s->s1;
- char buf[256];
- Section *sr;
- ElfW_Rel *rel;
-
- sr = s->reloc;
- if (!sr) {
- /* if no relocation section, create it */
- snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
- /* if the symtab is allocated, then we consider the relocation
- are also */
- sr = new_section(s->s1, buf, SHT_RELX, symtab->sh_flags);
- sr->sh_entsize = sizeof(ElfW_Rel);
- sr->link = symtab;
- sr->sh_info = s->sh_num;
- s->reloc = sr;
- }
- rel = section_ptr_add(sr, sizeof(ElfW_Rel));
- rel->r_offset = offset;
- rel->r_info = ELFW(R_INFO)(symbol, type);
-#if SHT_RELX == SHT_RELA
- rel->r_addend = addend;
-#endif
- if (SHT_RELX != SHT_RELA && addend)
- tcc_error_noabort("non-zero addend on REL architecture");
-}
-
-ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
- int type, int symbol)
-{
- put_elf_reloca(symtab, s, offset, type, symbol, 0);
-}
-
-ST_FUNC struct sym_attr *get_sym_attr(TCCState *s1, int index, int alloc)
-{
- int n;
- struct sym_attr *tab;
-
- if (index >= s1->nb_sym_attrs) {
- if (!alloc)
- return s1->sym_attrs;
- /* find immediately bigger power of 2 and reallocate array */
- n = 1;
- while (index >= n)
- n *= 2;
- tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
- s1->sym_attrs = tab;
- memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
- (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
- s1->nb_sym_attrs = n;
- }
- return &s1->sym_attrs[index];
-}
-
-static void modify_reloctions_old_to_new(TCCState *s1, Section *s, int *old_to_new_syms)
-{
- int i, type, sym_index;
- Section *sr;
- ElfW_Rel *rel;
-
- for(i = 1; i < s1->nb_sections; i++) {
- sr = s1->sections[i];
- if (sr->sh_type == SHT_RELX && sr->link == s) {
- for_each_elem(sr, 0, rel, ElfW_Rel) {
- sym_index = ELFW(R_SYM)(rel->r_info);
- type = ELFW(R_TYPE)(rel->r_info);
- sym_index = old_to_new_syms[sym_index];
- rel->r_info = ELFW(R_INFO)(sym_index, type);
- }
- }
- }
-}
-
-/* In an ELF file symbol table, the local symbols must appear below
- the global and weak ones. Since TCC cannot sort it while generating
- the code, we must do it after. All the relocation tables are also
- modified to take into account the symbol table sorting */
-static void sort_syms(TCCState *s1, Section *s)
-{
- int *old_to_new_syms;
- ElfW(Sym) *new_syms;
- int nb_syms, i;
- ElfW(Sym) *p, *q;
-
- nb_syms = s->data_offset / sizeof(ElfW(Sym));
- new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
- old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
-
- /* first pass for local symbols */
- p = (ElfW(Sym) *)s->data;
- q = new_syms;
- for(i = 0; i < nb_syms; i++) {
- if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
- old_to_new_syms[i] = q - new_syms;
- *q++ = *p;
- }
- p++;
- }
- /* save the number of local symbols in section header */
- if( s->sh_size ) /* this 'if' makes IDA happy */
- s->sh_info = q - new_syms;
-
- /* then second pass for non local symbols */
- p = (ElfW(Sym) *)s->data;
- for(i = 0; i < nb_syms; i++) {
- if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
- old_to_new_syms[i] = q - new_syms;
- *q++ = *p;
- }
- p++;
- }
-
- /* we copy the new symbols to the old */
- memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
- tcc_free(new_syms);
-
- modify_reloctions_old_to_new(s1, s, old_to_new_syms);
-
- tcc_free(old_to_new_syms);
-}
-
-#ifndef ELF_OBJ_ONLY
-/* See: https://flapenguin.me/elf-dt-gnu-hash */
-#define ELFCLASS_BITS (PTR_SIZE * 8)
-
-static Section *create_gnu_hash(TCCState *s1)
-{
- int nb_syms, i, ndef, nbuckets, symoffset, bloom_size, bloom_shift;
- ElfW(Sym) *p;
- Section *gnu_hash;
- Section *dynsym = s1->dynsym;
- Elf32_Word *ptr;
-
- gnu_hash = new_section(s1, ".gnu.hash", SHT_GNU_HASH, SHF_ALLOC);
- gnu_hash->link = dynsym->hash->link;
-
- nb_syms = dynsym->data_offset / sizeof(ElfW(Sym));
-
- /* count def symbols */
- ndef = 0;
- p = (ElfW(Sym) *)dynsym->data;
- for(i = 0; i < nb_syms; i++, p++)
- ndef += p->st_shndx != SHN_UNDEF;
-
- /* calculate gnu hash sizes and fill header */
- nbuckets = ndef / 4 + 1;
- symoffset = nb_syms - ndef;
- bloom_shift = PTR_SIZE == 8 ? 6 : 5;
- bloom_size = 1; /* must be power of two */
- while (ndef >= bloom_size * (1 << (bloom_shift - 3)))
- bloom_size *= 2;
- ptr = section_ptr_add(gnu_hash, 4 * 4 +
- PTR_SIZE * bloom_size +
- nbuckets * 4 +
- ndef * 4);
- ptr[0] = nbuckets;
- ptr[1] = symoffset;
- ptr[2] = bloom_size;
- ptr[3] = bloom_shift;
- return gnu_hash;
-}
-
-static Elf32_Word elf_gnu_hash (const unsigned char *name)
-{
- Elf32_Word h = 5381;
- unsigned char c;
-
- while ((c = *name++))
- h = h * 33 + c;
- return h;
-}
-
-static void update_gnu_hash(TCCState *s1, Section *gnu_hash)
-{
- int *old_to_new_syms;
- ElfW(Sym) *new_syms;
- int nb_syms, i, nbuckets, bloom_size, bloom_shift;
- ElfW(Sym) *p, *q;
- Section *vs;
- Section *dynsym = s1->dynsym;
- Elf32_Word *ptr, *buckets, *chain, *hash;
- unsigned int *nextbuck;
- addr_t *bloom;
- unsigned char *strtab;
- struct { int first, last; } *buck;
-
- strtab = dynsym->link->data;
- nb_syms = dynsym->data_offset / sizeof(ElfW(Sym));
- new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
- old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
- hash = tcc_malloc(nb_syms * sizeof(Elf32_Word));
- nextbuck = tcc_malloc(nb_syms * sizeof(int));
-
- /* calculate hashes and copy undefs */
- p = (ElfW(Sym) *)dynsym->data;
- q = new_syms;
- for(i = 0; i < nb_syms; i++, p++) {
- if (p->st_shndx == SHN_UNDEF) {
- old_to_new_syms[i] = q - new_syms;
- *q++ = *p;
- }
- else
- hash[i] = elf_gnu_hash(strtab + p->st_name);
- }
-
- ptr = (Elf32_Word *) gnu_hash->data;
- nbuckets = ptr[0];
- bloom_size = ptr[2];
- bloom_shift = ptr[3];
- bloom = (addr_t *) (void *) &ptr[4];
- buckets = (Elf32_Word*) (void *) &bloom[bloom_size];
- chain = &buckets[nbuckets];
- buck = tcc_malloc(nbuckets * sizeof(*buck));
-
- if (gnu_hash->data_offset != 4 * 4 +
- PTR_SIZE * bloom_size +
- nbuckets * 4 +
- (nb_syms - (q - new_syms)) * 4)
- tcc_error_noabort ("gnu_hash size incorrect");
-
- /* find buckets */
- for(i = 0; i < nbuckets; i++)
- buck[i].first = -1;
-
- p = (ElfW(Sym) *)dynsym->data;
- for(i = 0; i < nb_syms; i++, p++)
- if (p->st_shndx != SHN_UNDEF) {
- int bucket = hash[i] % nbuckets;
-
- if (buck[bucket].first == -1)
- buck[bucket].first = buck[bucket].last = i;
- else {
- nextbuck[buck[bucket].last] = i;
- buck[bucket].last = i;
- }
- }
-
- /* fill buckets/chains/bloom and sort symbols */
- p = (ElfW(Sym) *)dynsym->data;
- for(i = 0; i < nbuckets; i++) {
- int cur = buck[i].first;
-
- if (cur != -1) {
- buckets[i] = q - new_syms;
- for (;;) {
- old_to_new_syms[cur] = q - new_syms;
- *q++ = p[cur];
- *chain++ = hash[cur] & ~1;
- bloom[(hash[cur] / ELFCLASS_BITS) % bloom_size] |=
- (addr_t)1 << (hash[cur] % ELFCLASS_BITS) |
- (addr_t)1 << ((hash[cur] >> bloom_shift) % ELFCLASS_BITS);
- if (cur == buck[i].last)
- break;
- cur = nextbuck[cur];
- }
- chain[-1] |= 1;
- }
- }
-
- memcpy(dynsym->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
- tcc_free(new_syms);
- tcc_free(hash);
- tcc_free(buck);
- tcc_free(nextbuck);
-
- modify_reloctions_old_to_new(s1, dynsym, old_to_new_syms);
-
- /* modify the versions */
- vs = versym_section;
- if (vs) {
- ElfW(Half) *newver, *versym = (ElfW(Half) *)vs->data;
-
- if (1/*versym*/) {
- newver = tcc_malloc(nb_syms * sizeof(*newver));
- for (i = 0; i < nb_syms; i++)
- newver[old_to_new_syms[i]] = versym[i];
- memcpy(vs->data, newver, nb_syms * sizeof(*newver));
- tcc_free(newver);
- }
- }
-
- tcc_free(old_to_new_syms);
-
- /* rebuild hash */
- ptr = (Elf32_Word *) dynsym->hash->data;
- rebuild_hash(dynsym, ptr[0]);
-}
-#endif /* ELF_OBJ_ONLY */
-
-/* relocate symbol table, resolve undefined symbols if do_resolve is
- true and output error if undefined symbol. */
-ST_FUNC void relocate_syms(TCCState *s1, Section *symtab, int do_resolve)
-{
- ElfW(Sym) *sym;
- int sym_bind, sh_num;
- const char *name;
-
- for_each_elem(symtab, 1, sym, ElfW(Sym)) {
- sh_num = sym->st_shndx;
- if (sh_num == SHN_UNDEF) {
- if (do_resolve == 2) /* relocating dynsym */
- continue;
- name = (char *) s1->symtab->link->data + sym->st_name;
- /* Use ld.so to resolve symbol for us (for tcc -run) */
- if (do_resolve) {
-#if defined TCC_IS_NATIVE && !defined TCC_TARGET_PE
- /* dlsym() needs the undecorated name. */
- void *addr = dlsym(RTLD_DEFAULT, &name[s1->leading_underscore]);
-#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD || TARGETOS_ANDROID
- if (addr == NULL) {
- int i;
- for (i = 0; i < s1->nb_loaded_dlls; i++)
- if ((addr = dlsym(s1->loaded_dlls[i]->handle, name)))
- break;
- }
-#endif
- if (addr) {
- sym->st_value = (addr_t) addr;
-#ifdef DEBUG_RELOC
- printf ("relocate_sym: %s -> 0x%lx\n", name, sym->st_value);
-#endif
- goto found;
- }
-#endif
- /* if dynamic symbol exist, it will be used in relocate_section */
- } else if (s1->dynsym && find_elf_sym(s1->dynsym, name))
- goto found;
- /* XXX: _fp_hw seems to be part of the ABI, so we ignore
- it */
- if (!strcmp(name, "_fp_hw"))
- goto found;
- /* only weak symbols are accepted to be undefined. Their
- value is zero */
- sym_bind = ELFW(ST_BIND)(sym->st_info);
- if (sym_bind == STB_WEAK)
- sym->st_value = 0;
- else
- tcc_error_noabort("undefined symbol '%s'", name);
-
- } else if (sh_num < SHN_LORESERVE) {
- /* add section base */
- sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
- }
- found: ;
- }
-}
-
-/* relocate a given section (CPU dependent) by applying the relocations
- in the associated relocation section */
-static void relocate_section(TCCState *s1, Section *s, Section *sr)
-{
- ElfW_Rel *rel;
- ElfW(Sym) *sym;
- int type, sym_index;
- unsigned char *ptr;
- addr_t tgt, addr;
- int is_dwarf = s->sh_num >= s1->dwlo && s->sh_num < s1->dwhi;
-
- qrel = (ElfW_Rel *)sr->data;
- for_each_elem(sr, 0, rel, ElfW_Rel) {
- ptr = s->data + rel->r_offset;
- sym_index = ELFW(R_SYM)(rel->r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- type = ELFW(R_TYPE)(rel->r_info);
- tgt = sym->st_value;
-#if SHT_RELX == SHT_RELA
- tgt += rel->r_addend;
-#endif
- if (is_dwarf && type == R_DATA_32DW
- && sym->st_shndx >= s1->dwlo && sym->st_shndx < s1->dwhi) {
- /* dwarf section relocation to each other */
- add32le(ptr, tgt - s1->sections[sym->st_shndx]->sh_addr);
- continue;
- }
- addr = s->sh_addr + rel->r_offset;
- relocate(s1, rel, type, ptr, addr, tgt);
- }
-#ifndef ELF_OBJ_ONLY
- /* if the relocation is allocated, we change its symbol table */
- if (sr->sh_flags & SHF_ALLOC) {
- sr->link = s1->dynsym;
- if (s1->output_type & TCC_OUTPUT_DYN) {
- size_t r = (uint8_t*)qrel - sr->data;
- if (sizeof ((Stab_Sym*)0)->n_value < PTR_SIZE
- && 0 == strcmp(s->name, ".stab"))
- r = 0; /* cannot apply 64bit relocation to 32bit value */
- sr->data_offset = sr->sh_size = r;
-#ifdef CONFIG_TCC_PIE
- if (r && 0 == (s->sh_flags & SHF_WRITE))
- tcc_warning("%d relocations to ro-section %s", (unsigned)(r / sizeof *qrel), s->name);
-#endif
- }
- }
-#endif
-}
-
-/* relocate all sections */
-ST_FUNC void relocate_sections(TCCState *s1)
-{
- int i;
- Section *s, *sr;
-
- for (i = 1; i < s1->nb_sections; ++i) {
- sr = s1->sections[i];
- if (sr->sh_type != SHT_RELX)
- continue;
- s = s1->sections[sr->sh_info];
-#ifndef TCC_TARGET_MACHO
- if (s != s1->got
- || s1->static_link
- || s1->output_type == TCC_OUTPUT_MEMORY)
-#endif
- {
- relocate_section(s1, s, sr);
- }
-#ifndef ELF_OBJ_ONLY
- if (sr->sh_flags & SHF_ALLOC) {
- ElfW_Rel *rel;
- /* relocate relocation table in 'sr' */
- for_each_elem(sr, 0, rel, ElfW_Rel)
- rel->r_offset += s->sh_addr;
- }
-#endif
- }
-}
-
-#ifndef ELF_OBJ_ONLY
-/* count the number of dynamic relocations so that we can reserve
- their space */
-static int prepare_dynamic_rel(TCCState *s1, Section *sr)
-{
- int count = 0;
-#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64) || \
- defined(TCC_TARGET_ARM) || defined(TCC_TARGET_ARM64) || \
- defined(TCC_TARGET_RISCV64)
- ElfW_Rel *rel;
- for_each_elem(sr, 0, rel, ElfW_Rel) {
- int sym_index = ELFW(R_SYM)(rel->r_info);
- int type = ELFW(R_TYPE)(rel->r_info);
- switch(type) {
-#if defined(TCC_TARGET_I386)
- case R_386_32:
- if (!get_sym_attr(s1, sym_index, 0)->dyn_index
- && ((ElfW(Sym)*)symtab_section->data + sym_index)->st_shndx == SHN_UNDEF) {
- /* don't fixup unresolved (weak) symbols */
- rel->r_info = ELFW(R_INFO)(sym_index, R_386_RELATIVE);
- break;
- }
-#elif defined(TCC_TARGET_X86_64)
- case R_X86_64_32:
- case R_X86_64_32S:
- case R_X86_64_64:
-#elif defined(TCC_TARGET_ARM)
- case R_ARM_ABS32:
- case R_ARM_TARGET1:
-#elif defined(TCC_TARGET_ARM64)
- case R_AARCH64_ABS32:
- case R_AARCH64_ABS64:
-#elif defined(TCC_TARGET_RISCV64)
- case R_RISCV_32:
- case R_RISCV_64:
-#endif
- count++;
- break;
-#if defined(TCC_TARGET_I386)
- case R_386_PC32:
-#elif defined(TCC_TARGET_X86_64)
- case R_X86_64_PC32:
- {
- ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- /* Hidden defined symbols can and must be resolved locally.
- We're misusing a PLT32 reloc for this, as that's always
- resolved to its address even in shared libs. */
- if (sym->st_shndx != SHN_UNDEF &&
- ELFW(ST_VISIBILITY)(sym->st_other) == STV_HIDDEN) {
- rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PLT32);
- break;
- }
- }
-#elif defined(TCC_TARGET_ARM64)
- case R_AARCH64_PREL32:
-#endif
- if (s1->output_type != TCC_OUTPUT_DLL)
- break;
- if (get_sym_attr(s1, sym_index, 0)->dyn_index)
- count++;
- break;
- default:
- break;
- }
- }
-#endif
- return count;
-}
-#endif
-
-#ifdef NEED_BUILD_GOT
-static int build_got(TCCState *s1)
-{
- /* if no got, then create it */
- s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
- s1->got->sh_entsize = 4;
- /* keep space for _DYNAMIC pointer and two dummy got entries */
- section_ptr_add(s1->got, 3 * PTR_SIZE);
- return set_elf_sym(symtab_section, 0, 0, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
- 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
-}
-
-/* Create a GOT and (for function call) a PLT entry corresponding to a symbol
- in s1->symtab. When creating the dynamic symbol table entry for the GOT
- relocation, use 'size' and 'info' for the corresponding symbol metadata.
- Returns the offset of the GOT or (if any) PLT entry. */
-static struct sym_attr * put_got_entry(TCCState *s1, int dyn_reloc_type,
- int sym_index)
-{
- int need_plt_entry;
- const char *name;
- ElfW(Sym) *sym;
- struct sym_attr *attr;
- unsigned got_offset;
- char plt_name[200];
- int len;
- Section *s_rel;
-
- need_plt_entry = (dyn_reloc_type == R_JMP_SLOT);
- attr = get_sym_attr(s1, sym_index, 1);
-
- /* In case a function is both called and its address taken 2 GOT entries
- are created, one for taking the address (GOT) and the other for the PLT
- entry (PLTGOT). */
- if (need_plt_entry ? attr->plt_offset : attr->got_offset)
- return attr;
-
- s_rel = s1->got;
- if (need_plt_entry) {
- if (!s1->plt) {
- s1->plt = new_section(s1, ".plt", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
- s1->plt->sh_entsize = 4;
- }
- s_rel = s1->plt;
- }
-
- /* create the GOT entry */
- got_offset = s1->got->data_offset;
- section_ptr_add(s1->got, PTR_SIZE);
-
- /* Create the GOT relocation that will insert the address of the object or
- function of interest in the GOT entry. This is a static relocation for
- memory output (dlsym will give us the address of symbols) and dynamic
- relocation otherwise (executable and DLLs). The relocation should be
- done lazily for GOT entry with *_JUMP_SLOT relocation type (the one
- associated to a PLT entry) but is currently done at load time for an
- unknown reason. */
-
- sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
- name = (char *) symtab_section->link->data + sym->st_name;
- //printf("sym %d %s\n", need_plt_entry, name);
-
- if (s1->dynsym) {
- if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
- /* Hack alarm. We don't want to emit dynamic symbols
- and symbol based relocs for STB_LOCAL symbols, but rather
- want to resolve them directly. At this point the symbol
- values aren't final yet, so we must defer this. We will later
- have to create a RELATIVE reloc anyway, so we misuse the
- relocation slot to smuggle the symbol reference until
- fill_local_got_entries. Not that the sym_index is
- relative to symtab_section, not s1->dynsym! Nevertheless
- we use s1->dyn_sym so that if this is the first call
- that got->reloc is correctly created. Also note that
- RELATIVE relocs are not normally created for the .got,
- so the types serves as a marker for later (and is retained
- also for the final output, which is okay because then the
- got is just normal data). */
- put_elf_reloc(s1->dynsym, s1->got, got_offset, R_RELATIVE,
- sym_index);
- } else {
- if (0 == attr->dyn_index)
- attr->dyn_index = set_elf_sym(s1->dynsym, sym->st_value,
- sym->st_size, sym->st_info, 0,
- sym->st_shndx, name);
- put_elf_reloc(s1->dynsym, s_rel, got_offset, dyn_reloc_type,
- attr->dyn_index);
- }
- } else {
- put_elf_reloc(symtab_section, s1->got, got_offset, dyn_reloc_type,
- sym_index);
- }
-
- if (need_plt_entry) {
- attr->plt_offset = create_plt_entry(s1, got_offset, attr);
-
- /* create a symbol 'sym@plt' for the PLT jump vector */
- len = strlen(name);
- if (len > sizeof plt_name - 5)
- len = sizeof plt_name - 5;
- memcpy(plt_name, name, len);
- strcpy(plt_name + len, "@plt");
- attr->plt_sym = put_elf_sym(s1->symtab, attr->plt_offset, 0,
- ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC), 0, s1->plt->sh_num, plt_name);
- } else {
- attr->got_offset = got_offset;
- }
-
- return attr;
-}
-
-/* build GOT and PLT entries */
-/* Two passes because R_JMP_SLOT should become first. Some targets
- (arm, arm64) do not allow mixing R_JMP_SLOT and R_GLOB_DAT. */
-ST_FUNC void build_got_entries(TCCState *s1, int got_sym)
-{
- Section *s;
- ElfW_Rel *rel;
- ElfW(Sym) *sym;
- int i, type, gotplt_entry, reloc_type, sym_index;
- struct sym_attr *attr;
- int pass = 0;
-redo:
- for(i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
- if (s->sh_type != SHT_RELX)
- continue;
- /* no need to handle got relocations */
- if (s->link != symtab_section)
- continue;
- for_each_elem(s, 0, rel, ElfW_Rel) {
- type = ELFW(R_TYPE)(rel->r_info);
- gotplt_entry = gotplt_entry_type(type);
- if (gotplt_entry == -1) {
- tcc_error_noabort ("Unknown relocation type for got: %d", type);
- continue;
- }
- sym_index = ELFW(R_SYM)(rel->r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
-
- if (gotplt_entry == NO_GOTPLT_ENTRY) {
- continue;
- }
-
- /* Automatically create PLT/GOT [entry] if it is an undefined
- reference (resolved at runtime), or the symbol is absolute,
- probably created by tcc_add_symbol, and thus on 64-bit
- targets might be too far from application code. */
- if (gotplt_entry == AUTO_GOTPLT_ENTRY) {
- if (sym->st_shndx == SHN_UNDEF) {
- ElfW(Sym) *esym;
- int dynindex;
- if (!PCRELATIVE_DLLPLT
- && (s1->output_type & TCC_OUTPUT_DYN))
- continue;
- /* Relocations for UNDEF symbols would normally need
- to be transferred into the executable or shared object.
- If that were done AUTO_GOTPLT_ENTRY wouldn't exist.
- But TCC doesn't do that (at least for exes), so we
- need to resolve all such relocs locally. And that
- means PLT slots for functions in DLLs and COPY relocs for
- data symbols. COPY relocs were generated in
- bind_exe_dynsyms (and the symbol adjusted to be defined),
- and for functions we were generated a dynamic symbol
- of function type. */
- if (s1->dynsym) {
- /* dynsym isn't set for -run :-/ */
- dynindex = get_sym_attr(s1, sym_index, 0)->dyn_index;
- esym = (ElfW(Sym) *)s1->dynsym->data + dynindex;
- if (dynindex
- && (ELFW(ST_TYPE)(esym->st_info) == STT_FUNC
- || (ELFW(ST_TYPE)(esym->st_info) == STT_NOTYPE
- && ELFW(ST_TYPE)(sym->st_info) == STT_FUNC)))
- goto jmp_slot;
- }
- } else if (sym->st_shndx == SHN_ABS) {
- if (sym->st_value == 0) /* from tcc_add_btstub() */
- continue;
-#ifndef TCC_TARGET_ARM
- if (PTR_SIZE != 8)
- continue;
-#endif
- /* from tcc_add_symbol(): on 64 bit platforms these
- need to go through .got */
- } else
- continue;
- }
-
-#ifdef TCC_TARGET_X86_64
- if ((type == R_X86_64_PLT32 || type == R_X86_64_PC32) &&
- sym->st_shndx != SHN_UNDEF &&
- (ELFW(ST_VISIBILITY)(sym->st_other) != STV_DEFAULT ||
- ELFW(ST_BIND)(sym->st_info) == STB_LOCAL ||
- s1->output_type & TCC_OUTPUT_EXE)) {
- if (pass != 0)
- continue;
- rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PC32);
- continue;
- }
-#endif
- reloc_type = code_reloc(type);
- if (reloc_type == -1) {
- tcc_error_noabort ("Unknown relocation type: %d", type);
- continue;
- }
-
- if (reloc_type != 0) {
- jmp_slot:
- if (pass != 0)
- continue;
- reloc_type = R_JMP_SLOT;
- } else {
- if (pass != 1)
- continue;
- reloc_type = R_GLOB_DAT;
- }
-
- if (!s1->got)
- got_sym = build_got(s1);
-
- if (gotplt_entry == BUILD_GOT_ONLY)
- continue;
-
- attr = put_got_entry(s1, reloc_type, sym_index);
-
- if (reloc_type == R_JMP_SLOT)
- rel->r_info = ELFW(R_INFO)(attr->plt_sym, type);
- }
- }
- if (++pass < 2)
- goto redo;
- /* .rel.plt refers to .got actually */
- if (s1->plt && s1->plt->reloc)
- s1->plt->reloc->sh_info = s1->got->sh_num;
- if (got_sym) /* set size */
- ((ElfW(Sym)*)symtab_section->data)[got_sym].st_size = s1->got->data_offset;
-}
-#endif /* def NEED_BUILD_GOT */
-
-ST_FUNC int set_global_sym(TCCState *s1, const char *name, Section *sec, addr_t offs)
-{
- int shn = sec ? sec->sh_num : offs || !name ? SHN_ABS : SHN_UNDEF;
- if (sec && offs == -1)
- offs = sec->data_offset;
- return set_elf_sym(symtab_section, offs, 0,
- ELFW(ST_INFO)(name ? STB_GLOBAL : STB_LOCAL, STT_NOTYPE), 0, shn, name);
-}
-
-static void add_init_array_defines(TCCState *s1, const char *section_name)
-{
- Section *s;
- addr_t end_offset;
- char buf[1024];
- s = have_section(s1, section_name);
- if (!s || !(s->sh_flags & SHF_ALLOC)) {
- end_offset = 0;
- s = data_section;
- } else {
- end_offset = s->data_offset;
- }
- snprintf(buf, sizeof(buf), "__%s_start", section_name + 1);
- set_global_sym(s1, buf, s, 0);
- snprintf(buf, sizeof(buf), "__%s_end", section_name + 1);
- set_global_sym(s1, buf, s, end_offset);
-}
-
-ST_FUNC void add_array (TCCState *s1, const char *sec, int c)
-{
- Section *s;
- s = find_section(s1, sec);
- s->sh_flags = shf_RELRO;
- s->sh_type = sec[1] == 'i' ? SHT_INIT_ARRAY : SHT_FINI_ARRAY;
- put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
- section_ptr_add(s, PTR_SIZE);
-}
-
-#ifdef CONFIG_TCC_BCHECK
-ST_FUNC void tcc_add_bcheck(TCCState *s1)
-{
- if (0 == s1->do_bounds_check)
- return;
- section_ptr_add(bounds_section, sizeof(addr_t));
-}
-#endif
-
-/* set symbol to STB_LOCAL and resolve. The point is to not export it as
- a dynamic symbol to allow so's to have one each with a different value. */
-static void set_local_sym(TCCState *s1, const char *name, Section *s, int offset)
-{
- int c = find_elf_sym(s1->symtab, name);
- if (c) {
- ElfW(Sym) *esym = (ElfW(Sym)*)s1->symtab->data + c;
- esym->st_info = ELFW(ST_INFO)(STB_LOCAL, STT_NOTYPE);
- esym->st_value = offset;
- esym->st_shndx = s->sh_num;
- }
-}
-
-/* avoid generating debug/test_coverage code for stub functions */
-static void tcc_compile_string_no_debug(TCCState *s, const char *str)
-{
- int save_do_debug = s->do_debug;
- int save_test_coverage = s->test_coverage;
-
- s->do_debug = 0;
- s->test_coverage = 0;
- tcc_compile_string(s, str);
- s->do_debug = save_do_debug;
- s->test_coverage = save_test_coverage;
-}
-
-#ifdef CONFIG_TCC_BACKTRACE
-static void put_ptr(TCCState *s1, Section *s, int offs)
-{
- int c;
- c = set_global_sym(s1, NULL, s, offs);
- s = data_section;
- put_elf_reloc (s1->symtab, s, s->data_offset, R_DATA_PTR, c);
- section_ptr_add(s, PTR_SIZE);
-}
-
-ST_FUNC void tcc_add_btstub(TCCState *s1)
-{
- Section *s;
- int n, o;
- CString cstr;
-
- s = data_section;
- /* Align to PTR_SIZE */
- section_ptr_add(s, -s->data_offset & (PTR_SIZE - 1));
- o = s->data_offset;
- /* create (part of) a struct rt_context (see tccrun.c) */
- if (s1->dwarf) {
- put_ptr(s1, dwarf_line_section, 0);
- put_ptr(s1, dwarf_line_section, -1);
- if (s1->dwarf >= 5)
- put_ptr(s1, dwarf_line_str_section, 0);
- else
- put_ptr(s1, dwarf_str_section, 0);
- }
- else
- {
- put_ptr(s1, stab_section, 0);
- put_ptr(s1, stab_section, -1);
- put_ptr(s1, stab_section->link, 0);
- }
- *(addr_t *)section_ptr_add(s, PTR_SIZE) = s1->dwarf;
- /* skip esym_start/esym_end/elf_str (not loaded) */
- section_ptr_add(s, 3 * PTR_SIZE);
- /* prog_base : local nameless symbol with offset 0 at SHN_ABS */
- put_ptr(s1, NULL, 0);
-#if defined TCC_TARGET_MACHO
- /* adjust for __PAGEZERO */
- if (s1->dwarf == 0 && s1->output_type == TCC_OUTPUT_EXE)
- write64le(data_section->data + data_section->data_offset - PTR_SIZE,
- (uint64_t)1 << 32);
-#endif
- n = 2 * PTR_SIZE;
-#ifdef CONFIG_TCC_BCHECK
- if (s1->do_bounds_check) {
- put_ptr(s1, bounds_section, 0);
- n -= PTR_SIZE;
- }
-#endif
- section_ptr_add(s, n);
- cstr_new(&cstr);
- cstr_printf(&cstr,
- "extern void __bt_init(),__bt_exit(),__bt_init_dll();"
- "static void *__rt_info[];"
- "__attribute__((constructor)) static void __bt_init_rt(){");
-#ifdef TCC_TARGET_PE
- if (s1->output_type == TCC_OUTPUT_DLL)
-#ifdef CONFIG_TCC_BCHECK
- cstr_printf(&cstr, "__bt_init_dll(%d);", s1->do_bounds_check);
-#else
- cstr_printf(&cstr, "__bt_init_dll(0);");
-#endif
-#endif
- cstr_printf(&cstr, "__bt_init(__rt_info,%d);}",
- s1->output_type == TCC_OUTPUT_DLL ? 0 : s1->rt_num_callers + 1);
- /* In case dlcose is called by application */
- cstr_printf(&cstr,
- "__attribute__((destructor)) static void __bt_exit_rt(){"
- "__bt_exit(__rt_info);}");
- tcc_compile_string_no_debug(s1, cstr.data);
- cstr_free(&cstr);
- set_local_sym(s1, &"___rt_info"[!s1->leading_underscore], s, o);
-}
-#endif /* def CONFIG_TCC_BACKTRACE */
-
-static void tcc_tcov_add_file(TCCState *s1, const char *filename)
-{
- CString cstr;
- void *ptr;
- char wd[1024];
-
- if (tcov_section == NULL)
- return;
- section_ptr_add(tcov_section, 1);
- write32le (tcov_section->data, tcov_section->data_offset);
-
- cstr_new (&cstr);
- if (filename[0] == '/')
- cstr_printf (&cstr, "%s.tcov", filename);
- else {
- getcwd (wd, sizeof(wd));
- cstr_printf (&cstr, "%s/%s.tcov", wd, filename);
- }
- ptr = section_ptr_add(tcov_section, cstr.size + 1);
- strcpy((char *)ptr, cstr.data);
- unlink((char *)ptr);
-#ifdef _WIN32
- normalize_slashes((char *)ptr);
-#endif
- cstr_free (&cstr);
-
- cstr_new(&cstr);
- cstr_printf(&cstr,
- "extern char *__tcov_data[];"
- "extern void __store_test_coverage ();"
- "__attribute__((destructor)) static void __tcov_exit() {"
- "__store_test_coverage(__tcov_data);"
- "}");
- tcc_compile_string_no_debug(s1, cstr.data);
- cstr_free(&cstr);
- set_local_sym(s1, &"___tcov_data"[!s1->leading_underscore], tcov_section, 0);
-}
-
-#ifndef TCC_TARGET_PE
-/* add tcc runtime libraries */
-ST_FUNC void tcc_add_runtime(TCCState *s1)
-{
- s1->filetype = 0;
-
-#ifdef CONFIG_TCC_BCHECK
- tcc_add_bcheck(s1);
-#endif
- tcc_add_pragma_libs(s1);
-
- /* add libc */
- if (!s1->nostdlib) {
- int lpthread = s1->option_pthread;
-
-#ifdef CONFIG_TCC_BCHECK
- if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) {
- tcc_add_support(s1, "bcheck.o");
-# if !(TARGETOS_OpenBSD || TARGETOS_NetBSD)
- tcc_add_library_err(s1, "dl");
-# endif
- lpthread = 1;
- }
-#endif
-#ifdef CONFIG_TCC_BACKTRACE
- if (s1->do_backtrace) {
- if (s1->output_type & TCC_OUTPUT_EXE)
- tcc_add_support(s1, "bt-exe.o");
- if (s1->output_type != TCC_OUTPUT_DLL)
- tcc_add_support(s1, "bt-log.o");
- if (s1->output_type != TCC_OUTPUT_MEMORY)
- tcc_add_btstub(s1);
- }
-#endif
- if (lpthread)
- tcc_add_library_err(s1, "pthread");
- tcc_add_library_err(s1, "c");
-#ifdef TCC_LIBGCC
- if (!s1->static_link) {
- if (TCC_LIBGCC[0] == '/')
- tcc_add_file(s1, TCC_LIBGCC);
- else
- tcc_add_dll(s1, TCC_LIBGCC, 0);
- }
-#endif
-#if defined TCC_TARGET_ARM && TARGETOS_FreeBSD
- tcc_add_library_err(s1, "gcc_s"); // unwind code
-#endif
- if (TCC_LIBTCC1[0])
- tcc_add_support(s1, TCC_LIBTCC1);
-
- /* add crt end if not memory output */
- if (s1->output_type != TCC_OUTPUT_MEMORY) {
-#if defined TCC_TARGET_MACHO
- /* nothing to do */
-#elif TARGETOS_FreeBSD || TARGETOS_NetBSD
- if (s1->output_type & TCC_OUTPUT_DYN)
- tcc_add_crt(s1, "crtendS.o");
- else
- tcc_add_crt(s1, "crtend.o");
- tcc_add_crt(s1, "crtn.o");
-#elif TARGETOS_OpenBSD
- if (s1->output_type == TCC_OUTPUT_DLL)
- tcc_add_crt(s1, "crtendS.o");
- else
- tcc_add_crt(s1, "crtend.o");
-#elif TARGETOS_ANDROID
- if (s1->output_type == TCC_OUTPUT_DLL)
- tcc_add_crt(s1, "crtend_so.o");
- else
- tcc_add_crt(s1, "crtend_android.o");
-#else
- tcc_add_crt(s1, "crtn.o");
-#endif
- }
- }
-}
-#endif /* ndef TCC_TARGET_PE */
-
-/* add various standard linker symbols (must be done after the
- sections are filled (for example after allocating common
- symbols)) */
-static void tcc_add_linker_symbols(TCCState *s1)
-{
- char buf[1024];
- int i;
- Section *s;
-
- set_global_sym(s1, "_etext", text_section, -1);
- set_global_sym(s1, "_edata", data_section, -1);
- set_global_sym(s1, "_end", bss_section, -1);
-#if TARGETOS_OpenBSD
- set_global_sym(s1, "__executable_start", NULL, ELF_START_ADDR);
-#endif
-#ifdef TCC_TARGET_RISCV64
- /* XXX should be .sdata+0x800, not .data+0x800 */
- set_global_sym(s1, "__global_pointer$", data_section, 0x800);
-#endif
- /* horrible new standard ldscript defines */
- add_init_array_defines(s1, ".preinit_array");
- add_init_array_defines(s1, ".init_array");
- add_init_array_defines(s1, ".fini_array");
- /* add start and stop symbols for sections whose name can be
- expressed in C */
- for(i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
- if ((s->sh_flags & SHF_ALLOC)
- && (s->sh_type == SHT_PROGBITS
- || s->sh_type == SHT_STRTAB)) {
- const char *p;
- /* check if section name can be expressed in C */
- p = s->name;
- for(;;) {
- int c = *p;
- if (!c)
- break;
- if (!isid(c) && !isnum(c))
- goto next_sec;
- p++;
- }
- snprintf(buf, sizeof(buf), "__start_%s", s->name);
- set_global_sym(s1, buf, s, 0);
- snprintf(buf, sizeof(buf), "__stop_%s", s->name);
- set_global_sym(s1, buf, s, -1);
- }
- next_sec: ;
- }
-}
-
-ST_FUNC void resolve_common_syms(TCCState *s1)
-{
- ElfW(Sym) *sym;
-
- /* Allocate common symbols in BSS. */
- for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
- if (sym->st_shndx == SHN_COMMON) {
- /* symbol alignment is in st_value for SHN_COMMONs */
- sym->st_value = section_add(bss_section, sym->st_size,
- sym->st_value);
- sym->st_shndx = bss_section->sh_num;
- }
- }
-
- /* Now assign linker provided symbols their value. */
- tcc_add_linker_symbols(s1);
-}
-
-#ifndef ELF_OBJ_ONLY
-ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
-{
- int sym_index = ELFW(R_SYM) (rel->r_info);
- ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
- struct sym_attr *attr = get_sym_attr(s1, sym_index, 0);
- unsigned offset = attr->got_offset;
-
- if (0 == offset)
- return;
- section_reserve(s1->got, offset + PTR_SIZE);
-#if PTR_SIZE == 8
- write64le(s1->got->data + offset, sym->st_value);
-#else
- write32le(s1->got->data + offset, sym->st_value);
-#endif
-}
-
-/* Perform relocation to GOT or PLT entries */
-ST_FUNC void fill_got(TCCState *s1)
-{
- Section *s;
- ElfW_Rel *rel;
- int i;
-
- for(i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
- if (s->sh_type != SHT_RELX)
- continue;
- /* no need to handle got relocations */
- if (s->link != symtab_section)
- continue;
- for_each_elem(s, 0, rel, ElfW_Rel) {
- switch (ELFW(R_TYPE) (rel->r_info)) {
- case R_X86_64_GOT32:
- case R_X86_64_GOTPCREL:
- case R_X86_64_GOTPCRELX:
- case R_X86_64_REX_GOTPCRELX:
- case R_X86_64_PLT32:
- fill_got_entry(s1, rel);
- break;
- }
- }
- }
-}
-
-/* See put_got_entry for a description. This is the second stage
- where GOT references to local defined symbols are rewritten. */
-static void fill_local_got_entries(TCCState *s1)
-{
- ElfW_Rel *rel;
- if (!s1->got->reloc)
- return;
- for_each_elem(s1->got->reloc, 0, rel, ElfW_Rel) {
- if (ELFW(R_TYPE)(rel->r_info) == R_RELATIVE) {
- int sym_index = ELFW(R_SYM) (rel->r_info);
- ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
- struct sym_attr *attr = get_sym_attr(s1, sym_index, 0);
- unsigned offset = attr->got_offset;
- if (offset != rel->r_offset - s1->got->sh_addr)
- tcc_error_noabort("fill_local_got_entries: huh?");
- rel->r_info = ELFW(R_INFO)(0, R_RELATIVE);
-#if SHT_RELX == SHT_RELA
- rel->r_addend = sym->st_value;
-#else
- /* All our REL architectures also happen to be 32bit LE. */
- write32le(s1->got->data + offset, sym->st_value);
-#endif
- }
- }
-}
-
-/* Bind symbols of executable: resolve undefined symbols from exported symbols
- in shared libraries */
-static void bind_exe_dynsyms(TCCState *s1)
-{
- const char *name;
- int sym_index, index;
- ElfW(Sym) *sym, *esym;
- int type;
-
- /* Resolve undefined symbols from dynamic symbols. When there is a match:
- - if STT_FUNC or STT_GNU_IFUNC symbol -> add it in PLT
- - if STT_OBJECT symbol -> add it in .bss section with suitable reloc */
- for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
- if (sym->st_shndx == SHN_UNDEF) {
- name = (char *) symtab_section->link->data + sym->st_name;
- sym_index = find_elf_sym(s1->dynsymtab_section, name);
- if (sym_index) {
- esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
- type = ELFW(ST_TYPE)(esym->st_info);
- if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
- /* Indirect functions shall have STT_FUNC type in executable
- * dynsym section. Indeed, a dlsym call following a lazy
- * resolution would pick the symbol value from the
- * executable dynsym entry which would contain the address
- * of the function wanted by the caller of dlsym instead of
- * the address of the function that would return that
- * address */
- int dynindex
- = put_elf_sym(s1->dynsym, 0, esym->st_size,
- ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC), 0, 0,
- name);
- int index = sym - (ElfW(Sym) *) symtab_section->data;
- get_sym_attr(s1, index, 1)->dyn_index = dynindex;
- } else if (type == STT_OBJECT) {
- unsigned long offset;
- ElfW(Sym) *dynsym;
- offset = bss_section->data_offset;
- /* XXX: which alignment ? */
- offset = (offset + 16 - 1) & -16;
- set_elf_sym (s1->symtab, offset, esym->st_size,
- esym->st_info, 0, bss_section->sh_num, name);
- index = put_elf_sym(s1->dynsym, offset, esym->st_size,
- esym->st_info, 0, bss_section->sh_num,
- name);
-
- /* Ensure R_COPY works for weak symbol aliases */
- if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
- for_each_elem(s1->dynsymtab_section, 1, dynsym, ElfW(Sym)) {
- if ((dynsym->st_value == esym->st_value)
- && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
- char *dynname = (char *) s1->dynsymtab_section->link->data
- + dynsym->st_name;
- put_elf_sym(s1->dynsym, offset, dynsym->st_size,
- dynsym->st_info, 0,
- bss_section->sh_num, dynname);
- break;
- }
- }
- }
-
- put_elf_reloc(s1->dynsym, bss_section,
- offset, R_COPY, index);
- offset += esym->st_size;
- bss_section->data_offset = offset;
- }
- } else {
- /* STB_WEAK undefined symbols are accepted */
- /* XXX: _fp_hw seems to be part of the ABI, so we ignore it */
- if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
- !strcmp(name, "_fp_hw")) {
- } else {
- tcc_error_noabort("undefined symbol '%s'", name);
- }
- }
- }
- }
-}
-
-/* Bind symbols of libraries: export all non local symbols of executable that
- are referenced by shared libraries. The reason is that the dynamic loader
- search symbol first in executable and then in libraries. Therefore a
- reference to a symbol already defined by a library can still be resolved by
- a symbol in the executable. With -rdynamic, export all defined symbols */
-static void bind_libs_dynsyms(TCCState *s1)
-{
- const char *name;
- int dynsym_index;
- ElfW(Sym) *sym, *esym;
-
- for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
- name = (char *)symtab_section->link->data + sym->st_name;
- dynsym_index = find_elf_sym(s1->dynsymtab_section, name);
- if (sym->st_shndx != SHN_UNDEF
- && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
- if (dynsym_index || s1->rdynamic)
- set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
- sym->st_info, 0, sym->st_shndx, name);
- } else if (dynsym_index) {
- esym = (ElfW(Sym) *)s1->dynsymtab_section->data + dynsym_index;
- if (esym->st_shndx == SHN_UNDEF) {
- /* weak symbols can stay undefined */
- if (ELFW(ST_BIND)(esym->st_info) != STB_WEAK)
- tcc_warning("undefined dynamic symbol '%s'", name);
- }
- }
- }
-}
-
-/* Export all non local symbols. This is used by shared libraries so that the
- non local symbols they define can resolve a reference in another shared
- library or in the executable. Correspondingly, it allows undefined local
- symbols to be resolved by other shared libraries or by the executable. */
-static void export_global_syms(TCCState *s1)
-{
- int dynindex, index;
- const char *name;
- ElfW(Sym) *sym;
- for_each_elem(symtab_section, 1, sym, ElfW(Sym)) {
- if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
- name = (char *) symtab_section->link->data + sym->st_name;
- dynindex = set_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
- sym->st_info, 0, sym->st_shndx, name);
- index = sym - (ElfW(Sym) *) symtab_section->data;
- get_sym_attr(s1, index, 1)->dyn_index = dynindex;
- }
- }
-}
-
-/* decide if an unallocated section should be output. */
-static int set_sec_sizes(TCCState *s1)
-{
- int i;
- Section *s;
- int textrel = 0;
- int file_type = s1->output_type;
-
- /* Allocate strings for section names */
- for(i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
- if (s->sh_type == SHT_RELX && !(s->sh_flags & SHF_ALLOC)) {
- /* when generating a DLL, we include relocations but
- we may patch them */
- if ((file_type & TCC_OUTPUT_DYN)
- && (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)) {
- int count = prepare_dynamic_rel(s1, s);
- if (count) {
- /* allocate the section */
- s->sh_flags |= SHF_ALLOC;
- s->sh_size = count * sizeof(ElfW_Rel);
- if (!(s1->sections[s->sh_info]->sh_flags & SHF_WRITE))
- textrel += count;
- }
- }
- } else if ((s->sh_flags & SHF_ALLOC)
-#ifdef TCC_TARGET_ARM
- || s->sh_type == SHT_ARM_ATTRIBUTES
-#endif
- || s1->do_debug) {
- s->sh_size = s->data_offset;
- }
-
-#ifdef TCC_TARGET_ARM
- /* XXX: Suppress stack unwinding section. */
- if (s->sh_type == SHT_ARM_EXIDX) {
- s->sh_flags = 0;
- s->sh_size = 0;
- }
-#endif
-
- }
- return textrel;
-}
-
-/* various data used under elf_output_file() */
-struct dyn_inf {
- Section *dynamic;
- Section *dynstr;
- struct {
- /* Info to be copied in dynamic section */
- unsigned long data_offset;
- addr_t rel_addr;
- addr_t rel_size;
- };
-
- ElfW(Phdr) *phdr;
- int phnum;
- Section *interp;
- Section *note;
- Section *gnu_hash;
-
- /* read only segment mapping for GNU_RELRO */
- Section _roinf, *roinf;
-};
-
-/* Decide the layout of sections loaded in memory. This must be done before
- program headers are filled since they contain info about the layout.
- We do the following ordering: interp, symbol tables, relocations, progbits,
- nobits */
-static int sort_sections(TCCState *s1, int *sec_order, Section *interp)
-{
- Section *s;
- int i, j, k, f, f0, n;
- int nb_sections = s1->nb_sections;
- int *sec_cls = sec_order + nb_sections;
-
- for (i = 1; i < nb_sections; i++) {
- s = s1->sections[i];
- if (s->sh_flags & SHF_ALLOC) {
- j = 0x100;
- if (s->sh_flags & SHF_WRITE)
- j = 0x200;
- if (s->sh_flags & SHF_TLS)
- j += 0x200;
- } else if (s->sh_name) {
- j = 0x700;
- } else {
- j = 0x900; /* no sh_name: won't go to file */
- }
- if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_DYNSYM) {
- k = 0x10;
- } else if (s->sh_type == SHT_STRTAB && strcmp(s->name, ".stabstr")) {
- k = 0x11;
- if (i == nb_sections - 1) /* ".shstrtab" assumed to remain last */
- k = 0xff;
- } else if (s->sh_type == SHT_HASH || s->sh_type == SHT_GNU_HASH) {
- k = 0x12;
- } else if (s->sh_type == SHT_RELX) {
- k = 0x20;
- if (s1->plt && s == s1->plt->reloc)
- k = 0x21;
- } else if (s->sh_type == SHT_PREINIT_ARRAY) {
- k = 0x41;
- } else if (s->sh_type == SHT_INIT_ARRAY) {
- k = 0x42;
- } else if (s->sh_type == SHT_FINI_ARRAY) {
- k = 0x43;
-#ifdef CONFIG_TCC_BCHECK
- } else if (s == bounds_section || s == lbounds_section) {
- k = 0x44;
-#endif
- } else if (s == rodata_section || 0 == strcmp(s->name, ".data.rel.ro")) {
- k = 0x45;
- } else if (s->sh_type == SHT_DYNAMIC) {
- k = 0x46;
- } else if (s == s1->got) {
- k = 0x47; /* .got as RELRO needs BIND_NOW in DT_FLAGS */
- } else {
- k = 0x50;
- if (s->sh_type == SHT_NOTE)
- k = 0x60;
- if (s->sh_flags & SHF_EXECINSTR)
- k = 0x70;
- if (s->sh_type == SHT_NOBITS)
- k = 0x80;
- if (s == interp)
- k = 0x00;
- }
- k += j;
-
- for (n = i; n > 1 && k < (f = sec_cls[n - 1]); --n)
- sec_cls[n] = f, sec_order[n] = sec_order[n - 1];
- sec_cls[n] = k, sec_order[n] = i;
- }
- sec_order[0] = 0;
-
- /* count PT_LOAD headers needed */
- n = f0 = 0;
- for (i = 1; i < nb_sections; i++) {
- s = s1->sections[sec_order[i]];
- k = sec_cls[i];
- f = 0;
- if (k < 0x700) {
- f = s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR|SHF_TLS);
-#if TARGETOS_NetBSD
- /* NetBSD only supports 2 PT_LOAD sections.
- See: https://blog.netbsd.org/tnf/entry/the_first_report_on_lld */
- if ((f & SHF_WRITE) == 0) f |= SHF_EXECINSTR;
-#else
- if ((k & 0xfff0) == 0x240) /* RELRO sections */
- f |= 1<<4;
-#endif
- if (f != f0) /* start new header when flags changed or relro */
- f0 = f, ++n, f |= 1<<8;
- }
- sec_cls[i] = f;
- //printf("ph %d sec %02d : %3X %3X %8.2X %04X %s\n", !!f * n, i, f, k, s->sh_type, s->sh_size, s->name);
- }
- return n;
-}
-
-static ElfW(Phdr) *fill_phdr(ElfW(Phdr) *ph, int type, Section *s)
-{
- if (s) {
- ph->p_offset = s->sh_offset;
- ph->p_vaddr = s->sh_addr;
- ph->p_filesz = s->sh_size;
- ph->p_align = s->sh_addralign;
- }
- ph->p_type = type;
- ph->p_flags = PF_R;
- ph->p_paddr = ph->p_vaddr;
- ph->p_memsz = ph->p_filesz;
- return ph;
-}
-
-/* Assign sections to segments and decide how are sections laid out when loaded
- in memory. This function also fills corresponding program headers. */
-static int layout_sections(TCCState *s1, int *sec_order, struct dyn_inf *d)
-{
- Section *s;
- addr_t addr, tmp, align, s_align, base;
- ElfW(Phdr) *ph = NULL;
- int i, f, n, phnum, phfill;
- int file_offset;
-
- /* compute number of program headers */
- phnum = sort_sections(s1, sec_order, d->interp);
- phfill = 0; /* set to 1 to have dll's with a PT_PHDR */
- if (d->interp)
- phfill = 2;
- phnum += phfill;
- if (d->note)
- ++phnum;
- if (d->dynamic)
- ++phnum;
- if (d->roinf)
- ++phnum;
- d->phnum = phnum;
- d->phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
-
- file_offset = 0;
- if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
- file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
-
- s_align = ELF_PAGE_SIZE;
- if (s1->section_align)
- s_align = s1->section_align;
-
- addr = ELF_START_ADDR;
- if (s1->output_type & TCC_OUTPUT_DYN)
- addr = 0;
-
- if (s1->has_text_addr) {
- addr = s1->text_addr;
- if (0) {
- int a_offset, p_offset;
- /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
- ELF_PAGE_SIZE */
- a_offset = (int) (addr & (s_align - 1));
- p_offset = file_offset & (s_align - 1);
- if (a_offset < p_offset)
- a_offset += s_align;
- file_offset += (a_offset - p_offset);
- }
- }
- base = addr;
- /* compute address after headers */
- addr = addr + (file_offset & (s_align - 1));
-
- n = 0;
- for(i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[sec_order[i]];
- f = sec_order[i + s1->nb_sections];
- align = s->sh_addralign - 1;
-
- if (f == 0) { /* no alloc */
- file_offset = (file_offset + align) & ~align;
- s->sh_offset = file_offset;
- if (s->sh_type != SHT_NOBITS)
- file_offset += s->sh_size;
- continue;
- }
-
- if ((f & 1<<8) && n) {
- /* different rwx section flags */
- if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
- /* if in the middle of a page, w e duplicate the page in
- memory so that one copy is RX and the other is RW */
- if ((addr & (s_align - 1)) != 0)
- addr += s_align;
- } else {
- align = s_align - 1;
- }
- }
-
- tmp = addr;
- addr = (addr + align) & ~align;
- file_offset += (int)(addr - tmp);
- s->sh_offset = file_offset;
- s->sh_addr = addr;
-
- if (f & 1<<8) {
- /* set new program header */
- ph = &d->phdr[phfill + n];
- ph->p_type = PT_LOAD;
- ph->p_align = s_align;
- ph->p_flags = PF_R;
- if (f & SHF_WRITE)
- ph->p_flags |= PF_W;
- if (f & SHF_EXECINSTR)
- ph->p_flags |= PF_X;
- if (f & SHF_TLS) {
- ph->p_type = PT_TLS;
- ph->p_align = align + 1;
- }
-
- ph->p_offset = file_offset;
- ph->p_vaddr = addr;
- if (n == 0) {
- /* Make the first PT_LOAD segment include the program
- headers itself (and the ELF header as well), it'll
- come out with same memory use but will make various
- tools like binutils strip work better. */
- ph->p_offset = 0;
- ph->p_vaddr = base;
- }
- ph->p_paddr = ph->p_vaddr;
- ++n;
- }
-
- if (f & 1<<4) {
- Section *roinf = &d->_roinf;
- if (roinf->sh_size == 0) {
- roinf->sh_offset = s->sh_offset;
- roinf->sh_addr = s->sh_addr;
- roinf->sh_addralign = 1;
- }
- roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size;
- }
-
- addr += s->sh_size;
- if (s->sh_type != SHT_NOBITS)
- file_offset += s->sh_size;
-
- ph->p_filesz = file_offset - ph->p_offset;
- ph->p_memsz = addr - ph->p_vaddr;
- }
-
- /* Fill other headers */
- if (d->note)
- fill_phdr(++ph, PT_NOTE, d->note);
- if (d->dynamic)
- fill_phdr(++ph, PT_DYNAMIC, d->dynamic)->p_flags |= PF_W;
- if (d->roinf)
- fill_phdr(++ph, PT_GNU_RELRO, d->roinf)->p_flags |= PF_W;
- if (d->interp)
- fill_phdr(&d->phdr[1], PT_INTERP, d->interp);
- if (phfill) {
- ph = &d->phdr[0];
- ph->p_offset = sizeof(ElfW(Ehdr));
- ph->p_vaddr = base + ph->p_offset;
- ph->p_filesz = phnum * sizeof(ElfW(Phdr));
- ph->p_align = 4;
- fill_phdr(ph, PT_PHDR, NULL);
- }
- return file_offset;
-}
-
-/* put dynamic tag */
-static void put_dt(Section *dynamic, int dt, addr_t val)
-{
- ElfW(Dyn) *dyn;
- dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
- dyn->d_tag = dt;
- dyn->d_un.d_val = val;
-}
-
-/* Fill the dynamic section with tags describing the address and size of
- sections */
-static void fill_dynamic(TCCState *s1, struct dyn_inf *dyninf)
-{
- Section *dynamic = dyninf->dynamic;
- Section *s;
-
- /* put dynamic section entries */
- put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
- put_dt(dynamic, DT_GNU_HASH, dyninf->gnu_hash->sh_addr);
- put_dt(dynamic, DT_STRTAB, dyninf->dynstr->sh_addr);
- put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
- put_dt(dynamic, DT_STRSZ, dyninf->dynstr->data_offset);
- put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
-#if PTR_SIZE == 8
- put_dt(dynamic, DT_RELA, dyninf->rel_addr);
- put_dt(dynamic, DT_RELASZ, dyninf->rel_size);
- put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
- if (s1->plt && s1->plt->reloc) {
- put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
- put_dt(dynamic, DT_PLTRELSZ, s1->plt->reloc->data_offset);
- put_dt(dynamic, DT_JMPREL, s1->plt->reloc->sh_addr);
- put_dt(dynamic, DT_PLTREL, DT_RELA);
- }
- put_dt(dynamic, DT_RELACOUNT, 0);
-#else
- put_dt(dynamic, DT_REL, dyninf->rel_addr);
- put_dt(dynamic, DT_RELSZ, dyninf->rel_size);
- put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
- if (s1->plt && s1->plt->reloc) {
- put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
- put_dt(dynamic, DT_PLTRELSZ, s1->plt->reloc->data_offset);
- put_dt(dynamic, DT_JMPREL, s1->plt->reloc->sh_addr);
- put_dt(dynamic, DT_PLTREL, DT_REL);
- }
- put_dt(dynamic, DT_RELCOUNT, 0);
-#endif
- if (versym_section && verneed_section) {
- /* The dynamic linker can not handle VERSYM without VERNEED */
- put_dt(dynamic, DT_VERSYM, versym_section->sh_addr);
- put_dt(dynamic, DT_VERNEED, verneed_section->sh_addr);
- put_dt(dynamic, DT_VERNEEDNUM, dt_verneednum);
- }
- s = have_section(s1, ".preinit_array");
- if (s && s->data_offset) {
- put_dt(dynamic, DT_PREINIT_ARRAY, s->sh_addr);
- put_dt(dynamic, DT_PREINIT_ARRAYSZ, s->data_offset);
- }
- s = have_section(s1, ".init_array");
- if (s && s->data_offset) {
- put_dt(dynamic, DT_INIT_ARRAY, s->sh_addr);
- put_dt(dynamic, DT_INIT_ARRAYSZ, s->data_offset);
- }
- s = have_section(s1, ".fini_array");
- if (s && s->data_offset) {
- put_dt(dynamic, DT_FINI_ARRAY, s->sh_addr);
- put_dt(dynamic, DT_FINI_ARRAYSZ, s->data_offset);
- }
- s = have_section(s1, ".init");
- if (s && s->data_offset) {
- put_dt(dynamic, DT_INIT, s->sh_addr);
- }
- s = have_section(s1, ".fini");
- if (s && s->data_offset) {
- put_dt(dynamic, DT_FINI, s->sh_addr);
- }
- if (s1->do_debug)
- put_dt(dynamic, DT_DEBUG, 0);
- put_dt(dynamic, DT_NULL, 0);
-}
-
-/* Remove gaps between RELX sections.
- These gaps are a result of final_sections_reloc. Here some relocs are removed.
- The gaps are then filled with 0 in tcc_output_elf. The 0 is intepreted as
- R_...NONE reloc. This does work on most targets but on OpenBSD/arm64 this
- is illegal. OpenBSD/arm64 does not support R_...NONE reloc. */
-static void update_reloc_sections(TCCState *s1, struct dyn_inf *dyninf)
-{
- int i;
- unsigned long file_offset = 0;
- Section *s;
- Section *relocplt = s1->plt ? s1->plt->reloc : NULL;
-
- /* dynamic relocation table information, for .dynamic section */
- dyninf->rel_addr = dyninf->rel_size = 0;
-
- for(i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
- if (s->sh_type == SHT_RELX && s != relocplt) {
- if (dyninf->rel_size == 0) {
- dyninf->rel_addr = s->sh_addr;
- file_offset = s->sh_offset;
- }
- else {
- s->sh_addr = dyninf->rel_addr + dyninf->rel_size;
- s->sh_offset = file_offset + dyninf->rel_size;
- }
- dyninf->rel_size += s->sh_size;
- }
- }
-}
-
-static int tidy_section_headers(TCCState *s1, int *sec_order);
-#endif /* ndef ELF_OBJ_ONLY */
-
-/* Create an ELF file on disk.
- This function handle ELF specific layout requirements */
-static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr,
- int file_offset, int *sec_order)
-{
- int i, shnum, offset, size, file_type;
- Section *s;
- ElfW(Ehdr) ehdr;
- ElfW(Shdr) shdr, *sh;
-
- file_type = s1->output_type;
- shnum = s1->nb_sections;
-
- memset(&ehdr, 0, sizeof(ehdr));
-
- if (phnum > 0) {
- ehdr.e_phentsize = sizeof(ElfW(Phdr));
- ehdr.e_phnum = phnum;
- ehdr.e_phoff = sizeof(ElfW(Ehdr));
-#ifndef ELF_OBJ_ONLY
- shnum = tidy_section_headers(s1, sec_order);
-#endif
- }
-
- /* align to 4 */
- file_offset = (file_offset + 3) & -4;
-
- /* fill header */
- ehdr.e_ident[0] = ELFMAG0;
- ehdr.e_ident[1] = ELFMAG1;
- ehdr.e_ident[2] = ELFMAG2;
- ehdr.e_ident[3] = ELFMAG3;
- ehdr.e_ident[4] = ELFCLASSW;
- ehdr.e_ident[5] = ELFDATA2LSB;
- ehdr.e_ident[6] = EV_CURRENT;
-
-#if TARGETOS_FreeBSD || TARGETOS_FreeBSD_kernel
- ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
-#elif defined TCC_TARGET_ARM && defined TCC_ARM_EABI
- ehdr.e_flags = EF_ARM_EABI_VER5;
- ehdr.e_flags |= s1->float_abi == ARM_HARD_FLOAT
- ? EF_ARM_VFP_FLOAT : EF_ARM_SOFT_FLOAT;
-#elif defined TCC_TARGET_ARM
- ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
-#elif defined TCC_TARGET_RISCV64
- ehdr.e_flags = EF_RISCV_FLOAT_ABI_DOUBLE;
-#endif
-
- if (file_type == TCC_OUTPUT_OBJ) {
- ehdr.e_type = ET_REL;
- } else {
- if (file_type & TCC_OUTPUT_DYN)
- ehdr.e_type = ET_DYN;
- else
- ehdr.e_type = ET_EXEC;
- if (s1->elf_entryname)
- ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0);
- else
- ehdr.e_entry = get_sym_addr(s1, "_start", !!(file_type & TCC_OUTPUT_EXE), 0);
- if (ehdr.e_entry == (addr_t)-1)
- ehdr.e_entry = text_section->sh_addr;
- if (s1->nb_errors)
- return -1;
- }
-
- ehdr.e_machine = EM_TCC_TARGET;
- ehdr.e_version = EV_CURRENT;
- ehdr.e_shoff = file_offset;
- ehdr.e_ehsize = sizeof(ElfW(Ehdr));
- ehdr.e_shentsize = sizeof(ElfW(Shdr));
- ehdr.e_shnum = shnum;
- ehdr.e_shstrndx = shnum - 1;
-
- fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
- if (phdr)
- fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
- offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
-
- sort_syms(s1, symtab_section);
-
- for(i = 1; i < shnum; i++) {
- s = s1->sections[sec_order ? sec_order[i] : i];
- if (s->sh_type != SHT_NOBITS) {
- while (offset < s->sh_offset) {
- fputc(0, f);
- offset++;
- }
- size = s->sh_size;
- if (size)
- fwrite(s->data, 1, size, f);
- offset += size;
- }
- }
-
- /* output section headers */
- while (offset < ehdr.e_shoff) {
- fputc(0, f);
- offset++;
- }
-
- for(i = 0; i < shnum; i++) {
- sh = &shdr;
- memset(sh, 0, sizeof(ElfW(Shdr)));
- s = s1->sections[i];
- if (s) {
- sh->sh_name = s->sh_name;
- sh->sh_type = s->sh_type;
- sh->sh_flags = s->sh_flags;
- sh->sh_entsize = s->sh_entsize;
- sh->sh_info = s->sh_info;
- if (s->link)
- sh->sh_link = s->link->sh_num;
- sh->sh_addralign = s->sh_addralign;
- sh->sh_addr = s->sh_addr;
- sh->sh_offset = s->sh_offset;
- sh->sh_size = s->sh_size;
- }
- fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
- }
- return 0;
-}
-
-static int tcc_output_binary(TCCState *s1, FILE *f,
- const int *sec_order)
-{
- Section *s;
- int i, offset, size;
-
- offset = 0;
- for(i=1;i<s1->nb_sections;i++) {
- s = s1->sections[sec_order[i]];
- if (s->sh_type != SHT_NOBITS &&
- (s->sh_flags & SHF_ALLOC)) {
- while (offset < s->sh_offset) {
- fputc(0, f);
- offset++;
- }
- size = s->sh_size;
- fwrite(s->data, 1, size, f);
- offset += size;
- }
- }
- return 0;
-}
-
-/* Write an elf, coff or "binary" file */
-static int tcc_write_elf_file(TCCState *s1, const char *filename, int phnum,
- ElfW(Phdr) *phdr, int file_offset, int *sec_order)
-{
- int fd, mode, file_type, ret;
- FILE *f;
-
- file_type = s1->output_type;
- if (file_type == TCC_OUTPUT_OBJ)
- mode = 0666;
- else
- mode = 0777;
- unlink(filename);
- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
- if (fd < 0 || (f = fdopen(fd, "wb")) == NULL)
- return tcc_error_noabort("could not write '%s: %s'", filename, strerror(errno));
- if (s1->verbose)
- printf("<- %s\n", filename);
-#ifdef TCC_TARGET_COFF
- if (s1->output_format == TCC_OUTPUT_FORMAT_COFF)
- tcc_output_coff(s1, f);
- else
-#endif
- if (s1->output_format == TCC_OUTPUT_FORMAT_ELF)
- ret = tcc_output_elf(s1, f, phnum, phdr, file_offset, sec_order);
- else
- ret = tcc_output_binary(s1, f, sec_order);
- fclose(f);
-
- return ret;
-}
-
-#ifndef ELF_OBJ_ONLY
-/* Sort section headers by assigned sh_addr, remove sections
- that we aren't going to output. */
-static int tidy_section_headers(TCCState *s1, int *sec_order)
-{
- int i, nnew, l, *backmap;
- Section **snew, *s;
- ElfW(Sym) *sym;
-
- snew = tcc_malloc(s1->nb_sections * sizeof(snew[0]));
- backmap = tcc_malloc(s1->nb_sections * sizeof(backmap[0]));
- for (i = 0, nnew = 0, l = s1->nb_sections; i < s1->nb_sections; i++) {
- s = s1->sections[sec_order[i]];
- if (!i || s->sh_name) {
- backmap[sec_order[i]] = nnew;
- snew[nnew] = s;
- ++nnew;
- } else {
- backmap[sec_order[i]] = 0;
- snew[--l] = s;
- }
- }
- for (i = 0; i < nnew; i++) {
- s = snew[i];
- if (s) {
- s->sh_num = i;
- if (s->sh_type == SHT_RELX)
- s->sh_info = backmap[s->sh_info];
- }
- }
-
- for_each_elem(symtab_section, 1, sym, ElfW(Sym))
- if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE)
- sym->st_shndx = backmap[sym->st_shndx];
- if ( !s1->static_link ) {
- for_each_elem(s1->dynsym, 1, sym, ElfW(Sym))
- if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE)
- sym->st_shndx = backmap[sym->st_shndx];
- }
- for (i = 0; i < s1->nb_sections; i++)
- sec_order[i] = i;
- tcc_free(s1->sections);
- s1->sections = snew;
- tcc_free(backmap);
- return nnew;
-}
-
-#ifdef TCC_TARGET_ARM
-static void create_arm_attribute_section(TCCState *s1)
-{
- // Needed for DLL support.
- static const unsigned char arm_attr[] = {
- 0x41, // 'A'
- 0x2c, 0x00, 0x00, 0x00, // size 0x2c
- 'a', 'e', 'a', 'b', 'i', 0x00, // "aeabi"
- 0x01, 0x22, 0x00, 0x00, 0x00, // 'File Attributes', size 0x22
- 0x05, 0x36, 0x00, // 'CPU_name', "6"
- 0x06, 0x06, // 'CPU_arch', 'v6'
- 0x08, 0x01, // 'ARM_ISA_use', 'Yes'
- 0x09, 0x01, // 'THUMB_ISA_use', 'Thumb-1'
- 0x0a, 0x02, // 'FP_arch', 'VFPv2'
- 0x12, 0x04, // 'ABI_PCS_wchar_t', 4
- 0x14, 0x01, // 'ABI_FP_denormal', 'Needed'
- 0x15, 0x01, // 'ABI_FP_exceptions', 'Needed'
- 0x17, 0x03, // 'ABI_FP_number_model', 'IEEE 754'
- 0x18, 0x01, // 'ABI_align_needed', '8-byte'
- 0x19, 0x01, // 'ABI_align_preserved', '8-byte, except leaf SP'
- 0x1a, 0x02, // 'ABI_enum_size', 'int'
- 0x1c, 0x01, // 'ABI_VFP_args', 'VFP registers'
- 0x22, 0x01 // 'CPU_unaligned_access', 'v6'
- };
- Section *attr = new_section(s1, ".ARM.attributes", SHT_ARM_ATTRIBUTES, 0);
- unsigned char *ptr = section_ptr_add(attr, sizeof(arm_attr));
- attr->sh_addralign = 1;
- memcpy(ptr, arm_attr, sizeof(arm_attr));
- if (s1->float_abi != ARM_HARD_FLOAT) {
- ptr[26] = 0x00; // 'FP_arch', 'No'
- ptr[41] = 0x1e; // 'ABI_optimization_goals'
- ptr[42] = 0x06; // 'Aggressive Debug'
- }
-}
-#endif
-
-#if TARGETOS_OpenBSD || TARGETOS_NetBSD
-static Section *create_bsd_note_section(TCCState *s1,
- const char *name,
- const char *value)
-{
- Section *s = find_section (s1, name);
-
- if (s->data_offset == 0) {
- char *ptr = section_ptr_add(s, sizeof(ElfW(Nhdr)) + 8 + 4);
- ElfW(Nhdr) *note = (ElfW(Nhdr) *) ptr;
-
- s->sh_type = SHT_NOTE;
- note->n_namesz = 8;
- note->n_descsz = 4;
- note->n_type = ELF_NOTE_OS_GNU;
- strcpy (ptr + sizeof(ElfW(Nhdr)), value);
- }
- return s;
-}
-#endif
-
-static void alloc_sec_names(TCCState *s1, int is_obj);
-
-/* Output an elf, coff or binary file */
-/* XXX: suppress unneeded sections */
-static int elf_output_file(TCCState *s1, const char *filename)
-{
- int i, ret, file_type, file_offset, *sec_order;
- struct dyn_inf dyninf = {0};
- Section *interp, *dynstr, *dynamic;
- int textrel, got_sym, dt_flags_1;
-
- file_type = s1->output_type;
- s1->nb_errors = 0;
- ret = -1;
- interp = dynstr = dynamic = NULL;
- sec_order = NULL;
- dyninf.roinf = &dyninf._roinf;
-
-#ifdef TCC_TARGET_ARM
- create_arm_attribute_section (s1);
-#endif
-
-#if TARGETOS_OpenBSD
- dyninf.note = create_bsd_note_section (s1, ".note.openbsd.ident", "OpenBSD");
-#endif
-
-#if TARGETOS_NetBSD
- dyninf.note = create_bsd_note_section (s1, ".note.netbsd.ident", "NetBSD");
-#endif
-
-#if TARGETOS_FreeBSD || TARGETOS_NetBSD
- dyninf.roinf = NULL;
-#endif
- /* if linking, also link in runtime libraries (libc, libgcc, etc.) */
- tcc_add_runtime(s1);
- resolve_common_syms(s1);
-
- if (!s1->static_link) {
- if (file_type & TCC_OUTPUT_EXE) {
- char *ptr;
- /* allow override the dynamic loader */
- const char *elfint = getenv("LD_SO");
- if (elfint == NULL)
- elfint = DEFAULT_ELFINTERP(s1);
- /* add interpreter section only if executable */
- interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
- interp->sh_addralign = 1;
- ptr = section_ptr_add(interp, 1 + strlen(elfint));
- strcpy(ptr, elfint);
- dyninf.interp = interp;
- }
-
- /* add dynamic symbol table */
- s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
- ".dynstr",
- ".hash", SHF_ALLOC);
- /* Number of local symbols (readelf complains if not set) */
- s1->dynsym->sh_info = 1;
- dynstr = s1->dynsym->link;
- /* add dynamic section */
- dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
- SHF_ALLOC | SHF_WRITE);
- dynamic->link = dynstr;
- dynamic->sh_entsize = sizeof(ElfW(Dyn));
-
- got_sym = build_got(s1);
- if (file_type == TCC_OUTPUT_EXE) {
- bind_exe_dynsyms(s1);
- if (s1->nb_errors)
- goto the_end;
- }
- build_got_entries(s1, got_sym);
- if (file_type & TCC_OUTPUT_EXE) {
- bind_libs_dynsyms(s1);
- } else {
- /* shared library case: simply export all global symbols */
- export_global_syms(s1);
- }
- dyninf.gnu_hash = create_gnu_hash(s1);
- } else {
- build_got_entries(s1, 0);
- }
- version_add (s1);
-
- textrel = set_sec_sizes(s1);
- alloc_sec_names(s1, 0);
-
- if (!s1->static_link) {
- /* add a list of needed dlls */
- for(i = 0; i < s1->nb_loaded_dlls; i++) {
- DLLReference *dllref = s1->loaded_dlls[i];
- if (dllref->level == 0)
- put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
- }
-
- if (s1->rpath)
- put_dt(dynamic, s1->enable_new_dtags ? DT_RUNPATH : DT_RPATH,
- put_elf_str(dynstr, s1->rpath));
-
- dt_flags_1 = DF_1_NOW;
- if (file_type & TCC_OUTPUT_DYN) {
- if (s1->soname)
- put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
- /* XXX: currently, since we do not handle PIC code, we
- must relocate the readonly segments */
- if (textrel)
- put_dt(dynamic, DT_TEXTREL, 0);
- if (file_type & TCC_OUTPUT_EXE)
- dt_flags_1 = DF_1_NOW | DF_1_PIE;
- }
- put_dt(dynamic, DT_FLAGS, DF_BIND_NOW);
- put_dt(dynamic, DT_FLAGS_1, dt_flags_1);
- if (s1->symbolic)
- put_dt(dynamic, DT_SYMBOLIC, 0);
-
- dyninf.dynamic = dynamic;
- dyninf.dynstr = dynstr;
- /* remember offset and reserve space for 2nd call below */
- dyninf.data_offset = dynamic->data_offset;
- fill_dynamic(s1, &dyninf);
- dynamic->sh_size = dynamic->data_offset;
- dynstr->sh_size = dynstr->data_offset;
- }
-
- /* this array is used to reorder sections in the output file */
- sec_order = tcc_malloc(sizeof(int) * 2 * s1->nb_sections);
- /* compute section to program header mapping */
- file_offset = layout_sections(s1, sec_order, &dyninf);
-
- if (dynamic) {
- /* put in GOT the dynamic section address and relocate PLT */
- write32le(s1->got->data, dynamic->sh_addr);
- if (file_type == TCC_OUTPUT_EXE
- || (RELOCATE_DLLPLT && (file_type & TCC_OUTPUT_DYN)))
- relocate_plt(s1);
- /* relocate symbols in .dynsym now that final addresses are known */
- relocate_syms(s1, s1->dynsym, 2);
- }
-
- /* if building executable or DLL, then relocate each section
- except the GOT which is already relocated */
- relocate_syms(s1, s1->symtab, 0);
- if (s1->nb_errors != 0)
- goto the_end;
- relocate_sections(s1);
- if (dynamic) {
- update_reloc_sections (s1, &dyninf);
- dynamic->data_offset = dyninf.data_offset;
- fill_dynamic(s1, &dyninf);
- }
- /* Perform relocation to GOT or PLT entries */
- if (file_type == TCC_OUTPUT_EXE && s1->static_link)
- fill_got(s1);
- else if (s1->got)
- fill_local_got_entries(s1);
-
- if (dyninf.gnu_hash)
- update_gnu_hash(s1, dyninf.gnu_hash);
-
- /* Create the ELF file with name 'filename' */
- ret = tcc_write_elf_file(s1, filename, dyninf.phnum, dyninf.phdr, file_offset, sec_order);
- the_end:
- tcc_free(sec_order);
- tcc_free(dyninf.phdr);
- return ret;
-}
-#endif /* ndef ELF_OBJ_ONLY */
-
-/* Allocate strings for section names */
-static void alloc_sec_names(TCCState *s1, int is_obj)
-{
- int i;
- Section *s, *strsec;
-
- strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
- put_elf_str(strsec, "");
- for(i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
- if (is_obj)
- s->sh_size = s->data_offset;
- if (s == strsec || s->sh_size || (s->sh_flags & SHF_ALLOC))
- s->sh_name = put_elf_str(strsec, s->name);
- }
- strsec->sh_size = strsec->data_offset;
-}
-
-/* Output an elf .o file */
-static int elf_output_obj(TCCState *s1, const char *filename)
-{
- Section *s;
- int i, ret, file_offset;
- s1->nb_errors = 0;
- /* Allocate strings for section names */
- alloc_sec_names(s1, 1);
- file_offset = sizeof (ElfW(Ehdr));
- for(i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
- file_offset = (file_offset + 15) & -16;
- s->sh_offset = file_offset;
- if (s->sh_type != SHT_NOBITS)
- file_offset += s->sh_size;
- }
- /* Create the ELF file with name 'filename' */
- ret = tcc_write_elf_file(s1, filename, 0, NULL, file_offset, NULL);
- return ret;
-}
-
-LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
-{
- if (s->test_coverage)
- tcc_tcov_add_file(s, filename);
- if (s->output_type == TCC_OUTPUT_OBJ)
- return elf_output_obj(s, filename);
-#ifdef TCC_TARGET_PE
- return pe_output_file(s, filename);
-#elif TCC_TARGET_MACHO
- return macho_output_file(s, filename);
-#else
- return elf_output_file(s, filename);
-#endif
-}
-
-ST_FUNC ssize_t full_read(int fd, void *buf, size_t count) {
- char *cbuf = buf;
- size_t rnum = 0;
- while (1) {
- ssize_t num = read(fd, cbuf, count-rnum);
- if (num < 0) return num;
- if (num == 0) return rnum;
- rnum += num;
- cbuf += num;
- }
-}
-
-ST_FUNC void *load_data(int fd, unsigned long file_offset, unsigned long size)
-{
- void *data;
-
- data = tcc_malloc(size);
- lseek(fd, file_offset, SEEK_SET);
- full_read(fd, data, size);
- return data;
-}
-
-typedef struct SectionMergeInfo {
- Section *s; /* corresponding existing section */
- unsigned long offset; /* offset of the new section in the existing section */
- uint8_t new_section; /* true if section 's' was added */
- uint8_t link_once; /* true if link once section */
-} SectionMergeInfo;
-
-ST_FUNC int tcc_object_type(int fd, ElfW(Ehdr) *h)
-{
- int size = full_read(fd, h, sizeof *h);
- if (size == sizeof *h && 0 == memcmp(h, ELFMAG, 4)) {
- if (h->e_type == ET_REL)
- return AFF_BINTYPE_REL;
- if (h->e_type == ET_DYN)
- return AFF_BINTYPE_DYN;
- } else if (size >= 8) {
- if (0 == memcmp(h, ARMAG, 8))
- return AFF_BINTYPE_AR;
-#ifdef TCC_TARGET_COFF
- if (((struct filehdr*)h)->f_magic == COFF_C67_MAGIC)
- return AFF_BINTYPE_C67;
-#endif
- }
- return 0;
-}
-
-/* load an object file and merge it with current files */
-/* XXX: handle correctly stab (debug) info */
-ST_FUNC int tcc_load_object_file(TCCState *s1,
- int fd, unsigned long file_offset)
-{
- ElfW(Ehdr) ehdr;
- ElfW(Shdr) *shdr, *sh;
- unsigned long size, offset, offseti;
- int i, j, nb_syms, sym_index, ret, seencompressed;
- char *strsec, *strtab;
- int stab_index, stabstr_index;
- int *old_to_new_syms;
- char *sh_name, *name;
- SectionMergeInfo *sm_table, *sm;
- ElfW(Sym) *sym, *symtab;
- ElfW_Rel *rel;
- Section *s;
-
- lseek(fd, file_offset, SEEK_SET);
- if (tcc_object_type(fd, &ehdr) != AFF_BINTYPE_REL)
- goto invalid;
- /* test CPU specific stuff */
- if (ehdr.e_ident[5] != ELFDATA2LSB ||
- ehdr.e_machine != EM_TCC_TARGET) {
-invalid:
- return tcc_error_noabort("invalid object file");
- }
- /* read sections */
- shdr = load_data(fd, file_offset + ehdr.e_shoff,
- sizeof(ElfW(Shdr)) * ehdr.e_shnum);
- sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
-
- /* load section names */
- sh = &shdr[ehdr.e_shstrndx];
- strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
-
- /* load symtab and strtab */
- old_to_new_syms = NULL;
- symtab = NULL;
- strtab = NULL;
- nb_syms = 0;
- seencompressed = 0;
- stab_index = stabstr_index = 0;
- ret = -1;
-
- for(i = 1; i < ehdr.e_shnum; i++) {
- sh = &shdr[i];
- if (sh->sh_type == SHT_SYMTAB) {
- if (symtab) {
- tcc_error_noabort("object must contain only one symtab");
- goto the_end;
- }
- nb_syms = sh->sh_size / sizeof(ElfW(Sym));
- symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
- sm_table[i].s = symtab_section;
-
- /* now load strtab */
- sh = &shdr[sh->sh_link];
- strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
- }
- if (sh->sh_flags & SHF_COMPRESSED)
- seencompressed = 1;
- }
-
- /* now examine each section and try to merge its content with the
- ones in memory */
- for(i = 1; i < ehdr.e_shnum; i++) {
- /* no need to examine section name strtab */
- if (i == ehdr.e_shstrndx)
- continue;
- sh = &shdr[i];
- if (sh->sh_type == SHT_RELX)
- sh = &shdr[sh->sh_info];
- /* ignore sections types we do not handle (plus relocs to those) */
- if (sh->sh_type != SHT_PROGBITS &&
-#ifdef TCC_ARM_EABI
- sh->sh_type != SHT_ARM_EXIDX &&
-#endif
-#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
- sh->sh_type != SHT_X86_64_UNWIND &&
-#endif
- sh->sh_type != SHT_NOTE &&
- sh->sh_type != SHT_NOBITS &&
- sh->sh_type != SHT_PREINIT_ARRAY &&
- sh->sh_type != SHT_INIT_ARRAY &&
- sh->sh_type != SHT_FINI_ARRAY &&
- strcmp(strsec + sh->sh_name, ".stabstr")
- )
- continue;
- if (seencompressed && 0 == strncmp(strsec + sh->sh_name, ".debug_", 7))
- continue;
-
- sh = &shdr[i];
- sh_name = strsec + sh->sh_name;
- if (sh->sh_addralign < 1)
- sh->sh_addralign = 1;
- /* find corresponding section, if any */
- for(j = 1; j < s1->nb_sections;j++) {
- s = s1->sections[j];
- if (!strcmp(s->name, sh_name)) {
- if (!strncmp(sh_name, ".gnu.linkonce",
- sizeof(".gnu.linkonce") - 1)) {
- /* if a 'linkonce' section is already present, we
- do not add it again. It is a little tricky as
- symbols can still be defined in
- it. */
- sm_table[i].link_once = 1;
- goto next;
- }
- if (stab_section) {
- if (s == stab_section)
- stab_index = i;
- if (s == stab_section->link)
- stabstr_index = i;
- }
- goto found;
- }
- }
- /* not found: create new section */
- s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags & ~SHF_GROUP);
- /* take as much info as possible from the section. sh_link and
- sh_info will be updated later */
- s->sh_addralign = sh->sh_addralign;
- s->sh_entsize = sh->sh_entsize;
- sm_table[i].new_section = 1;
- found:
- if (sh->sh_type != s->sh_type
-#if TARGETOS_OpenBSD || TARGETOS_FreeBSD || TARGETOS_NetBSD
- && strcmp (s->name, ".eh_frame")
-#endif
- ) {
- tcc_error_noabort("invalid section type");
- goto the_end;
- }
- /* align start of section */
- s->data_offset += -s->data_offset & (sh->sh_addralign - 1);
- if (sh->sh_addralign > s->sh_addralign)
- s->sh_addralign = sh->sh_addralign;
- sm_table[i].offset = s->data_offset;
- sm_table[i].s = s;
- /* concatenate sections */
- size = sh->sh_size;
- if (sh->sh_type != SHT_NOBITS) {
- unsigned char *ptr;
- lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
- ptr = section_ptr_add(s, size);
- full_read(fd, ptr, size);
- } else {
- s->data_offset += size;
- }
- next: ;
- }
-
- /* gr relocate stab strings */
- if (stab_index && stabstr_index) {
- Stab_Sym *a, *b;
- unsigned o;
- s = sm_table[stab_index].s;
- a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
- b = (Stab_Sym *)(s->data + s->data_offset);
- o = sm_table[stabstr_index].offset;
- while (a < b) {
- if (a->n_strx)
- a->n_strx += o;
- a++;
- }
- }
-
- /* second short pass to update sh_link and sh_info fields of new
- sections */
- for(i = 1; i < ehdr.e_shnum; i++) {
- s = sm_table[i].s;
- if (!s || !sm_table[i].new_section)
- continue;
- sh = &shdr[i];
- if (sh->sh_link > 0)
- s->link = sm_table[sh->sh_link].s;
- if (sh->sh_type == SHT_RELX) {
- s->sh_info = sm_table[sh->sh_info].s->sh_num;
- /* update backward link */
- s1->sections[s->sh_info]->reloc = s;
- }
- }
-
- /* resolve symbols */
- old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
-
- sym = symtab + 1;
- for(i = 1; i < nb_syms; i++, sym++) {
- if (sym->st_shndx != SHN_UNDEF &&
- sym->st_shndx < SHN_LORESERVE) {
- sm = &sm_table[sym->st_shndx];
- if (sm->link_once) {
- /* if a symbol is in a link once section, we use the
- already defined symbol. It is very important to get
- correct relocations */
- if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
- name = strtab + sym->st_name;
- sym_index = find_elf_sym(symtab_section, name);
- if (sym_index)
- old_to_new_syms[i] = sym_index;
- }
- continue;
- }
- /* if no corresponding section added, no need to add symbol */
- if (!sm->s)
- continue;
- /* convert section number */
- sym->st_shndx = sm->s->sh_num;
- /* offset value */
- sym->st_value += sm->offset;
- }
- /* add symbol */
- name = strtab + sym->st_name;
- sym_index = set_elf_sym(symtab_section, sym->st_value, sym->st_size,
- sym->st_info, sym->st_other,
- sym->st_shndx, name);
- old_to_new_syms[i] = sym_index;
- }
-
- /* third pass to patch relocation entries */
- for(i = 1; i < ehdr.e_shnum; i++) {
- s = sm_table[i].s;
- if (!s)
- continue;
- sh = &shdr[i];
- offset = sm_table[i].offset;
- size = sh->sh_size;
- switch(s->sh_type) {
- case SHT_RELX:
- /* take relocation offset information */
- offseti = sm_table[sh->sh_info].offset;
- for (rel = (ElfW_Rel *) s->data + (offset / sizeof(*rel));
- rel < (ElfW_Rel *) s->data + ((offset + size) / sizeof(*rel));
- rel++) {
- int type;
- unsigned sym_index;
- /* convert symbol index */
- type = ELFW(R_TYPE)(rel->r_info);
- sym_index = ELFW(R_SYM)(rel->r_info);
- /* NOTE: only one symtab assumed */
- if (sym_index >= nb_syms)
- goto invalid_reloc;
- sym_index = old_to_new_syms[sym_index];
- /* ignore link_once in rel section. */
- if (!sym_index && !sm_table[sh->sh_info].link_once
-#ifdef TCC_TARGET_ARM
- && type != R_ARM_V4BX
-#elif defined TCC_TARGET_RISCV64
- && type != R_RISCV_ALIGN
- && type != R_RISCV_RELAX
-#endif
- ) {
- invalid_reloc:
- tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
- i, strsec + sh->sh_name, (int)rel->r_offset);
- goto the_end;
- }
- rel->r_info = ELFW(R_INFO)(sym_index, type);
- /* offset the relocation offset */
- rel->r_offset += offseti;
-#ifdef TCC_TARGET_ARM
- /* Jumps and branches from a Thumb code to a PLT entry need
- special handling since PLT entries are ARM code.
- Unconditional bl instructions referencing PLT entries are
- handled by converting these instructions into blx
- instructions. Other case of instructions referencing a PLT
- entry require to add a Thumb stub before the PLT entry to
- switch to ARM mode. We set bit plt_thumb_stub of the
- attribute of a symbol to indicate such a case. */
- if (type == R_ARM_THM_JUMP24)
- get_sym_attr(s1, sym_index, 1)->plt_thumb_stub = 1;
-#endif
- }
- break;
- default:
- break;
- }
- }
-
- ret = 0;
- the_end:
- tcc_free(symtab);
- tcc_free(strtab);
- tcc_free(old_to_new_syms);
- tcc_free(sm_table);
- tcc_free(strsec);
- tcc_free(shdr);
- return ret;
-}
-
-typedef struct ArchiveHeader {
- char ar_name[16]; /* name of this member */
- char ar_date[12]; /* file mtime */
- char ar_uid[6]; /* owner uid; printed as decimal */
- char ar_gid[6]; /* owner gid; printed as decimal */
- char ar_mode[8]; /* file mode, printed as octal */
- char ar_size[10]; /* file size, printed as decimal */
- char ar_fmag[2]; /* should contain ARFMAG */
-} ArchiveHeader;
-
-#define ARFMAG "`\n"
-
-static unsigned long long get_be(const uint8_t *b, int n)
-{
- unsigned long long ret = 0;
- while (n)
- ret = (ret << 8) | *b++, --n;
- return ret;
-}
-
-static int read_ar_header(int fd, int offset, ArchiveHeader *hdr)
-{
- char *p, *e;
- int len;
- lseek(fd, offset, SEEK_SET);
- len = full_read(fd, hdr, sizeof(ArchiveHeader));
- if (len != sizeof(ArchiveHeader))
- return len ? -1 : 0;
- p = hdr->ar_name;
- for (e = p + sizeof hdr->ar_name; e > p && e[-1] == ' ';)
- --e;
- *e = '\0';
- hdr->ar_size[sizeof hdr->ar_size-1] = 0;
- return len;
-}
-
-/* load only the objects which resolve undefined symbols */
-static int tcc_load_alacarte(TCCState *s1, int fd, int size, int entrysize)
-{
- int i, bound, nsyms, sym_index, len, ret = -1;
- unsigned long long off;
- uint8_t *data;
- const char *ar_names, *p;
- const uint8_t *ar_index;
- ElfW(Sym) *sym;
- ArchiveHeader hdr;
-
- data = tcc_malloc(size);
- if (full_read(fd, data, size) != size)
- goto the_end;
- nsyms = get_be(data, entrysize);
- ar_index = data + entrysize;
- ar_names = (char *) ar_index + nsyms * entrysize;
-
- do {
- bound = 0;
- for (p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
- Section *s = symtab_section;
- sym_index = find_elf_sym(s, p);
- if (!sym_index)
- continue;
- sym = &((ElfW(Sym) *)s->data)[sym_index];
- if(sym->st_shndx != SHN_UNDEF)
- continue;
- off = get_be(ar_index + i * entrysize, entrysize);
- len = read_ar_header(fd, off, &hdr);
- if (len <= 0 || memcmp(hdr.ar_fmag, ARFMAG, 2)) {
- tcc_error_noabort("invalid archive");
- goto the_end;
- }
- off += len;
- if (s1->verbose == 2)
- printf(" -> %s\n", hdr.ar_name);
- if (tcc_load_object_file(s1, fd, off) < 0)
- goto the_end;
- ++bound;
- }
- } while(bound);
- ret = 0;
- the_end:
- tcc_free(data);
- return ret;
-}
-
-/* load a '.a' file */
-ST_FUNC int tcc_load_archive(TCCState *s1, int fd, int alacarte)
-{
- ArchiveHeader hdr;
- /* char magic[8]; */
- int size, len;
- unsigned long file_offset;
- ElfW(Ehdr) ehdr;
-
- /* skip magic which was already checked */
- /* full_read(fd, magic, sizeof(magic)); */
- file_offset = sizeof ARMAG - 1;
-
- for(;;) {
- len = read_ar_header(fd, file_offset, &hdr);
- if (len == 0)
- return 0;
- if (len < 0)
- return tcc_error_noabort("invalid archive");
- file_offset += len;
- size = strtol(hdr.ar_size, NULL, 0);
- /* align to even */
- size = (size + 1) & ~1;
- if (alacarte) {
- /* coff symbol table : we handle it */
- if (!strcmp(hdr.ar_name, "/"))
- return tcc_load_alacarte(s1, fd, size, 4);
- if (!strcmp(hdr.ar_name, "/SYM64/"))
- return tcc_load_alacarte(s1, fd, size, 8);
- } else if (tcc_object_type(fd, &ehdr) == AFF_BINTYPE_REL) {
- if (s1->verbose == 2)
- printf(" -> %s\n", hdr.ar_name);
- if (tcc_load_object_file(s1, fd, file_offset) < 0)
- return -1;
- }
- file_offset += size;
- }
-}
-
-#ifndef ELF_OBJ_ONLY
-/* Set LV[I] to the global index of sym-version (LIB,VERSION). Maybe resizes
- LV, maybe create a new entry for (LIB,VERSION). */
-static void set_ver_to_ver(TCCState *s1, int *n, int **lv, int i, char *lib, char *version)
-{
- while (i >= *n) {
- *lv = tcc_realloc(*lv, (*n + 1) * sizeof(**lv));
- (*lv)[(*n)++] = -1;
- }
- if ((*lv)[i] == -1) {
- int v, prev_same_lib = -1;
- for (v = 0; v < nb_sym_versions; v++) {
- if (strcmp(sym_versions[v].lib, lib))
- continue;
- prev_same_lib = v;
- if (!strcmp(sym_versions[v].version, version))
- break;
- }
- if (v == nb_sym_versions) {
- sym_versions = tcc_realloc (sym_versions,
- (v + 1) * sizeof(*sym_versions));
- sym_versions[v].lib = tcc_strdup(lib);
- sym_versions[v].version = tcc_strdup(version);
- sym_versions[v].out_index = 0;
- sym_versions[v].prev_same_lib = prev_same_lib;
- nb_sym_versions++;
- }
- (*lv)[i] = v;
- }
-}
-
-/* Associates symbol SYM_INDEX (in dynsymtab) with sym-version index
- VERNDX. */
-static void
-set_sym_version(TCCState *s1, int sym_index, int verndx)
-{
- if (sym_index >= nb_sym_to_version) {
- int newelems = sym_index ? sym_index * 2 : 1;
- sym_to_version = tcc_realloc(sym_to_version,
- newelems * sizeof(*sym_to_version));
- memset(sym_to_version + nb_sym_to_version, -1,
- (newelems - nb_sym_to_version) * sizeof(*sym_to_version));
- nb_sym_to_version = newelems;
- }
- if (sym_to_version[sym_index] < 0)
- sym_to_version[sym_index] = verndx;
-}
-
-struct versym_info {
- int nb_versyms;
- ElfW(Verdef) *verdef;
- ElfW(Verneed) *verneed;
- ElfW(Half) *versym;
- int nb_local_ver, *local_ver;
-};
-
-
-static void store_version(TCCState *s1, struct versym_info *v, char *dynstr)
-{
- char *lib, *version;
- uint32_t next;
- int i;
-
-#define DEBUG_VERSION 0
-
- if (v->versym && v->verdef) {
- ElfW(Verdef) *vdef = v->verdef;
- lib = NULL;
- do {
- ElfW(Verdaux) *verdaux =
- (ElfW(Verdaux) *) (((char *) vdef) + vdef->vd_aux);
-
-#if DEBUG_VERSION
- printf ("verdef: version:%u flags:%u index:%u, hash:%u\n",
- vdef->vd_version, vdef->vd_flags, vdef->vd_ndx,
- vdef->vd_hash);
-#endif
- if (vdef->vd_cnt) {
- version = dynstr + verdaux->vda_name;
-
- if (lib == NULL)
- lib = version;
- else
- set_ver_to_ver(s1, &v->nb_local_ver, &v->local_ver, vdef->vd_ndx,
- lib, version);
-#if DEBUG_VERSION
- printf (" verdaux(%u): %s\n", vdef->vd_ndx, version);
-#endif
- }
- next = vdef->vd_next;
- vdef = (ElfW(Verdef) *) (((char *) vdef) + next);
- } while (next);
- }
- if (v->versym && v->verneed) {
- ElfW(Verneed) *vneed = v->verneed;
- do {
- ElfW(Vernaux) *vernaux =
- (ElfW(Vernaux) *) (((char *) vneed) + vneed->vn_aux);
-
- lib = dynstr + vneed->vn_file;
-#if DEBUG_VERSION
- printf ("verneed: %u %s\n", vneed->vn_version, lib);
-#endif
- for (i = 0; i < vneed->vn_cnt; i++) {
- if ((vernaux->vna_other & 0x8000) == 0) { /* hidden */
- version = dynstr + vernaux->vna_name;
- set_ver_to_ver(s1, &v->nb_local_ver, &v->local_ver, vernaux->vna_other,
- lib, version);
-#if DEBUG_VERSION
- printf (" vernaux(%u): %u %u %s\n",
- vernaux->vna_other, vernaux->vna_hash,
- vernaux->vna_flags, version);
-#endif
- }
- vernaux = (ElfW(Vernaux) *) (((char *) vernaux) + vernaux->vna_next);
- }
- next = vneed->vn_next;
- vneed = (ElfW(Verneed) *) (((char *) vneed) + next);
- } while (next);
- }
-
-#if DEBUG_VERSION
- for (i = 0; i < v->nb_local_ver; i++) {
- if (v->local_ver[i] > 0) {
- printf ("%d: lib: %s, version %s\n",
- i, sym_versions[v->local_ver[i]].lib,
- sym_versions[v->local_ver[i]].version);
- }
- }
-#endif
-}
-
-/* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
- is referenced by the user (so it should be added as DT_NEEDED in
- the generated ELF file) */
-ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
-{
- ElfW(Ehdr) ehdr;
- ElfW(Shdr) *shdr, *sh, *sh1;
- int i, nb_syms, nb_dts, sym_bind, ret = -1;
- ElfW(Sym) *sym, *dynsym;
- ElfW(Dyn) *dt, *dynamic;
-
- char *dynstr;
- int sym_index;
- const char *name, *soname;
- struct versym_info v;
-
- full_read(fd, &ehdr, sizeof(ehdr));
-
- /* test CPU specific stuff */
- if (ehdr.e_ident[5] != ELFDATA2LSB ||
- ehdr.e_machine != EM_TCC_TARGET) {
- return tcc_error_noabort("bad architecture");
- }
-
- /* read sections */
- shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
-
- /* load dynamic section and dynamic symbols */
- nb_syms = 0;
- nb_dts = 0;
- dynamic = NULL;
- dynsym = NULL; /* avoid warning */
- dynstr = NULL; /* avoid warning */
- memset(&v, 0, sizeof v);
-
- for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
- switch(sh->sh_type) {
- case SHT_DYNAMIC:
- nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
- dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
- break;
- case SHT_DYNSYM:
- nb_syms = sh->sh_size / sizeof(ElfW(Sym));
- dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
- sh1 = &shdr[sh->sh_link];
- dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
- break;
- case SHT_GNU_verdef:
- v.verdef = load_data(fd, sh->sh_offset, sh->sh_size);
- break;
- case SHT_GNU_verneed:
- v.verneed = load_data(fd, sh->sh_offset, sh->sh_size);
- break;
- case SHT_GNU_versym:
- v.nb_versyms = sh->sh_size / sizeof(ElfW(Half));
- v.versym = load_data(fd, sh->sh_offset, sh->sh_size);
- break;
- default:
- break;
- }
- }
-
- if (!dynamic)
- goto the_end;
-
- /* compute the real library name */
- soname = tcc_basename(filename);
- for(i = 0, dt = dynamic; i < nb_dts; i++, dt++)
- if (dt->d_tag == DT_SONAME)
- soname = dynstr + dt->d_un.d_val;
-
- /* if the dll is already loaded, do not load it */
- if (tcc_add_dllref(s1, soname, level)->found)
- goto ret_success;
-
- if (v.nb_versyms != nb_syms)
- tcc_free (v.versym), v.versym = NULL;
- else
- store_version(s1, &v, dynstr);
-
- /* add dynamic symbols in dynsym_section */
- for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
- sym_bind = ELFW(ST_BIND)(sym->st_info);
- if (sym_bind == STB_LOCAL)
- continue;
- name = dynstr + sym->st_name;
- sym_index = set_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
- sym->st_info, sym->st_other, sym->st_shndx, name);
- if (v.versym) {
- ElfW(Half) vsym = v.versym[i];
- if ((vsym & 0x8000) == 0 && vsym > 0 && vsym < v.nb_local_ver)
- set_sym_version(s1, sym_index, v.local_ver[vsym]);
- }
- }
-
- for(i = 0, dt = dynamic; i < nb_dts; i++, dt++)
- if (dt->d_tag == DT_RPATH)
- tcc_add_library_path(s1, dynstr + dt->d_un.d_val);
-
- /* load all referenced DLLs */
- for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
- switch(dt->d_tag) {
- case DT_NEEDED:
- name = dynstr + dt->d_un.d_val;
- if (tcc_add_dllref(s1, name, -1))
- continue;
- if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
- ret = tcc_error_noabort("referenced dll '%s' not found", name);
- goto the_end;
- }
- }
- }
-
- ret_success:
- ret = 0;
- the_end:
- tcc_free(dynstr);
- tcc_free(dynsym);
- tcc_free(dynamic);
- tcc_free(shdr);
- tcc_free(v.local_ver);
- tcc_free(v.verdef);
- tcc_free(v.verneed);
- tcc_free(v.versym);
- return ret;
-}
-
-#define LD_TOK_NAME 256
-#define LD_TOK_EOF (-1)
-
-static int ld_inp(TCCState *s1)
-{
- char b;
- if (s1->cc != -1) {
- int c = s1->cc;
- s1->cc = -1;
- return c;
- }
- if (1 == read(s1->fd, &b, 1))
- return b;
- return CH_EOF;
-}
-
-/* return next ld script token */
-static int ld_next(TCCState *s1, char *name, int name_size)
-{
- int c, d, ch;
- char *q;
-
- redo:
- ch = ld_inp(s1);
- switch(ch) {
- case ' ':
- case '\t':
- case '\f':
- case '\v':
- case '\r':
- case '\n':
- goto redo;
- case '/':
- ch = ld_inp(s1);
- if (ch == '*') { /* comment */
- for (d = 0;; d = ch) {
- ch = ld_inp(s1);
- if (ch == CH_EOF || (ch == '/' && d == '*'))
- break;
- }
- goto redo;
- } else {
- q = name;
- *q++ = '/';
- goto parse_name;
- }
- break;
- case '\\':
- /* case 'a' ... 'z': */
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w':
- case 'x':
- case 'y':
- case 'z':
- /* case 'A' ... 'z': */
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W':
- case 'X':
- case 'Y':
- case 'Z':
- case '_':
- case '.':
- case '$':
- case '~':
- q = name;
- parse_name:
- for(;;) {
- if (!((ch >= 'a' && ch <= 'z') ||
- (ch >= 'A' && ch <= 'Z') ||
- (ch >= '0' && ch <= '9') ||
- strchr("/.-_+=$:\\,~", ch)))
- break;
- if ((q - name) < name_size - 1) {
- *q++ = ch;
- }
- ch = ld_inp(s1);
- }
- s1->cc = ch;
- *q = '\0';
- c = LD_TOK_NAME;
- break;
- case CH_EOF:
- c = LD_TOK_EOF;
- break;
- default:
- c = ch;
- break;
- }
- return c;
-}
-
-static int ld_add_file(TCCState *s1, const char filename[])
-{
- if (filename[0] == '/') {
- if (CONFIG_SYSROOT[0] == '\0'
- && tcc_add_file_internal(s1, filename, AFF_TYPE_BIN) == 0)
- return 0;
- filename = tcc_basename(filename);
- }
- return tcc_add_dll(s1, filename, 0);
-}
-
-static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
-{
- char filename[1024], libname[1024];
- int t, group, nblibs = 0, ret = 0;
- char **libs = NULL;
-
- group = !strcmp(cmd, "GROUP");
- if (!as_needed)
- s1->new_undef_sym = 0;
- t = ld_next(s1, filename, sizeof(filename));
- if (t != '(') {
- ret = tcc_error_noabort("( expected");
- goto lib_parse_error;
- }
- t = ld_next(s1, filename, sizeof(filename));
- for(;;) {
- libname[0] = '\0';
- if (t == LD_TOK_EOF) {
- ret = tcc_error_noabort("unexpected end of file");
- goto lib_parse_error;
- } else if (t == ')') {
- break;
- } else if (t == '-') {
- t = ld_next(s1, filename, sizeof(filename));
- if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
- ret = tcc_error_noabort("library name expected");
- goto lib_parse_error;
- }
- pstrcpy(libname, sizeof libname, &filename[1]);
- if (s1->static_link) {
- snprintf(filename, sizeof filename, "lib%s.a", libname);
- } else {
- snprintf(filename, sizeof filename, "lib%s.so", libname);
- }
- } else if (t != LD_TOK_NAME) {
- ret = tcc_error_noabort("filename expected");
- goto lib_parse_error;
- }
- if (!strcmp(filename, "AS_NEEDED")) {
- ret = ld_add_file_list(s1, cmd, 1);
- if (ret)
- goto lib_parse_error;
- } else {
- /* TODO: Implement AS_NEEDED support. Ignore it for now */
- if (!as_needed) {
- ret = ld_add_file(s1, filename);
- if (ret)
- goto lib_parse_error;
- if (group) {
- /* Add the filename *and* the libname to avoid future conversions */
- dynarray_add(&libs, &nblibs, tcc_strdup(filename));
- if (libname[0] != '\0')
- dynarray_add(&libs, &nblibs, tcc_strdup(libname));
- }
- }
- }
- t = ld_next(s1, filename, sizeof(filename));
- if (t == ',') {
- t = ld_next(s1, filename, sizeof(filename));
- }
- }
- if (group && !as_needed) {
- while (s1->new_undef_sym) {
- int i;
- s1->new_undef_sym = 0;
- for (i = 0; i < nblibs; i ++)
- ld_add_file(s1, libs[i]);
- }
- }
-lib_parse_error:
- dynarray_reset(&libs, &nblibs);
- return ret;
-}
-
-/* interpret a subset of GNU ldscripts to handle the dummy libc.so
- files */
-ST_FUNC int tcc_load_ldscript(TCCState *s1, int fd)
-{
- char cmd[64];
- char filename[1024];
- int t, ret;
-
- s1->fd = fd;
- s1->cc = -1;
- for(;;) {
- t = ld_next(s1, cmd, sizeof(cmd));
- if (t == LD_TOK_EOF)
- return 0;
- else if (t != LD_TOK_NAME)
- return -1;
- if (!strcmp(cmd, "INPUT") ||
- !strcmp(cmd, "GROUP")) {
- ret = ld_add_file_list(s1, cmd, 0);
- if (ret)
- return ret;
- } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
- !strcmp(cmd, "TARGET")) {
- /* ignore some commands */
- t = ld_next(s1, cmd, sizeof(cmd));
- if (t != '(')
- return tcc_error_noabort("( expected");
- for(;;) {
- t = ld_next(s1, filename, sizeof(filename));
- if (t == LD_TOK_EOF) {
- return tcc_error_noabort("unexpected end of file");
- } else if (t == ')') {
- break;
- }
- }
- } else {
- return -1;
- }
- }
- return 0;
-}
-#endif /* !ELF_OBJ_ONLY */
diff --git a/tinycc/tccgen.c b/tinycc/tccgen.c
deleted file mode 100644
index c582c4a..0000000
--- a/tinycc/tccgen.c
+++ /dev/null
@@ -1,8678 +0,0 @@
-/*
- * TCC - Tiny C Compiler
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define USING_GLOBALS
-#include "tcc.h"
-
-/********************************************************/
-/* global variables */
-
-/* loc : local variable index
- ind : output code index
- rsym: return symbol
- anon_sym: anonymous symbol index
-*/
-ST_DATA int rsym, anon_sym, ind, loc;
-
-ST_DATA Sym *global_stack;
-ST_DATA Sym *local_stack;
-ST_DATA Sym *define_stack;
-ST_DATA Sym *global_label_stack;
-ST_DATA Sym *local_label_stack;
-
-static Sym *sym_free_first;
-static void **sym_pools;
-static int nb_sym_pools;
-
-static Sym *all_cleanups, *pending_gotos;
-static int local_scope;
-static int in_sizeof;
-static int constant_p;
-ST_DATA char debug_modes;
-
-ST_DATA SValue *vtop;
-static SValue _vstack[1 + VSTACK_SIZE];
-#define vstack (_vstack + 1)
-
-ST_DATA int nocode_wanted; /* no code generation wanted */
-#define NODATA_WANTED (nocode_wanted > 0) /* no static data output wanted either */
-#define DATA_ONLY_WANTED 0x80000000 /* ON outside of functions and for static initializers */
-
-/* no code output after unconditional jumps such as with if (0) ... */
-#define CODE_OFF_BIT 0x20000000
-#define CODE_OFF() if(!nocode_wanted)(nocode_wanted |= CODE_OFF_BIT)
-#define CODE_ON() (nocode_wanted &= ~CODE_OFF_BIT)
-
-/* no code output when parsing sizeof()/typeof() etc. (using nocode_wanted++/--) */
-#define NOEVAL_MASK 0x0000FFFF
-#define NOEVAL_WANTED (nocode_wanted & NOEVAL_MASK)
-
-/* no code output when parsing constant expressions */
-#define CONST_WANTED_BIT 0x00010000
-#define CONST_WANTED_MASK 0x0FFF0000
-#define CONST_WANTED (nocode_wanted & CONST_WANTED_MASK)
-
-ST_DATA int global_expr; /* true if compound literals must be allocated globally (used during initializers parsing */
-ST_DATA CType func_vt; /* current function return type (used by return instruction) */
-ST_DATA int func_var; /* true if current function is variadic (used by return instruction) */
-ST_DATA int func_vc;
-ST_DATA int func_ind;
-ST_DATA const char *funcname;
-ST_DATA CType int_type, func_old_type, char_type, char_pointer_type;
-static CString initstr;
-
-#if PTR_SIZE == 4
-#define VT_SIZE_T (VT_INT | VT_UNSIGNED)
-#define VT_PTRDIFF_T VT_INT
-#elif LONG_SIZE == 4
-#define VT_SIZE_T (VT_LLONG | VT_UNSIGNED)
-#define VT_PTRDIFF_T VT_LLONG
-#else
-#define VT_SIZE_T (VT_LONG | VT_LLONG | VT_UNSIGNED)
-#define VT_PTRDIFF_T (VT_LONG | VT_LLONG)
-#endif
-
-static struct switch_t {
- struct case_t {
- int64_t v1, v2;
- int sym;
- } **p; int n; /* list of case ranges */
- int def_sym; /* default symbol */
- int nocode_wanted;
- int *bsym;
- struct scope *scope;
- struct switch_t *prev;
- SValue sv;
-} *cur_switch; /* current switch */
-
-#define MAX_TEMP_LOCAL_VARIABLE_NUMBER 8
-/*list of temporary local variables on the stack in current function. */
-static struct temp_local_variable {
- int location; //offset on stack. Svalue.c.i
- short size;
- short align;
-} arr_temp_local_vars[MAX_TEMP_LOCAL_VARIABLE_NUMBER];
-static int nb_temp_local_vars;
-
-static struct scope {
- struct scope *prev;
- struct { int loc, locorig, num; } vla;
- struct { Sym *s; int n; } cl;
- int *bsym, *csym;
- Sym *lstk, *llstk;
-} *cur_scope, *loop_scope, *root_scope;
-
-typedef struct {
- Section *sec;
- int local_offset;
- Sym *flex_array_ref;
-} init_params;
-
-#if 1
-#define precedence_parser
-static void init_prec(void);
-#endif
-
-static void gen_cast(CType *type);
-static void gen_cast_s(int t);
-static inline CType *pointed_type(CType *type);
-static int is_compatible_types(CType *type1, CType *type2);
-static int parse_btype(CType *type, AttributeDef *ad, int ignore_label);
-static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
-static void parse_expr_type(CType *type);
-static void init_putv(init_params *p, CType *type, unsigned long c);
-static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags);
-static void block(int is_expr);
-static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope);
-static int decl(int l);
-static void expr_eq(void);
-static void vpush_type_size(CType *type, int *a);
-static int is_compatible_unqualified_types(CType *type1, CType *type2);
-static inline int64_t expr_const64(void);
-static void vpush64(int ty, unsigned long long v);
-static void vpush(CType *type);
-static int gvtst(int inv, int t);
-static void gen_inline_functions(TCCState *s);
-static void free_inline_functions(TCCState *s);
-static void skip_or_save_block(TokenString **str);
-static void gv_dup(void);
-static int get_temp_local_var(int size,int align);
-static void clear_temp_local_var_list();
-static void cast_error(CType *st, CType *dt);
-
-/* ------------------------------------------------------------------------- */
-/* Automagical code suppression */
-
-/* Clear 'nocode_wanted' at forward label if it was used */
-ST_FUNC void gsym(int t)
-{
- if (t) {
- gsym_addr(t, ind);
- CODE_ON();
- }
-}
-
-/* Clear 'nocode_wanted' if current pc is a label */
-static int gind()
-{
- int t = ind;
- CODE_ON();
- if (debug_modes)
- tcc_tcov_block_begin(tcc_state);
- return t;
-}
-
-/* Set 'nocode_wanted' after unconditional (backwards) jump */
-static void gjmp_addr_acs(int t)
-{
- gjmp_addr(t);
- CODE_OFF();
-}
-
-/* Set 'nocode_wanted' after unconditional (forwards) jump */
-static int gjmp_acs(int t)
-{
- t = gjmp(t);
- CODE_OFF();
- return t;
-}
-
-/* These are #undef'd at the end of this file */
-#define gjmp_addr gjmp_addr_acs
-#define gjmp gjmp_acs
-/* ------------------------------------------------------------------------- */
-
-ST_INLN int is_float(int t)
-{
- int bt = t & VT_BTYPE;
- return bt == VT_LDOUBLE
- || bt == VT_DOUBLE
- || bt == VT_FLOAT
- || bt == VT_QFLOAT;
-}
-
-static inline int is_integer_btype(int bt)
-{
- return bt == VT_BYTE
- || bt == VT_BOOL
- || bt == VT_SHORT
- || bt == VT_INT
- || bt == VT_LLONG;
-}
-
-static int btype_size(int bt)
-{
- return bt == VT_BYTE || bt == VT_BOOL ? 1 :
- bt == VT_SHORT ? 2 :
- bt == VT_INT ? 4 :
- bt == VT_LLONG ? 8 :
- bt == VT_PTR ? PTR_SIZE : 0;
-}
-
-/* returns function return register from type */
-static int R_RET(int t)
-{
- if (!is_float(t))
- return REG_IRET;
-#ifdef TCC_TARGET_X86_64
- if ((t & VT_BTYPE) == VT_LDOUBLE)
- return TREG_ST0;
-#elif defined TCC_TARGET_RISCV64
- if ((t & VT_BTYPE) == VT_LDOUBLE)
- return REG_IRET;
-#endif
- return REG_FRET;
-}
-
-/* returns 2nd function return register, if any */
-static int R2_RET(int t)
-{
- t &= VT_BTYPE;
-#if PTR_SIZE == 4
- if (t == VT_LLONG)
- return REG_IRE2;
-#elif defined TCC_TARGET_X86_64
- if (t == VT_QLONG)
- return REG_IRE2;
- if (t == VT_QFLOAT)
- return REG_FRE2;
-#elif defined TCC_TARGET_RISCV64
- if (t == VT_LDOUBLE)
- return REG_IRE2;
-#endif
- return VT_CONST;
-}
-
-/* returns true for two-word types */
-#define USING_TWO_WORDS(t) (R2_RET(t) != VT_CONST)
-
-/* put function return registers to stack value */
-static void PUT_R_RET(SValue *sv, int t)
-{
- sv->r = R_RET(t), sv->r2 = R2_RET(t);
-}
-
-/* returns function return register class for type t */
-static int RC_RET(int t)
-{
- return reg_classes[R_RET(t)] & ~(RC_FLOAT | RC_INT);
-}
-
-/* returns generic register class for type t */
-static int RC_TYPE(int t)
-{
- if (!is_float(t))
- return RC_INT;
-#ifdef TCC_TARGET_X86_64
- if ((t & VT_BTYPE) == VT_LDOUBLE)
- return RC_ST0;
- if ((t & VT_BTYPE) == VT_QFLOAT)
- return RC_FRET;
-#elif defined TCC_TARGET_RISCV64
- if ((t & VT_BTYPE) == VT_LDOUBLE)
- return RC_INT;
-#endif
- return RC_FLOAT;
-}
-
-/* returns 2nd register class corresponding to t and rc */
-static int RC2_TYPE(int t, int rc)
-{
- if (!USING_TWO_WORDS(t))
- return 0;
-#ifdef RC_IRE2
- if (rc == RC_IRET)
- return RC_IRE2;
-#endif
-#ifdef RC_FRE2
- if (rc == RC_FRET)
- return RC_FRE2;
-#endif
- if (rc & RC_FLOAT)
- return RC_FLOAT;
- return RC_INT;
-}
-
-/* we use our own 'finite' function to avoid potential problems with
- non standard math libs */
-/* XXX: endianness dependent */
-ST_FUNC int ieee_finite(double d)
-{
- int p[4];
- memcpy(p, &d, sizeof(double));
- return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
-}
-
-/* compiling intel long double natively */
-#if (defined __i386__ || defined __x86_64__) \
- && (defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64)
-# define TCC_IS_NATIVE_387
-#endif
-
-ST_FUNC void test_lvalue(void)
-{
- if (!(vtop->r & VT_LVAL))
- expect("lvalue");
-}
-
-ST_FUNC void check_vstack(void)
-{
- if (vtop != vstack - 1)
- tcc_error("internal compiler error: vstack leak (%d)",
- (int)(vtop - vstack + 1));
-}
-
-/* vstack debugging aid */
-#if 0
-void pv (const char *lbl, int a, int b)
-{
- int i;
- for (i = a; i < a + b; ++i) {
- SValue *p = &vtop[-i];
- printf("%s vtop[-%d] : type.t:%04x r:%04x r2:%04x c.i:%d\n",
- lbl, i, p->type.t, p->r, p->r2, (int)p->c.i);
- }
-}
-#endif
-
-/* ------------------------------------------------------------------------- */
-/* initialize vstack and types. This must be done also for tcc -E */
-ST_FUNC void tccgen_init(TCCState *s1)
-{
- vtop = vstack - 1;
- memset(vtop, 0, sizeof *vtop);
-
- /* define some often used types */
- int_type.t = VT_INT;
-
- char_type.t = VT_BYTE;
- if (s1->char_is_unsigned)
- char_type.t |= VT_UNSIGNED;
- char_pointer_type = char_type;
- mk_pointer(&char_pointer_type);
-
- func_old_type.t = VT_FUNC;
- func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0);
- func_old_type.ref->f.func_call = FUNC_CDECL;
- func_old_type.ref->f.func_type = FUNC_OLD;
-#ifdef precedence_parser
- init_prec();
-#endif
- cstr_new(&initstr);
-}
-
-ST_FUNC int tccgen_compile(TCCState *s1)
-{
- cur_text_section = NULL;
- funcname = "";
- func_ind = -1;
- anon_sym = SYM_FIRST_ANOM;
- nocode_wanted = DATA_ONLY_WANTED; /* no code outside of functions */
- local_scope = 0;
- debug_modes = (s1->do_debug ? 1 : 0) | s1->test_coverage << 1;
-
- tcc_debug_start(s1);
- tcc_tcov_start (s1);
-#ifdef TCC_TARGET_ARM
- arm_init(s1);
-#endif
-#ifdef INC_DEBUG
- printf("%s: **** new file\n", file->filename);
-#endif
- parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM | PARSE_FLAG_TOK_STR;
- next();
- decl(VT_CONST);
- gen_inline_functions(s1);
- check_vstack();
- /* end of translation unit info */
- tcc_debug_end(s1);
- tcc_tcov_end(s1);
- return 0;
-}
-
-ST_FUNC void tccgen_finish(TCCState *s1)
-{
- tcc_debug_end(s1); /* just in case of errors: free memory */
- free_inline_functions(s1);
- sym_pop(&global_stack, NULL, 0);
- sym_pop(&local_stack, NULL, 0);
- /* free preprocessor macros */
- free_defines(NULL);
- /* free sym_pools */
- dynarray_reset(&sym_pools, &nb_sym_pools);
- sym_free_first = NULL;
- global_label_stack = local_label_stack = NULL;
- cstr_free(&initstr);
- dynarray_reset(&stk_data, &nb_stk_data);
-}
-
-/* ------------------------------------------------------------------------- */
-ST_FUNC ElfSym *elfsym(Sym *s)
-{
- if (!s || !s->c)
- return NULL;
- return &((ElfSym *)symtab_section->data)[s->c];
-}
-
-/* apply storage attributes to Elf symbol */
-ST_FUNC void update_storage(Sym *sym)
-{
- ElfSym *esym;
- int sym_bind, old_sym_bind;
-
- esym = elfsym(sym);
- if (!esym)
- return;
-
- if (sym->a.visibility)
- esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
- | sym->a.visibility;
-
- if (sym->type.t & (VT_STATIC | VT_INLINE))
- sym_bind = STB_LOCAL;
- else if (sym->a.weak)
- sym_bind = STB_WEAK;
- else
- sym_bind = STB_GLOBAL;
- old_sym_bind = ELFW(ST_BIND)(esym->st_info);
- if (sym_bind != old_sym_bind) {
- esym->st_info = ELFW(ST_INFO)(sym_bind, ELFW(ST_TYPE)(esym->st_info));
- }
-
-#ifdef TCC_TARGET_PE
- if (sym->a.dllimport)
- esym->st_other |= ST_PE_IMPORT;
- if (sym->a.dllexport)
- esym->st_other |= ST_PE_EXPORT;
-#endif
-
-#if 0
- printf("storage %s: bind=%c vis=%d exp=%d imp=%d\n",
- get_tok_str(sym->v, NULL),
- sym_bind == STB_WEAK ? 'w' : sym_bind == STB_LOCAL ? 'l' : 'g',
- sym->a.visibility,
- sym->a.dllexport,
- sym->a.dllimport
- );
-#endif
-}
-
-/* ------------------------------------------------------------------------- */
-/* update sym->c so that it points to an external symbol in section
- 'section' with value 'value' */
-
-ST_FUNC void put_extern_sym2(Sym *sym, int sh_num,
- addr_t value, unsigned long size,
- int can_add_underscore)
-{
- int sym_type, sym_bind, info, other, t;
- ElfSym *esym;
- const char *name;
- char buf1[256];
-
- if (!sym->c) {
- name = get_tok_str(sym->v, NULL);
- t = sym->type.t;
- if ((t & VT_BTYPE) == VT_FUNC) {
- sym_type = STT_FUNC;
- } else if ((t & VT_BTYPE) == VT_VOID) {
- sym_type = STT_NOTYPE;
- if ((t & (VT_BTYPE|VT_ASM_FUNC)) == VT_ASM_FUNC)
- sym_type = STT_FUNC;
- } else {
- sym_type = STT_OBJECT;
- }
- if (t & (VT_STATIC | VT_INLINE))
- sym_bind = STB_LOCAL;
- else
- sym_bind = STB_GLOBAL;
- other = 0;
-
-#ifdef TCC_TARGET_PE
- if (sym_type == STT_FUNC && sym->type.ref) {
- Sym *ref = sym->type.ref;
- if (ref->a.nodecorate) {
- can_add_underscore = 0;
- }
- if (ref->f.func_call == FUNC_STDCALL && can_add_underscore) {
- sprintf(buf1, "_%s@%d", name, ref->f.func_args * PTR_SIZE);
- name = buf1;
- other |= ST_PE_STDCALL;
- can_add_underscore = 0;
- }
- }
-#endif
-
- if (sym->asm_label) {
- name = get_tok_str(sym->asm_label, NULL);
- can_add_underscore = 0;
- }
-
- if (tcc_state->leading_underscore && can_add_underscore) {
- buf1[0] = '_';
- pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
- name = buf1;
- }
-
- info = ELFW(ST_INFO)(sym_bind, sym_type);
- sym->c = put_elf_sym(symtab_section, value, size, info, other, sh_num, name);
-
- if (debug_modes)
- tcc_debug_extern_sym(tcc_state, sym, sh_num, sym_bind, sym_type);
-
- } else {
- esym = elfsym(sym);
- esym->st_value = value;
- esym->st_size = size;
- esym->st_shndx = sh_num;
- }
- update_storage(sym);
-}
-
-ST_FUNC void put_extern_sym(Sym *sym, Section *s, addr_t value, unsigned long size)
-{
- if (nocode_wanted && (NODATA_WANTED || (s && s == cur_text_section)))
- return;
- put_extern_sym2(sym, s ? s->sh_num : SHN_UNDEF, value, size, 1);
-}
-
-/* add a new relocation entry to symbol 'sym' in section 's' */
-ST_FUNC void greloca(Section *s, Sym *sym, unsigned long offset, int type,
- addr_t addend)
-{
- int c = 0;
-
- if (nocode_wanted && s == cur_text_section)
- return;
-
- if (sym) {
- if (0 == sym->c)
- put_extern_sym(sym, NULL, 0, 0);
- c = sym->c;
- }
-
- /* now we can add ELF relocation info */
- put_elf_reloca(symtab_section, s, offset, type, c, addend);
-}
-
-#if PTR_SIZE == 4
-ST_FUNC void greloc(Section *s, Sym *sym, unsigned long offset, int type)
-{
- greloca(s, sym, offset, type, 0);
-}
-#endif
-
-/* ------------------------------------------------------------------------- */
-/* symbol allocator */
-static Sym *__sym_malloc(void)
-{
- Sym *sym_pool, *sym, *last_sym;
- int i;
-
- sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
- dynarray_add(&sym_pools, &nb_sym_pools, sym_pool);
-
- last_sym = sym_free_first;
- sym = sym_pool;
- for(i = 0; i < SYM_POOL_NB; i++) {
- sym->next = last_sym;
- last_sym = sym;
- sym++;
- }
- sym_free_first = last_sym;
- return last_sym;
-}
-
-static inline Sym *sym_malloc(void)
-{
- Sym *sym;
-#ifndef SYM_DEBUG
- sym = sym_free_first;
- if (!sym)
- sym = __sym_malloc();
- sym_free_first = sym->next;
- return sym;
-#else
- sym = tcc_malloc(sizeof(Sym));
- return sym;
-#endif
-}
-
-ST_INLN void sym_free(Sym *sym)
-{
-#ifndef SYM_DEBUG
- sym->next = sym_free_first;
- sym_free_first = sym;
-#else
- tcc_free(sym);
-#endif
-}
-
-/* push, without hashing */
-ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, int c)
-{
- Sym *s;
-
- s = sym_malloc();
- memset(s, 0, sizeof *s);
- s->v = v;
- s->type.t = t;
- s->c = c;
- /* add in stack */
- s->prev = *ps;
- *ps = s;
- return s;
-}
-
-/* find a symbol and return its associated structure. 's' is the top
- of the symbol stack */
-ST_FUNC Sym *sym_find2(Sym *s, int v)
-{
- while (s) {
- if (s->v == v)
- return s;
- else if (s->v == -1)
- return NULL;
- s = s->prev;
- }
- return NULL;
-}
-
-/* structure lookup */
-ST_INLN Sym *struct_find(int v)
-{
- v -= TOK_IDENT;
- if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
- return NULL;
- return table_ident[v]->sym_struct;
-}
-
-/* find an identifier */
-ST_INLN Sym *sym_find(int v)
-{
- v -= TOK_IDENT;
- if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
- return NULL;
- return table_ident[v]->sym_identifier;
-}
-
-static int sym_scope(Sym *s)
-{
- if (IS_ENUM_VAL (s->type.t))
- return s->type.ref->sym_scope;
- else
- return s->sym_scope;
-}
-
-/* push a given symbol on the symbol stack */
-ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
-{
- Sym *s, **ps;
- TokenSym *ts;
-
- if (local_stack)
- ps = &local_stack;
- else
- ps = &global_stack;
- s = sym_push2(ps, v, type->t, c);
- s->type.ref = type->ref;
- s->r = r;
- /* don't record fields or anonymous symbols */
- /* XXX: simplify */
- if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
- /* record symbol in token array */
- ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
- if (v & SYM_STRUCT)
- ps = &ts->sym_struct;
- else
- ps = &ts->sym_identifier;
- s->prev_tok = *ps;
- *ps = s;
- s->sym_scope = local_scope;
- if (s->prev_tok && sym_scope(s->prev_tok) == s->sym_scope)
- tcc_error("redeclaration of '%s'",
- get_tok_str(v & ~SYM_STRUCT, NULL));
- }
- return s;
-}
-
-/* push a global identifier */
-ST_FUNC Sym *global_identifier_push(int v, int t, int c)
-{
- Sym *s, **ps;
- s = sym_push2(&global_stack, v, t, c);
- s->r = VT_CONST | VT_SYM;
- /* don't record anonymous symbol */
- if (v < SYM_FIRST_ANOM) {
- ps = &table_ident[v - TOK_IDENT]->sym_identifier;
- /* modify the top most local identifier, so that sym_identifier will
- point to 's' when popped; happens when called from inline asm */
- while (*ps != NULL && (*ps)->sym_scope)
- ps = &(*ps)->prev_tok;
- s->prev_tok = *ps;
- *ps = s;
- }
- return s;
-}
-
-/* pop symbols until top reaches 'b'. If KEEP is non-zero don't really
- pop them yet from the list, but do remove them from the token array. */
-ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep)
-{
- Sym *s, *ss, **ps;
- TokenSym *ts;
- int v;
-
- s = *ptop;
- while(s != b) {
- ss = s->prev;
- v = s->v;
- /* remove symbol in token array */
- /* XXX: simplify */
- if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
- ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
- if (v & SYM_STRUCT)
- ps = &ts->sym_struct;
- else
- ps = &ts->sym_identifier;
- *ps = s->prev_tok;
- }
- if (!keep)
- sym_free(s);
- s = ss;
- }
- if (!keep)
- *ptop = b;
-}
-
-/* label lookup */
-ST_FUNC Sym *label_find(int v)
-{
- v -= TOK_IDENT;
- if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
- return NULL;
- return table_ident[v]->sym_label;
-}
-
-ST_FUNC Sym *label_push(Sym **ptop, int v, int flags)
-{
- Sym *s, **ps;
- s = sym_push2(ptop, v, VT_STATIC, 0);
- s->r = flags;
- ps = &table_ident[v - TOK_IDENT]->sym_label;
- if (ptop == &global_label_stack) {
- /* modify the top most local identifier, so that
- sym_identifier will point to 's' when popped */
- while (*ps != NULL)
- ps = &(*ps)->prev_tok;
- }
- s->prev_tok = *ps;
- *ps = s;
- return s;
-}
-
-/* pop labels until element last is reached. Look if any labels are
- undefined. Define symbols if '&&label' was used. */
-ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep)
-{
- Sym *s, *s1;
- for(s = *ptop; s != slast; s = s1) {
- s1 = s->prev;
- if (s->r == LABEL_DECLARED) {
- tcc_warning_c(warn_all)("label '%s' declared but not used", get_tok_str(s->v, NULL));
- } else if (s->r == LABEL_FORWARD) {
- tcc_error("label '%s' used but not defined",
- get_tok_str(s->v, NULL));
- } else {
- if (s->c) {
- /* define corresponding symbol. A size of
- 1 is put. */
- put_extern_sym(s, cur_text_section, s->jnext, 1);
- }
- }
- /* remove label */
- if (s->r != LABEL_GONE)
- table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
- if (!keep)
- sym_free(s);
- else
- s->r = LABEL_GONE;
- }
- if (!keep)
- *ptop = slast;
-}
-
-/* ------------------------------------------------------------------------- */
-static void vcheck_cmp(void)
-{
- /* cannot let cpu flags if other instruction are generated. Also
- avoid leaving VT_JMP anywhere except on the top of the stack
- because it would complicate the code generator.
-
- Don't do this when nocode_wanted. vtop might come from
- !nocode_wanted regions (see 88_codeopt.c) and transforming
- it to a register without actually generating code is wrong
- as their value might still be used for real. All values
- we push under nocode_wanted will eventually be popped
- again, so that the VT_CMP/VT_JMP value will be in vtop
- when code is unsuppressed again. */
-
- /* However if it's just automatic suppression via CODE_OFF/ON()
- then it seems that we better let things work undisturbed.
- How can it work at all under nocode_wanted? Well, gv() will
- actually clear it at the gsym() in load()/VT_JMP in the
- generator backends */
-
- if (vtop->r == VT_CMP && 0 == (nocode_wanted & ~CODE_OFF_BIT))
- gv(RC_INT);
-}
-
-static void vsetc(CType *type, int r, CValue *vc)
-{
- if (vtop >= vstack + (VSTACK_SIZE - 1))
- tcc_error("memory full (vstack)");
- vcheck_cmp();
- vtop++;
- vtop->type = *type;
- vtop->r = r;
- vtop->r2 = VT_CONST;
- vtop->c = *vc;
- vtop->sym = NULL;
-}
-
-ST_FUNC void vswap(void)
-{
- SValue tmp;
-
- vcheck_cmp();
- tmp = vtop[0];
- vtop[0] = vtop[-1];
- vtop[-1] = tmp;
-}
-
-/* pop stack value */
-ST_FUNC void vpop(void)
-{
- int v;
- v = vtop->r & VT_VALMASK;
-#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
- /* for x86, we need to pop the FP stack */
- if (v == TREG_ST0) {
- o(0xd8dd); /* fstp %st(0) */
- } else
-#endif
- if (v == VT_CMP) {
- /* need to put correct jump if && or || without test */
- gsym(vtop->jtrue);
- gsym(vtop->jfalse);
- }
- vtop--;
-}
-
-/* push constant of type "type" with useless value */
-static void vpush(CType *type)
-{
- vset(type, VT_CONST, 0);
-}
-
-/* push arbitrary 64bit constant */
-static void vpush64(int ty, unsigned long long v)
-{
- CValue cval;
- CType ctype;
- ctype.t = ty;
- ctype.ref = NULL;
- cval.i = v;
- vsetc(&ctype, VT_CONST, &cval);
-}
-
-/* push integer constant */
-ST_FUNC void vpushi(int v)
-{
- vpush64(VT_INT, v);
-}
-
-/* push a pointer sized constant */
-static void vpushs(addr_t v)
-{
- vpush64(VT_SIZE_T, v);
-}
-
-/* push long long constant */
-static inline void vpushll(long long v)
-{
- vpush64(VT_LLONG, v);
-}
-
-ST_FUNC void vset(CType *type, int r, int v)
-{
- CValue cval;
- cval.i = v;
- vsetc(type, r, &cval);
-}
-
-static void vseti(int r, int v)
-{
- CType type;
- type.t = VT_INT;
- type.ref = NULL;
- vset(&type, r, v);
-}
-
-ST_FUNC void vpushv(SValue *v)
-{
- if (vtop >= vstack + (VSTACK_SIZE - 1))
- tcc_error("memory full (vstack)");
- vtop++;
- *vtop = *v;
-}
-
-static void vdup(void)
-{
- vpushv(vtop);
-}
-
-/* rotate n first stack elements to the bottom
- I1 ... In -> I2 ... In I1 [top is right]
-*/
-ST_FUNC void vrotb(int n)
-{
- int i;
- SValue tmp;
-
- vcheck_cmp();
- tmp = vtop[-n + 1];
- for(i=-n+1;i!=0;i++)
- vtop[i] = vtop[i+1];
- vtop[0] = tmp;
-}
-
-/* rotate the n elements before entry e towards the top
- I1 ... In ... -> In I1 ... I(n-1) ... [top is right]
- */
-ST_FUNC void vrote(SValue *e, int n)
-{
- int i;
- SValue tmp;
-
- vcheck_cmp();
- tmp = *e;
- for(i = 0;i < n - 1; i++)
- e[-i] = e[-i - 1];
- e[-n + 1] = tmp;
-}
-
-/* rotate n first stack elements to the top
- I1 ... In -> In I1 ... I(n-1) [top is right]
- */
-ST_FUNC void vrott(int n)
-{
- vrote(vtop, n);
-}
-
-/* ------------------------------------------------------------------------- */
-/* vtop->r = VT_CMP means CPU-flags have been set from comparison or test. */
-
-/* called from generators to set the result from relational ops */
-ST_FUNC void vset_VT_CMP(int op)
-{
- vtop->r = VT_CMP;
- vtop->cmp_op = op;
- vtop->jfalse = 0;
- vtop->jtrue = 0;
-}
-
-/* called once before asking generators to load VT_CMP to a register */
-static void vset_VT_JMP(void)
-{
- int op = vtop->cmp_op;
-
- if (vtop->jtrue || vtop->jfalse) {
- int origt = vtop->type.t;
- /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */
- int inv = op & (op < 2); /* small optimization */
- vseti(VT_JMP+inv, gvtst(inv, 0));
- vtop->type.t |= origt & (VT_UNSIGNED | VT_DEFSIGN);
- } else {
- /* otherwise convert flags (rsp. 0/1) to register */
- vtop->c.i = op;
- if (op < 2) /* doesn't seem to happen */
- vtop->r = VT_CONST;
- }
-}
-
-/* Set CPU Flags, doesn't yet jump */
-static void gvtst_set(int inv, int t)
-{
- int *p;
-
- if (vtop->r != VT_CMP) {
- vpushi(0);
- gen_op(TOK_NE);
- if (vtop->r != VT_CMP) /* must be VT_CONST then */
- vset_VT_CMP(vtop->c.i != 0);
- }
-
- p = inv ? &vtop->jfalse : &vtop->jtrue;
- *p = gjmp_append(*p, t);
-}
-
-/* Generate value test
- *
- * Generate a test for any value (jump, comparison and integers) */
-static int gvtst(int inv, int t)
-{
- int op, x, u;
-
- gvtst_set(inv, t);
- t = vtop->jtrue, u = vtop->jfalse;
- if (inv)
- x = u, u = t, t = x;
- op = vtop->cmp_op;
-
- /* jump to the wanted target */
- if (op > 1)
- t = gjmp_cond(op ^ inv, t);
- else if (op != inv)
- t = gjmp(t);
- /* resolve complementary jumps to here */
- gsym(u);
-
- vtop--;
- return t;
-}
-
-/* generate a zero or nozero test */
-static void gen_test_zero(int op)
-{
- if (vtop->r == VT_CMP) {
- int j;
- if (op == TOK_EQ) {
- j = vtop->jfalse;
- vtop->jfalse = vtop->jtrue;
- vtop->jtrue = j;
- vtop->cmp_op ^= 1;
- }
- } else {
- vpushi(0);
- gen_op(op);
- }
-}
-
-/* ------------------------------------------------------------------------- */
-/* push a symbol value of TYPE */
-ST_FUNC void vpushsym(CType *type, Sym *sym)
-{
- CValue cval;
- cval.i = 0;
- vsetc(type, VT_CONST | VT_SYM, &cval);
- vtop->sym = sym;
-}
-
-/* Return a static symbol pointing to a section */
-ST_FUNC Sym *get_sym_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
-{
- int v;
- Sym *sym;
-
- v = anon_sym++;
- sym = sym_push(v, type, VT_CONST | VT_SYM, 0);
- sym->type.t |= VT_STATIC;
- put_extern_sym(sym, sec, offset, size);
- return sym;
-}
-
-/* push a reference to a section offset by adding a dummy symbol */
-static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
-{
- vpushsym(type, get_sym_ref(type, sec, offset, size));
-}
-
-/* define a new external reference to a symbol 'v' of type 'u' */
-ST_FUNC Sym *external_global_sym(int v, CType *type)
-{
- Sym *s;
-
- s = sym_find(v);
- if (!s) {
- /* push forward reference */
- s = global_identifier_push(v, type->t | VT_EXTERN, 0);
- s->type.ref = type->ref;
- } else if (IS_ASM_SYM(s)) {
- s->type.t = type->t | (s->type.t & VT_EXTERN);
- s->type.ref = type->ref;
- update_storage(s);
- }
- return s;
-}
-
-/* create an external reference with no specific type similar to asm labels.
- This avoids type conflicts if the symbol is used from C too */
-ST_FUNC Sym *external_helper_sym(int v)
-{
- CType ct = { VT_ASM_FUNC, NULL };
- return external_global_sym(v, &ct);
-}
-
-/* push a reference to an helper function (such as memmove) */
-ST_FUNC void vpush_helper_func(int v)
-{
- vpushsym(&func_old_type, external_helper_sym(v));
-}
-
-/* Merge symbol attributes. */
-static void merge_symattr(struct SymAttr *sa, struct SymAttr *sa1)
-{
- if (sa1->aligned && !sa->aligned)
- sa->aligned = sa1->aligned;
- sa->packed |= sa1->packed;
- sa->weak |= sa1->weak;
- sa->nodebug |= sa1->nodebug;
- if (sa1->visibility != STV_DEFAULT) {
- int vis = sa->visibility;
- if (vis == STV_DEFAULT
- || vis > sa1->visibility)
- vis = sa1->visibility;
- sa->visibility = vis;
- }
- sa->dllexport |= sa1->dllexport;
- sa->nodecorate |= sa1->nodecorate;
- sa->dllimport |= sa1->dllimport;
-}
-
-/* Merge function attributes. */
-static void merge_funcattr(struct FuncAttr *fa, struct FuncAttr *fa1)
-{
- if (fa1->func_call && !fa->func_call)
- fa->func_call = fa1->func_call;
- if (fa1->func_type && !fa->func_type)
- fa->func_type = fa1->func_type;
- if (fa1->func_args && !fa->func_args)
- fa->func_args = fa1->func_args;
- if (fa1->func_noreturn)
- fa->func_noreturn = 1;
- if (fa1->func_ctor)
- fa->func_ctor = 1;
- if (fa1->func_dtor)
- fa->func_dtor = 1;
-}
-
-/* Merge attributes. */
-static void merge_attr(AttributeDef *ad, AttributeDef *ad1)
-{
- merge_symattr(&ad->a, &ad1->a);
- merge_funcattr(&ad->f, &ad1->f);
-
- if (ad1->section)
- ad->section = ad1->section;
- if (ad1->alias_target)
- ad->alias_target = ad1->alias_target;
- if (ad1->asm_label)
- ad->asm_label = ad1->asm_label;
- if (ad1->attr_mode)
- ad->attr_mode = ad1->attr_mode;
-}
-
-/* Merge some type attributes. */
-static void patch_type(Sym *sym, CType *type)
-{
- if (!(type->t & VT_EXTERN) || IS_ENUM_VAL(sym->type.t)) {
- if (!(sym->type.t & VT_EXTERN))
- tcc_error("redefinition of '%s'", get_tok_str(sym->v, NULL));
- sym->type.t &= ~VT_EXTERN;
- }
-
- if (IS_ASM_SYM(sym)) {
- /* stay static if both are static */
- sym->type.t = type->t & (sym->type.t | ~VT_STATIC);
- sym->type.ref = type->ref;
- }
-
- if (!is_compatible_types(&sym->type, type)) {
- tcc_error("incompatible types for redefinition of '%s'",
- get_tok_str(sym->v, NULL));
-
- } else if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
- int static_proto = sym->type.t & VT_STATIC;
- /* warn if static follows non-static function declaration */
- if ((type->t & VT_STATIC) && !static_proto
- /* XXX this test for inline shouldn't be here. Until we
- implement gnu-inline mode again it silences a warning for
- mingw caused by our workarounds. */
- && !((type->t | sym->type.t) & VT_INLINE))
- tcc_warning("static storage ignored for redefinition of '%s'",
- get_tok_str(sym->v, NULL));
-
- /* set 'inline' if both agree or if one has static */
- if ((type->t | sym->type.t) & VT_INLINE) {
- if (!((type->t ^ sym->type.t) & VT_INLINE)
- || ((type->t | sym->type.t) & VT_STATIC))
- static_proto |= VT_INLINE;
- }
-
- if (0 == (type->t & VT_EXTERN)) {
- struct FuncAttr f = sym->type.ref->f;
- /* put complete type, use static from prototype */
- sym->type.t = (type->t & ~(VT_STATIC|VT_INLINE)) | static_proto;
- sym->type.ref = type->ref;
- merge_funcattr(&sym->type.ref->f, &f);
- } else {
- sym->type.t &= ~VT_INLINE | static_proto;
- }
-
- if (sym->type.ref->f.func_type == FUNC_OLD
- && type->ref->f.func_type != FUNC_OLD) {
- sym->type.ref = type->ref;
- }
-
- } else {
- if ((sym->type.t & VT_ARRAY) && type->ref->c >= 0) {
- /* set array size if it was omitted in extern declaration */
- sym->type.ref->c = type->ref->c;
- }
- if ((type->t ^ sym->type.t) & VT_STATIC)
- tcc_warning("storage mismatch for redefinition of '%s'",
- get_tok_str(sym->v, NULL));
- }
-}
-
-/* Merge some storage attributes. */
-static void patch_storage(Sym *sym, AttributeDef *ad, CType *type)
-{
- if (type)
- patch_type(sym, type);
-
-#ifdef TCC_TARGET_PE
- if (sym->a.dllimport != ad->a.dllimport)
- tcc_error("incompatible dll linkage for redefinition of '%s'",
- get_tok_str(sym->v, NULL));
-#endif
- merge_symattr(&sym->a, &ad->a);
- if (ad->asm_label)
- sym->asm_label = ad->asm_label;
- update_storage(sym);
-}
-
-/* copy sym to other stack */
-static Sym *sym_copy(Sym *s0, Sym **ps)
-{
- Sym *s;
- s = sym_malloc(), *s = *s0;
- s->prev = *ps, *ps = s;
- if (s->v < SYM_FIRST_ANOM) {
- ps = &table_ident[s->v - TOK_IDENT]->sym_identifier;
- s->prev_tok = *ps, *ps = s;
- }
- return s;
-}
-
-/* copy s->type.ref to stack 'ps' for VT_FUNC and VT_PTR */
-static void sym_copy_ref(Sym *s, Sym **ps)
-{
- int bt = s->type.t & VT_BTYPE;
- if (bt == VT_FUNC || bt == VT_PTR || (bt == VT_STRUCT && s->sym_scope)) {
- Sym **sp = &s->type.ref;
- for (s = *sp, *sp = NULL; s; s = s->next) {
- Sym *s2 = sym_copy(s, ps);
- sp = &(*sp = s2)->next;
- sym_copy_ref(s2, ps);
- }
- }
-}
-
-/* define a new external reference to a symbol 'v' */
-static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
-{
- Sym *s;
-
- /* look for global symbol */
- s = sym_find(v);
- while (s && s->sym_scope)
- s = s->prev_tok;
-
- if (!s) {
- /* push forward reference */
- s = global_identifier_push(v, type->t, 0);
- s->r |= r;
- s->a = ad->a;
- s->asm_label = ad->asm_label;
- s->type.ref = type->ref;
- /* copy type to the global stack */
- if (local_stack)
- sym_copy_ref(s, &global_stack);
- } else {
- patch_storage(s, ad, type);
- }
- /* push variables on local_stack if any */
- if (local_stack && (s->type.t & VT_BTYPE) != VT_FUNC)
- s = sym_copy(s, &local_stack);
- return s;
-}
-
-/* save registers up to (vtop - n) stack entry */
-ST_FUNC void save_regs(int n)
-{
- SValue *p, *p1;
- for(p = vstack, p1 = vtop - n; p <= p1; p++)
- save_reg(p->r);
-}
-
-/* save r to the memory stack, and mark it as being free */
-ST_FUNC void save_reg(int r)
-{
- save_reg_upstack(r, 0);
-}
-
-/* save r to the memory stack, and mark it as being free,
- if seen up to (vtop - n) stack entry */
-ST_FUNC void save_reg_upstack(int r, int n)
-{
- int l, size, align, bt;
- SValue *p, *p1, sv;
-
- if ((r &= VT_VALMASK) >= VT_CONST)
- return;
- if (nocode_wanted)
- return;
- l = 0;
- for(p = vstack, p1 = vtop - n; p <= p1; p++) {
- if ((p->r & VT_VALMASK) == r || p->r2 == r) {
- /* must save value on stack if not already done */
- if (!l) {
- bt = p->type.t & VT_BTYPE;
- if (bt == VT_VOID)
- continue;
- if ((p->r & VT_LVAL) || bt == VT_FUNC)
- bt = VT_PTR;
- sv.type.t = bt;
- size = type_size(&sv.type, &align);
- l = get_temp_local_var(size,align);
- sv.r = VT_LOCAL | VT_LVAL;
- sv.c.i = l;
- store(p->r & VT_VALMASK, &sv);
-#if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
- /* x86 specific: need to pop fp register ST0 if saved */
- if (r == TREG_ST0) {
- o(0xd8dd); /* fstp %st(0) */
- }
-#endif
- /* special long long case */
- if (p->r2 < VT_CONST && USING_TWO_WORDS(bt)) {
- sv.c.i += PTR_SIZE;
- store(p->r2, &sv);
- }
- }
- /* mark that stack entry as being saved on the stack */
- if (p->r & VT_LVAL) {
- /* also clear the bounded flag because the
- relocation address of the function was stored in
- p->c.i */
- p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
- } else {
- p->r = VT_LVAL | VT_LOCAL;
- }
- p->sym = NULL;
- p->r2 = VT_CONST;
- p->c.i = l;
- }
- }
-}
-
-#ifdef TCC_TARGET_ARM
-/* find a register of class 'rc2' with at most one reference on stack.
- * If none, call get_reg(rc) */
-ST_FUNC int get_reg_ex(int rc, int rc2)
-{
- int r;
- SValue *p;
-
- for(r=0;r<NB_REGS;r++) {
- if (reg_classes[r] & rc2) {
- int n;
- n=0;
- for(p = vstack; p <= vtop; p++) {
- if ((p->r & VT_VALMASK) == r ||
- p->r2 == r)
- n++;
- }
- if (n <= 1)
- return r;
- }
- }
- return get_reg(rc);
-}
-#endif
-
-/* find a free register of class 'rc'. If none, save one register */
-ST_FUNC int get_reg(int rc)
-{
- int r;
- SValue *p;
-
- /* find a free register */
- for(r=0;r<NB_REGS;r++) {
- if (reg_classes[r] & rc) {
- if (nocode_wanted)
- return r;
- for(p=vstack;p<=vtop;p++) {
- if ((p->r & VT_VALMASK) == r ||
- p->r2 == r)
- goto notfound;
- }
- return r;
- }
- notfound: ;
- }
-
- /* no register left : free the first one on the stack (VERY
- IMPORTANT to start from the bottom to ensure that we don't
- spill registers used in gen_opi()) */
- for(p=vstack;p<=vtop;p++) {
- /* look at second register (if long long) */
- r = p->r2;
- if (r < VT_CONST && (reg_classes[r] & rc))
- goto save_found;
- r = p->r & VT_VALMASK;
- if (r < VT_CONST && (reg_classes[r] & rc)) {
- save_found:
- save_reg(r);
- return r;
- }
- }
- /* Should never comes here */
- return -1;
-}
-
-/* find a free temporary local variable (return the offset on stack) match the size and align. If none, add new temporary stack variable*/
-static int get_temp_local_var(int size,int align){
- int i;
- struct temp_local_variable *temp_var;
- int found_var;
- SValue *p;
- int r;
- char free;
- char found;
- found=0;
- for(i=0;i<nb_temp_local_vars;i++){
- temp_var=&arr_temp_local_vars[i];
- if(temp_var->size<size||align!=temp_var->align){
- continue;
- }
- /*check if temp_var is free*/
- free=1;
- for(p=vstack;p<=vtop;p++) {
- r=p->r&VT_VALMASK;
- if(r==VT_LOCAL||r==VT_LLOCAL){
- if(p->c.i==temp_var->location){
- free=0;
- break;
- }
- }
- }
- if(free){
- found_var=temp_var->location;
- found=1;
- break;
- }
- }
- if(!found){
- loc = (loc - size) & -align;
- if(nb_temp_local_vars<MAX_TEMP_LOCAL_VARIABLE_NUMBER){
- temp_var=&arr_temp_local_vars[i];
- temp_var->location=loc;
- temp_var->size=size;
- temp_var->align=align;
- nb_temp_local_vars++;
- }
- found_var=loc;
- }
- return found_var;
-}
-
-static void clear_temp_local_var_list(){
- nb_temp_local_vars=0;
-}
-
-/* move register 's' (of type 't') to 'r', and flush previous value of r to memory
- if needed */
-static void move_reg(int r, int s, int t)
-{
- SValue sv;
-
- if (r != s) {
- save_reg(r);
- sv.type.t = t;
- sv.type.ref = NULL;
- sv.r = s;
- sv.c.i = 0;
- load(r, &sv);
- }
-}
-
-/* get address of vtop (vtop MUST BE an lvalue) */
-ST_FUNC void gaddrof(void)
-{
- vtop->r &= ~VT_LVAL;
- /* tricky: if saved lvalue, then we can go back to lvalue */
- if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
- vtop->r = (vtop->r & ~VT_VALMASK) | VT_LOCAL | VT_LVAL;
-}
-
-#ifdef CONFIG_TCC_BCHECK
-/* generate a bounded pointer addition */
-static void gen_bounded_ptr_add(void)
-{
- int save = (vtop[-1].r & VT_VALMASK) == VT_LOCAL;
- if (save) {
- vpushv(&vtop[-1]);
- vrott(3);
- }
- vpush_helper_func(TOK___bound_ptr_add);
- vrott(3);
- gfunc_call(2);
- vtop -= save;
- vpushi(0);
- /* returned pointer is in REG_IRET */
- vtop->r = REG_IRET | VT_BOUNDED;
- if (nocode_wanted)
- return;
- /* relocation offset of the bounding function call point */
- vtop->c.i = (cur_text_section->reloc->data_offset - sizeof(ElfW_Rel));
-}
-
-/* patch pointer addition in vtop so that pointer dereferencing is
- also tested */
-static void gen_bounded_ptr_deref(void)
-{
- addr_t func;
- int size, align;
- ElfW_Rel *rel;
- Sym *sym;
-
- if (nocode_wanted)
- return;
-
- size = type_size(&vtop->type, &align);
- switch(size) {
- case 1: func = TOK___bound_ptr_indir1; break;
- case 2: func = TOK___bound_ptr_indir2; break;
- case 4: func = TOK___bound_ptr_indir4; break;
- case 8: func = TOK___bound_ptr_indir8; break;
- case 12: func = TOK___bound_ptr_indir12; break;
- case 16: func = TOK___bound_ptr_indir16; break;
- default:
- /* may happen with struct member access */
- return;
- }
- sym = external_helper_sym(func);
- if (!sym->c)
- put_extern_sym(sym, NULL, 0, 0);
- /* patch relocation */
- /* XXX: find a better solution ? */
- rel = (ElfW_Rel *)(cur_text_section->reloc->data + vtop->c.i);
- rel->r_info = ELFW(R_INFO)(sym->c, ELFW(R_TYPE)(rel->r_info));
-}
-
-/* generate lvalue bound code */
-static void gbound(void)
-{
- CType type1;
-
- vtop->r &= ~VT_MUSTBOUND;
- /* if lvalue, then use checking code before dereferencing */
- if (vtop->r & VT_LVAL) {
- /* if not VT_BOUNDED value, then make one */
- if (!(vtop->r & VT_BOUNDED)) {
- /* must save type because we must set it to int to get pointer */
- type1 = vtop->type;
- vtop->type.t = VT_PTR;
- gaddrof();
- vpushi(0);
- gen_bounded_ptr_add();
- vtop->r |= VT_LVAL;
- vtop->type = type1;
- }
- /* then check for dereferencing */
- gen_bounded_ptr_deref();
- }
-}
-
-/* we need to call __bound_ptr_add before we start to load function
- args into registers */
-ST_FUNC void gbound_args(int nb_args)
-{
- int i, v;
- SValue *sv;
-
- for (i = 1; i <= nb_args; ++i)
- if (vtop[1 - i].r & VT_MUSTBOUND) {
- vrotb(i);
- gbound();
- vrott(i);
- }
-
- sv = vtop - nb_args;
- if (sv->r & VT_SYM) {
- v = sv->sym->v;
- if (v == TOK_setjmp
- || v == TOK__setjmp
-#ifndef TCC_TARGET_PE
- || v == TOK_sigsetjmp
- || v == TOK___sigsetjmp
-#endif
- ) {
- vpush_helper_func(TOK___bound_setjmp);
- vpushv(sv + 1);
- gfunc_call(1);
- func_bound_add_epilog = 1;
- }
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
- if (v == TOK_alloca)
- func_bound_add_epilog = 1;
-#endif
-#if TARGETOS_NetBSD
- if (v == TOK_longjmp) /* undo rename to __longjmp14 */
- sv->sym->asm_label = TOK___bound_longjmp;
-#endif
- }
-}
-
-/* Add bounds for local symbols from S to E (via ->prev) */
-static void add_local_bounds(Sym *s, Sym *e)
-{
- for (; s != e; s = s->prev) {
- if (!s->v || (s->r & VT_VALMASK) != VT_LOCAL)
- continue;
- /* Add arrays/structs/unions because we always take address */
- if ((s->type.t & VT_ARRAY)
- || (s->type.t & VT_BTYPE) == VT_STRUCT
- || s->a.addrtaken) {
- /* add local bound info */
- int align, size = type_size(&s->type, &align);
- addr_t *bounds_ptr = section_ptr_add(lbounds_section,
- 2 * sizeof(addr_t));
- bounds_ptr[0] = s->c;
- bounds_ptr[1] = size;
- }
- }
-}
-#endif
-
-/* Wrapper around sym_pop, that potentially also registers local bounds. */
-static void pop_local_syms(Sym *b, int keep)
-{
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check && !keep && (local_scope || !func_var))
- add_local_bounds(local_stack, b);
-#endif
- if (debug_modes)
- tcc_add_debug_info (tcc_state, !local_scope, local_stack, b);
- sym_pop(&local_stack, b, keep);
-}
-
-static void incr_bf_adr(int o)
-{
- vtop->type = char_pointer_type;
- gaddrof();
- vpushs(o);
- gen_op('+');
- vtop->type.t = VT_BYTE | VT_UNSIGNED;
- vtop->r |= VT_LVAL;
-}
-
-/* single-byte load mode for packed or otherwise unaligned bitfields */
-static void load_packed_bf(CType *type, int bit_pos, int bit_size)
-{
- int n, o, bits;
- save_reg_upstack(vtop->r, 1);
- vpush64(type->t & VT_BTYPE, 0); // B X
- bits = 0, o = bit_pos >> 3, bit_pos &= 7;
- do {
- vswap(); // X B
- incr_bf_adr(o);
- vdup(); // X B B
- n = 8 - bit_pos;
- if (n > bit_size)
- n = bit_size;
- if (bit_pos)
- vpushi(bit_pos), gen_op(TOK_SHR), bit_pos = 0; // X B Y
- if (n < 8)
- vpushi((1 << n) - 1), gen_op('&');
- gen_cast(type);
- if (bits)
- vpushi(bits), gen_op(TOK_SHL);
- vrotb(3); // B Y X
- gen_op('|'); // B X
- bits += n, bit_size -= n, o = 1;
- } while (bit_size);
- vswap(), vpop();
- if (!(type->t & VT_UNSIGNED)) {
- n = ((type->t & VT_BTYPE) == VT_LLONG ? 64 : 32) - bits;
- vpushi(n), gen_op(TOK_SHL);
- vpushi(n), gen_op(TOK_SAR);
- }
-}
-
-/* single-byte store mode for packed or otherwise unaligned bitfields */
-static void store_packed_bf(int bit_pos, int bit_size)
-{
- int bits, n, o, m, c;
- c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
- vswap(); // X B
- save_reg_upstack(vtop->r, 1);
- bits = 0, o = bit_pos >> 3, bit_pos &= 7;
- do {
- incr_bf_adr(o); // X B
- vswap(); //B X
- c ? vdup() : gv_dup(); // B V X
- vrott(3); // X B V
- if (bits)
- vpushi(bits), gen_op(TOK_SHR);
- if (bit_pos)
- vpushi(bit_pos), gen_op(TOK_SHL);
- n = 8 - bit_pos;
- if (n > bit_size)
- n = bit_size;
- if (n < 8) {
- m = ((1 << n) - 1) << bit_pos;
- vpushi(m), gen_op('&'); // X B V1
- vpushv(vtop-1); // X B V1 B
- vpushi(m & 0x80 ? ~m & 0x7f : ~m);
- gen_op('&'); // X B V1 B1
- gen_op('|'); // X B V2
- }
- vdup(), vtop[-1] = vtop[-2]; // X B B V2
- vstore(), vpop(); // X B
- bits += n, bit_size -= n, bit_pos = 0, o = 1;
- } while (bit_size);
- vpop(), vpop();
-}
-
-static int adjust_bf(SValue *sv, int bit_pos, int bit_size)
-{
- int t;
- if (0 == sv->type.ref)
- return 0;
- t = sv->type.ref->auxtype;
- if (t != -1 && t != VT_STRUCT) {
- sv->type.t = (sv->type.t & ~(VT_BTYPE | VT_LONG)) | t;
- sv->r |= VT_LVAL;
- }
- return t;
-}
-
-/* store vtop a register belonging to class 'rc'. lvalues are
- converted to values. Cannot be used if cannot be converted to
- register value (such as structures). */
-ST_FUNC int gv(int rc)
-{
- int r, r2, r_ok, r2_ok, rc2, bt;
- int bit_pos, bit_size, size, align;
-
- /* NOTE: get_reg can modify vstack[] */
- if (vtop->type.t & VT_BITFIELD) {
- CType type;
-
- bit_pos = BIT_POS(vtop->type.t);
- bit_size = BIT_SIZE(vtop->type.t);
- /* remove bit field info to avoid loops */
- vtop->type.t &= ~VT_STRUCT_MASK;
-
- type.ref = NULL;
- type.t = vtop->type.t & VT_UNSIGNED;
- if ((vtop->type.t & VT_BTYPE) == VT_BOOL)
- type.t |= VT_UNSIGNED;
-
- r = adjust_bf(vtop, bit_pos, bit_size);
-
- if ((vtop->type.t & VT_BTYPE) == VT_LLONG)
- type.t |= VT_LLONG;
- else
- type.t |= VT_INT;
-
- if (r == VT_STRUCT) {
- load_packed_bf(&type, bit_pos, bit_size);
- } else {
- int bits = (type.t & VT_BTYPE) == VT_LLONG ? 64 : 32;
- /* cast to int to propagate signedness in following ops */
- gen_cast(&type);
- /* generate shifts */
- vpushi(bits - (bit_pos + bit_size));
- gen_op(TOK_SHL);
- vpushi(bits - bit_size);
- /* NOTE: transformed to SHR if unsigned */
- gen_op(TOK_SAR);
- }
- r = gv(rc);
- } else {
- if (is_float(vtop->type.t) &&
- (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
- /* CPUs usually cannot use float constants, so we store them
- generically in data segment */
- init_params p = { rodata_section };
- unsigned long offset;
- size = type_size(&vtop->type, &align);
- if (NODATA_WANTED)
- size = 0, align = 1;
- offset = section_add(p.sec, size, align);
- vpush_ref(&vtop->type, p.sec, offset, size);
- vswap();
- init_putv(&p, &vtop->type, offset);
- vtop->r |= VT_LVAL;
- }
-#ifdef CONFIG_TCC_BCHECK
- if (vtop->r & VT_MUSTBOUND)
- gbound();
-#endif
-
- bt = vtop->type.t & VT_BTYPE;
-
-#ifdef TCC_TARGET_RISCV64
- /* XXX mega hack */
- if (bt == VT_LDOUBLE && rc == RC_FLOAT)
- rc = RC_INT;
-#endif
- rc2 = RC2_TYPE(bt, rc);
-
- /* need to reload if:
- - constant
- - lvalue (need to dereference pointer)
- - already a register, but not in the right class */
- r = vtop->r & VT_VALMASK;
- r_ok = !(vtop->r & VT_LVAL) && (r < VT_CONST) && (reg_classes[r] & rc);
- r2_ok = !rc2 || ((vtop->r2 < VT_CONST) && (reg_classes[vtop->r2] & rc2));
-
- if (!r_ok || !r2_ok) {
- if (!r_ok)
- r = get_reg(rc);
- if (rc2) {
- int load_type = (bt == VT_QFLOAT) ? VT_DOUBLE : VT_PTRDIFF_T;
- int original_type = vtop->type.t;
-
- /* two register type load :
- expand to two words temporarily */
- if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
- /* load constant */
- unsigned long long ll = vtop->c.i;
- vtop->c.i = ll; /* first word */
- load(r, vtop);
- vtop->r = r; /* save register value */
- vpushi(ll >> 32); /* second word */
- } else if (vtop->r & VT_LVAL) {
- /* We do not want to modifier the long long pointer here.
- So we save any other instances down the stack */
- save_reg_upstack(vtop->r, 1);
- /* load from memory */
- vtop->type.t = load_type;
- load(r, vtop);
- vdup();
- vtop[-1].r = r; /* save register value */
- /* increment pointer to get second word */
- vtop->type.t = VT_PTRDIFF_T;
- gaddrof();
- vpushs(PTR_SIZE);
- gen_op('+');
- vtop->r |= VT_LVAL;
- vtop->type.t = load_type;
- } else {
- /* move registers */
- if (!r_ok)
- load(r, vtop);
- if (r2_ok && vtop->r2 < VT_CONST)
- goto done;
- vdup();
- vtop[-1].r = r; /* save register value */
- vtop->r = vtop[-1].r2;
- }
- /* Allocate second register. Here we rely on the fact that
- get_reg() tries first to free r2 of an SValue. */
- r2 = get_reg(rc2);
- load(r2, vtop);
- vpop();
- /* write second register */
- vtop->r2 = r2;
- done:
- vtop->type.t = original_type;
- } else {
- if (vtop->r == VT_CMP)
- vset_VT_JMP();
- /* one register type load */
- load(r, vtop);
- }
- }
- vtop->r = r;
-#ifdef TCC_TARGET_C67
- /* uses register pairs for doubles */
- if (bt == VT_DOUBLE)
- vtop->r2 = r+1;
-#endif
- }
- return r;
-}
-
-/* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
-ST_FUNC void gv2(int rc1, int rc2)
-{
- /* generate more generic register first. But VT_JMP or VT_CMP
- values must be generated first in all cases to avoid possible
- reload errors */
- if (vtop->r != VT_CMP && rc1 <= rc2) {
- vswap();
- gv(rc1);
- vswap();
- gv(rc2);
- /* test if reload is needed for first register */
- if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
- vswap();
- gv(rc1);
- vswap();
- }
- } else {
- gv(rc2);
- vswap();
- gv(rc1);
- vswap();
- /* test if reload is needed for first register */
- if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
- gv(rc2);
- }
- }
-}
-
-#if PTR_SIZE == 4
-/* expand 64bit on stack in two ints */
-ST_FUNC void lexpand(void)
-{
- int u, v;
- u = vtop->type.t & (VT_DEFSIGN | VT_UNSIGNED);
- v = vtop->r & (VT_VALMASK | VT_LVAL);
- if (v == VT_CONST) {
- vdup();
- vtop[0].c.i >>= 32;
- } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
- vdup();
- vtop[0].c.i += 4;
- } else {
- gv(RC_INT);
- vdup();
- vtop[0].r = vtop[-1].r2;
- vtop[0].r2 = vtop[-1].r2 = VT_CONST;
- }
- vtop[0].type.t = vtop[-1].type.t = VT_INT | u;
-}
-#endif
-
-#if PTR_SIZE == 4
-/* build a long long from two ints */
-static void lbuild(int t)
-{
- gv2(RC_INT, RC_INT);
- vtop[-1].r2 = vtop[0].r;
- vtop[-1].type.t = t;
- vpop();
-}
-#endif
-
-/* convert stack entry to register and duplicate its value in another
- register */
-static void gv_dup(void)
-{
- int t, rc, r;
-
- t = vtop->type.t;
-#if PTR_SIZE == 4
- if ((t & VT_BTYPE) == VT_LLONG) {
- if (t & VT_BITFIELD) {
- gv(RC_INT);
- t = vtop->type.t;
- }
- lexpand();
- gv_dup();
- vswap();
- vrotb(3);
- gv_dup();
- vrotb(4);
- /* stack: H L L1 H1 */
- lbuild(t);
- vrotb(3);
- vrotb(3);
- vswap();
- lbuild(t);
- vswap();
- return;
- }
-#endif
- /* duplicate value */
- rc = RC_TYPE(t);
- gv(rc);
- r = get_reg(rc);
- vdup();
- load(r, vtop);
- vtop->r = r;
-}
-
-#if PTR_SIZE == 4
-/* generate CPU independent (unsigned) long long operations */
-static void gen_opl(int op)
-{
- int t, a, b, op1, c, i;
- int func;
- unsigned short reg_iret = REG_IRET;
- unsigned short reg_lret = REG_IRE2;
- SValue tmp;
-
- switch(op) {
- case '/':
- case TOK_PDIV:
- func = TOK___divdi3;
- goto gen_func;
- case TOK_UDIV:
- func = TOK___udivdi3;
- goto gen_func;
- case '%':
- func = TOK___moddi3;
- goto gen_mod_func;
- case TOK_UMOD:
- func = TOK___umoddi3;
- gen_mod_func:
-#ifdef TCC_ARM_EABI
- reg_iret = TREG_R2;
- reg_lret = TREG_R3;
-#endif
- gen_func:
- /* call generic long long function */
- vpush_helper_func(func);
- vrott(3);
- gfunc_call(2);
- vpushi(0);
- vtop->r = reg_iret;
- vtop->r2 = reg_lret;
- break;
- case '^':
- case '&':
- case '|':
- case '*':
- case '+':
- case '-':
- //pv("gen_opl A",0,2);
- t = vtop->type.t;
- vswap();
- lexpand();
- vrotb(3);
- lexpand();
- /* stack: L1 H1 L2 H2 */
- tmp = vtop[0];
- vtop[0] = vtop[-3];
- vtop[-3] = tmp;
- tmp = vtop[-2];
- vtop[-2] = vtop[-3];
- vtop[-3] = tmp;
- vswap();
- /* stack: H1 H2 L1 L2 */
- //pv("gen_opl B",0,4);
- if (op == '*') {
- vpushv(vtop - 1);
- vpushv(vtop - 1);
- gen_op(TOK_UMULL);
- lexpand();
- /* stack: H1 H2 L1 L2 ML MH */
- for(i=0;i<4;i++)
- vrotb(6);
- /* stack: ML MH H1 H2 L1 L2 */
- tmp = vtop[0];
- vtop[0] = vtop[-2];
- vtop[-2] = tmp;
- /* stack: ML MH H1 L2 H2 L1 */
- gen_op('*');
- vrotb(3);
- vrotb(3);
- gen_op('*');
- /* stack: ML MH M1 M2 */
- gen_op('+');
- gen_op('+');
- } else if (op == '+' || op == '-') {
- /* XXX: add non carry method too (for MIPS or alpha) */
- if (op == '+')
- op1 = TOK_ADDC1;
- else
- op1 = TOK_SUBC1;
- gen_op(op1);
- /* stack: H1 H2 (L1 op L2) */
- vrotb(3);
- vrotb(3);
- gen_op(op1 + 1); /* TOK_xxxC2 */
- } else {
- gen_op(op);
- /* stack: H1 H2 (L1 op L2) */
- vrotb(3);
- vrotb(3);
- /* stack: (L1 op L2) H1 H2 */
- gen_op(op);
- /* stack: (L1 op L2) (H1 op H2) */
- }
- /* stack: L H */
- lbuild(t);
- break;
- case TOK_SAR:
- case TOK_SHR:
- case TOK_SHL:
- if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
- t = vtop[-1].type.t;
- vswap();
- lexpand();
- vrotb(3);
- /* stack: L H shift */
- c = (int)vtop->c.i;
- /* constant: simpler */
- /* NOTE: all comments are for SHL. the other cases are
- done by swapping words */
- vpop();
- if (op != TOK_SHL)
- vswap();
- if (c >= 32) {
- /* stack: L H */
- vpop();
- if (c > 32) {
- vpushi(c - 32);
- gen_op(op);
- }
- if (op != TOK_SAR) {
- vpushi(0);
- } else {
- gv_dup();
- vpushi(31);
- gen_op(TOK_SAR);
- }
- vswap();
- } else {
- vswap();
- gv_dup();
- /* stack: H L L */
- vpushi(c);
- gen_op(op);
- vswap();
- vpushi(32 - c);
- if (op == TOK_SHL)
- gen_op(TOK_SHR);
- else
- gen_op(TOK_SHL);
- vrotb(3);
- /* stack: L L H */
- vpushi(c);
- if (op == TOK_SHL)
- gen_op(TOK_SHL);
- else
- gen_op(TOK_SHR);
- gen_op('|');
- }
- if (op != TOK_SHL)
- vswap();
- lbuild(t);
- } else {
- /* XXX: should provide a faster fallback on x86 ? */
- switch(op) {
- case TOK_SAR:
- func = TOK___ashrdi3;
- goto gen_func;
- case TOK_SHR:
- func = TOK___lshrdi3;
- goto gen_func;
- case TOK_SHL:
- func = TOK___ashldi3;
- goto gen_func;
- }
- }
- break;
- default:
- /* compare operations */
- t = vtop->type.t;
- vswap();
- lexpand();
- vrotb(3);
- lexpand();
- /* stack: L1 H1 L2 H2 */
- tmp = vtop[-1];
- vtop[-1] = vtop[-2];
- vtop[-2] = tmp;
- /* stack: L1 L2 H1 H2 */
- save_regs(4);
- /* compare high */
- op1 = op;
- /* when values are equal, we need to compare low words. since
- the jump is inverted, we invert the test too. */
- if (op1 == TOK_LT)
- op1 = TOK_LE;
- else if (op1 == TOK_GT)
- op1 = TOK_GE;
- else if (op1 == TOK_ULT)
- op1 = TOK_ULE;
- else if (op1 == TOK_UGT)
- op1 = TOK_UGE;
- a = 0;
- b = 0;
- gen_op(op1);
- if (op == TOK_NE) {
- b = gvtst(0, 0);
- } else {
- a = gvtst(1, 0);
- if (op != TOK_EQ) {
- /* generate non equal test */
- vpushi(0);
- vset_VT_CMP(TOK_NE);
- b = gvtst(0, 0);
- }
- }
- /* compare low. Always unsigned */
- op1 = op;
- if (op1 == TOK_LT)
- op1 = TOK_ULT;
- else if (op1 == TOK_LE)
- op1 = TOK_ULE;
- else if (op1 == TOK_GT)
- op1 = TOK_UGT;
- else if (op1 == TOK_GE)
- op1 = TOK_UGE;
- gen_op(op1);
-#if 0//def TCC_TARGET_I386
- if (op == TOK_NE) { gsym(b); break; }
- if (op == TOK_EQ) { gsym(a); break; }
-#endif
- gvtst_set(1, a);
- gvtst_set(0, b);
- break;
- }
-}
-#endif
-
-static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b)
-{
- uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b);
- return (a ^ b) >> 63 ? -x : x;
-}
-
-static int gen_opic_lt(uint64_t a, uint64_t b)
-{
- return (a ^ (uint64_t)1 << 63) < (b ^ (uint64_t)1 << 63);
-}
-
-/* handle integer constant optimizations and various machine
- independent opt */
-static void gen_opic(int op)
-{
- SValue *v1 = vtop - 1;
- SValue *v2 = vtop;
- int t1 = v1->type.t & VT_BTYPE;
- int t2 = v2->type.t & VT_BTYPE;
- int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
- int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
- uint64_t l1 = c1 ? v1->c.i : 0;
- uint64_t l2 = c2 ? v2->c.i : 0;
- int shm = (t1 == VT_LLONG) ? 63 : 31;
- int r;
-
- if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR))
- l1 = ((uint32_t)l1 |
- (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000)));
- if (t2 != VT_LLONG && (PTR_SIZE != 8 || t2 != VT_PTR))
- l2 = ((uint32_t)l2 |
- (v2->type.t & VT_UNSIGNED ? 0 : -(l2 & 0x80000000)));
-
- if (c1 && c2) {
- switch(op) {
- case '+': l1 += l2; break;
- case '-': l1 -= l2; break;
- case '&': l1 &= l2; break;
- case '^': l1 ^= l2; break;
- case '|': l1 |= l2; break;
- case '*': l1 *= l2; break;
-
- case TOK_PDIV:
- case '/':
- case '%':
- case TOK_UDIV:
- case TOK_UMOD:
- /* if division by zero, generate explicit division */
- if (l2 == 0) {
- if (CONST_WANTED && !NOEVAL_WANTED)
- tcc_error("division by zero in constant");
- goto general_case;
- }
- switch(op) {
- default: l1 = gen_opic_sdiv(l1, l2); break;
- case '%': l1 = l1 - l2 * gen_opic_sdiv(l1, l2); break;
- case TOK_UDIV: l1 = l1 / l2; break;
- case TOK_UMOD: l1 = l1 % l2; break;
- }
- break;
- case TOK_SHL: l1 <<= (l2 & shm); break;
- case TOK_SHR: l1 >>= (l2 & shm); break;
- case TOK_SAR:
- l1 = (l1 >> 63) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm);
- break;
- /* tests */
- case TOK_ULT: l1 = l1 < l2; break;
- case TOK_UGE: l1 = l1 >= l2; break;
- case TOK_EQ: l1 = l1 == l2; break;
- case TOK_NE: l1 = l1 != l2; break;
- case TOK_ULE: l1 = l1 <= l2; break;
- case TOK_UGT: l1 = l1 > l2; break;
- case TOK_LT: l1 = gen_opic_lt(l1, l2); break;
- case TOK_GE: l1 = !gen_opic_lt(l1, l2); break;
- case TOK_LE: l1 = !gen_opic_lt(l2, l1); break;
- case TOK_GT: l1 = gen_opic_lt(l2, l1); break;
- /* logical */
- case TOK_LAND: l1 = l1 && l2; break;
- case TOK_LOR: l1 = l1 || l2; break;
- default:
- goto general_case;
- }
- if (t1 != VT_LLONG && (PTR_SIZE != 8 || t1 != VT_PTR))
- l1 = ((uint32_t)l1 |
- (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000)));
- v1->c.i = l1;
- v1->r |= v2->r & VT_NONCONST;
- vtop--;
- } else {
- /* if commutative ops, put c2 as constant */
- if (c1 && (op == '+' || op == '&' || op == '^' ||
- op == '|' || op == '*' || op == TOK_EQ || op == TOK_NE)) {
- vswap();
- c2 = c1; //c = c1, c1 = c2, c2 = c;
- l2 = l1; //l = l1, l1 = l2, l2 = l;
- }
- if (c1 && ((l1 == 0 &&
- (op == TOK_SHL || op == TOK_SHR || op == TOK_SAR)) ||
- (l1 == -1 && op == TOK_SAR))) {
- /* treat (0 << x), (0 >> x) and (-1 >> x) as constant */
- vpop();
- } else if (c2 && ((l2 == 0 && (op == '&' || op == '*')) ||
- (op == '|' &&
- (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))) ||
- (l2 == 1 && (op == '%' || op == TOK_UMOD)))) {
- /* treat (x & 0), (x * 0), (x | -1) and (x % 1) as constant */
- if (l2 == 1)
- vtop->c.i = 0;
- vswap();
- vtop--;
- } else if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
- op == TOK_PDIV) &&
- l2 == 1) ||
- ((op == '+' || op == '-' || op == '|' || op == '^' ||
- op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
- l2 == 0) ||
- (op == '&' &&
- (l2 == -1 || (l2 == 0xFFFFFFFF && t2 != VT_LLONG))))) {
- /* filter out NOP operations like x*1, x-0, x&-1... */
- vtop--;
- } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
- /* try to use shifts instead of muls or divs */
- if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
- int n = -1;
- while (l2) {
- l2 >>= 1;
- n++;
- }
- vtop->c.i = n;
- if (op == '*')
- op = TOK_SHL;
- else if (op == TOK_PDIV)
- op = TOK_SAR;
- else
- op = TOK_SHR;
- }
- goto general_case;
- } else if (c2 && (op == '+' || op == '-') &&
- (r = vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM),
- r == (VT_CONST | VT_SYM) || r == VT_LOCAL)) {
- /* symbol + constant case */
- if (op == '-')
- l2 = -l2;
- l2 += vtop[-1].c.i;
- /* The backends can't always deal with addends to symbols
- larger than +-1<<31. Don't construct such. */
- if ((int)l2 != l2)
- goto general_case;
- vtop--;
- vtop->c.i = l2;
- } else {
- general_case:
- /* call low level op generator */
- if (t1 == VT_LLONG || t2 == VT_LLONG ||
- (PTR_SIZE == 8 && (t1 == VT_PTR || t2 == VT_PTR)))
- gen_opl(op);
- else
- gen_opi(op);
- }
- if (vtop->r == VT_CONST)
- vtop->r |= VT_NONCONST; /* is const, but only by optimization */
- }
-}
-
-#if defined TCC_TARGET_X86_64 || defined TCC_TARGET_I386
-# define gen_negf gen_opf
-#elif defined TCC_TARGET_ARM
-void gen_negf(int op)
-{
- /* arm will detect 0-x and replace by vneg */
- vpushi(0), vswap(), gen_op('-');
-}
-#else
-/* XXX: implement in gen_opf() for other backends too */
-void gen_negf(int op)
-{
- /* In IEEE negate(x) isn't subtract(0,x). Without NaNs it's
- subtract(-0, x), but with them it's really a sign flip
- operation. We implement this with bit manipulation and have
- to do some type reinterpretation for this, which TCC can do
- only via memory. */
-
- int align, size, bt;
-
- size = type_size(&vtop->type, &align);
- bt = vtop->type.t & VT_BTYPE;
- save_reg(gv(RC_TYPE(bt)));
- vdup();
- incr_bf_adr(size - 1);
- vdup();
- vpushi(0x80); /* flip sign */
- gen_op('^');
- vstore();
- vpop();
-}
-#endif
-
-/* generate a floating point operation with constant propagation */
-static void gen_opif(int op)
-{
- int c1, c2, cast_int = 0;
- SValue *v1, *v2;
-#if defined _MSC_VER && defined __x86_64__
- /* avoid bad optimization with f1 -= f2 for f1:-0.0, f2:0.0 */
- volatile
-#endif
- long double f1, f2;
-
- v1 = vtop - 1;
- v2 = vtop;
- if (op == TOK_NEG)
- v1 = v2;
-
- /* currently, we cannot do computations with forward symbols */
- c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
- c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
- if (c1 && c2) {
- if (v1->type.t == VT_FLOAT) {
- f1 = v1->c.f;
- f2 = v2->c.f;
- } else if (v1->type.t == VT_DOUBLE) {
- f1 = v1->c.d;
- f2 = v2->c.d;
- } else {
- f1 = v1->c.ld;
- f2 = v2->c.ld;
- }
- /* NOTE: we only do constant propagation if finite number (not
- NaN or infinity) (ANSI spec) */
- if (!(ieee_finite(f1) || !ieee_finite(f2)) && !CONST_WANTED)
- goto general_case;
- switch(op) {
- case '+': f1 += f2; break;
- case '-': f1 -= f2; break;
- case '*': f1 *= f2; break;
- case '/':
- if (f2 == 0.0) {
- union { float f; unsigned u; } x1, x2, y;
- /* If not in initializer we need to potentially generate
- FP exceptions at runtime, otherwise we want to fold. */
- if (!CONST_WANTED)
- goto general_case;
- /* the run-time result of 0.0/0.0 on x87, also of other compilers
- when used to compile the f1 /= f2 below, would be -nan */
- x1.f = f1, x2.f = f2;
- if (f1 == 0.0)
- y.u = 0x7fc00000; /* nan */
- else
- y.u = 0x7f800000; /* infinity */
- y.u |= (x1.u ^ x2.u) & 0x80000000; /* set sign */
- f1 = y.f;
- break;
- }
- f1 /= f2;
- break;
- case TOK_NEG:
- f1 = -f1;
- goto unary_result;
- case TOK_EQ:
- f1 = f1 == f2;
- make_int:
- cast_int = 1;
- break;
- case TOK_NE:
- f1 = f1 != f2;
- goto make_int;
- case TOK_LT:
- f1 = f1 < f2;
- goto make_int;
- case TOK_GE:
- f1 = f1 >= f2;
- goto make_int;
- case TOK_LE:
- f1 = f1 <= f2;
- goto make_int;
- case TOK_GT:
- f1 = f1 > f2;
- goto make_int;
- /* XXX: also handles tests ? */
- default:
- goto general_case;
- }
- vtop--;
- unary_result:
- /* XXX: overflow test ? */
- if (v1->type.t == VT_FLOAT) {
- v1->c.f = f1;
- } else if (v1->type.t == VT_DOUBLE) {
- v1->c.d = f1;
- } else {
- v1->c.ld = f1;
- }
- if (cast_int)
- gen_cast_s(VT_INT);
- } else {
- general_case:
- if (op == TOK_NEG) {
- gen_negf(op);
- } else {
- gen_opf(op);
- }
- }
-}
-
-/* print a type. If 'varstr' is not NULL, then the variable is also
- printed in the type */
-/* XXX: union */
-/* XXX: add array and function pointers */
-static void type_to_str(char *buf, int buf_size,
- CType *type, const char *varstr)
-{
- int bt, v, t;
- Sym *s, *sa;
- char buf1[256];
- const char *tstr;
-
- t = type->t;
- bt = t & VT_BTYPE;
- buf[0] = '\0';
-
- if (t & VT_EXTERN)
- pstrcat(buf, buf_size, "extern ");
- if (t & VT_STATIC)
- pstrcat(buf, buf_size, "static ");
- if (t & VT_TYPEDEF)
- pstrcat(buf, buf_size, "typedef ");
- if (t & VT_INLINE)
- pstrcat(buf, buf_size, "inline ");
- if (bt != VT_PTR) {
- if (t & VT_VOLATILE)
- pstrcat(buf, buf_size, "volatile ");
- if (t & VT_CONSTANT)
- pstrcat(buf, buf_size, "const ");
- }
- if (((t & VT_DEFSIGN) && bt == VT_BYTE)
- || ((t & VT_UNSIGNED)
- && (bt == VT_SHORT || bt == VT_INT || bt == VT_LLONG)
- && !IS_ENUM(t)
- ))
- pstrcat(buf, buf_size, (t & VT_UNSIGNED) ? "unsigned " : "signed ");
-
- buf_size -= strlen(buf);
- buf += strlen(buf);
-
- switch(bt) {
- case VT_VOID:
- tstr = "void";
- goto add_tstr;
- case VT_BOOL:
- tstr = "_Bool";
- goto add_tstr;
- case VT_BYTE:
- tstr = "char";
- goto add_tstr;
- case VT_SHORT:
- tstr = "short";
- goto add_tstr;
- case VT_INT:
- tstr = "int";
- goto maybe_long;
- case VT_LLONG:
- tstr = "long long";
- maybe_long:
- if (t & VT_LONG)
- tstr = "long";
- if (!IS_ENUM(t))
- goto add_tstr;
- tstr = "enum ";
- goto tstruct;
- case VT_FLOAT:
- tstr = "float";
- goto add_tstr;
- case VT_DOUBLE:
- tstr = "double";
- if (!(t & VT_LONG))
- goto add_tstr;
- case VT_LDOUBLE:
- tstr = "long double";
- add_tstr:
- pstrcat(buf, buf_size, tstr);
- break;
- case VT_STRUCT:
- tstr = "struct ";
- if (IS_UNION(t))
- tstr = "union ";
- tstruct:
- pstrcat(buf, buf_size, tstr);
- v = type->ref->v & ~SYM_STRUCT;
- if (v >= SYM_FIRST_ANOM)
- pstrcat(buf, buf_size, "<anonymous>");
- else
- pstrcat(buf, buf_size, get_tok_str(v, NULL));
- break;
- case VT_FUNC:
- s = type->ref;
- buf1[0]=0;
- if (varstr && '*' == *varstr) {
- pstrcat(buf1, sizeof(buf1), "(");
- pstrcat(buf1, sizeof(buf1), varstr);
- pstrcat(buf1, sizeof(buf1), ")");
- }
- pstrcat(buf1, buf_size, "(");
- sa = s->next;
- while (sa != NULL) {
- char buf2[256];
- type_to_str(buf2, sizeof(buf2), &sa->type, NULL);
- pstrcat(buf1, sizeof(buf1), buf2);
- sa = sa->next;
- if (sa)
- pstrcat(buf1, sizeof(buf1), ", ");
- }
- if (s->f.func_type == FUNC_ELLIPSIS)
- pstrcat(buf1, sizeof(buf1), ", ...");
- pstrcat(buf1, sizeof(buf1), ")");
- type_to_str(buf, buf_size, &s->type, buf1);
- goto no_var;
- case VT_PTR:
- s = type->ref;
- if (t & (VT_ARRAY|VT_VLA)) {
- if (varstr && '*' == *varstr)
- snprintf(buf1, sizeof(buf1), "(%s)[%d]", varstr, s->c);
- else
- snprintf(buf1, sizeof(buf1), "%s[%d]", varstr ? varstr : "", s->c);
- type_to_str(buf, buf_size, &s->type, buf1);
- goto no_var;
- }
- pstrcpy(buf1, sizeof(buf1), "*");
- if (t & VT_CONSTANT)
- pstrcat(buf1, buf_size, "const ");
- if (t & VT_VOLATILE)
- pstrcat(buf1, buf_size, "volatile ");
- if (varstr)
- pstrcat(buf1, sizeof(buf1), varstr);
- type_to_str(buf, buf_size, &s->type, buf1);
- goto no_var;
- }
- if (varstr) {
- pstrcat(buf, buf_size, " ");
- pstrcat(buf, buf_size, varstr);
- }
- no_var: ;
-}
-
-static void type_incompatibility_error(CType* st, CType* dt, const char* fmt)
-{
- char buf1[256], buf2[256];
- type_to_str(buf1, sizeof(buf1), st, NULL);
- type_to_str(buf2, sizeof(buf2), dt, NULL);
- tcc_error(fmt, buf1, buf2);
-}
-
-static void type_incompatibility_warning(CType* st, CType* dt, const char* fmt)
-{
- char buf1[256], buf2[256];
- type_to_str(buf1, sizeof(buf1), st, NULL);
- type_to_str(buf2, sizeof(buf2), dt, NULL);
- tcc_warning(fmt, buf1, buf2);
-}
-
-static int pointed_size(CType *type)
-{
- int align;
- return type_size(pointed_type(type), &align);
-}
-
-static inline int is_null_pointer(SValue *p)
-{
- if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM | VT_NONCONST)) != VT_CONST)
- return 0;
- return ((p->type.t & VT_BTYPE) == VT_INT && (uint32_t)p->c.i == 0) ||
- ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.i == 0) ||
- ((p->type.t & VT_BTYPE) == VT_PTR &&
- (PTR_SIZE == 4 ? (uint32_t)p->c.i == 0 : p->c.i == 0) &&
- ((pointed_type(&p->type)->t & VT_BTYPE) == VT_VOID) &&
- 0 == (pointed_type(&p->type)->t & (VT_CONSTANT | VT_VOLATILE))
- );
-}
-
-/* compare function types. OLD functions match any new functions */
-static int is_compatible_func(CType *type1, CType *type2)
-{
- Sym *s1, *s2;
-
- s1 = type1->ref;
- s2 = type2->ref;
- if (s1->f.func_call != s2->f.func_call)
- return 0;
- if (s1->f.func_type != s2->f.func_type
- && s1->f.func_type != FUNC_OLD
- && s2->f.func_type != FUNC_OLD)
- return 0;
- for (;;) {
- if (!is_compatible_unqualified_types(&s1->type, &s2->type))
- return 0;
- if (s1->f.func_type == FUNC_OLD || s2->f.func_type == FUNC_OLD )
- return 1;
- s1 = s1->next;
- s2 = s2->next;
- if (!s1)
- return !s2;
- if (!s2)
- return 0;
- }
-}
-
-/* return true if type1 and type2 are the same. If unqualified is
- true, qualifiers on the types are ignored.
- */
-static int compare_types(CType *type1, CType *type2, int unqualified)
-{
- int bt1, t1, t2;
-
- t1 = type1->t & VT_TYPE;
- t2 = type2->t & VT_TYPE;
- if (unqualified) {
- /* strip qualifiers before comparing */
- t1 &= ~(VT_CONSTANT | VT_VOLATILE);
- t2 &= ~(VT_CONSTANT | VT_VOLATILE);
- }
-
- /* Default Vs explicit signedness only matters for char */
- if ((t1 & VT_BTYPE) != VT_BYTE) {
- t1 &= ~VT_DEFSIGN;
- t2 &= ~VT_DEFSIGN;
- }
- /* XXX: bitfields ? */
- if (t1 != t2)
- return 0;
-
- if ((t1 & VT_ARRAY)
- && !(type1->ref->c < 0
- || type2->ref->c < 0
- || type1->ref->c == type2->ref->c))
- return 0;
-
- /* test more complicated cases */
- bt1 = t1 & VT_BTYPE;
- if (bt1 == VT_PTR) {
- type1 = pointed_type(type1);
- type2 = pointed_type(type2);
- return is_compatible_types(type1, type2);
- } else if (bt1 == VT_STRUCT) {
- return (type1->ref == type2->ref);
- } else if (bt1 == VT_FUNC) {
- return is_compatible_func(type1, type2);
- } else if (IS_ENUM(type1->t) && IS_ENUM(type2->t)) {
- /* If both are enums then they must be the same, if only one is then
- t1 and t2 must be equal, which was checked above already. */
- return type1->ref == type2->ref;
- } else {
- return 1;
- }
-}
-
-/* Check if OP1 and OP2 can be "combined" with operation OP, the combined
- type is stored in DEST if non-null (except for pointer plus/minus) . */
-static int combine_types(CType *dest, SValue *op1, SValue *op2, int op)
-{
- CType *type1 = &op1->type, *type2 = &op2->type, type;
- int t1 = type1->t, t2 = type2->t, bt1 = t1 & VT_BTYPE, bt2 = t2 & VT_BTYPE;
- int ret = 1;
-
- type.t = VT_VOID;
- type.ref = NULL;
-
- if (bt1 == VT_VOID || bt2 == VT_VOID) {
- ret = op == '?' ? 1 : 0;
- /* NOTE: as an extension, we accept void on only one side */
- type.t = VT_VOID;
- } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
- if (op == '+') ; /* Handled in caller */
- /* http://port70.net/~nsz/c/c99/n1256.html#6.5.15p6 */
- /* If one is a null ptr constant the result type is the other. */
- else if (is_null_pointer (op2)) type = *type1;
- else if (is_null_pointer (op1)) type = *type2;
- else if (bt1 != bt2) {
- /* accept comparison or cond-expr between pointer and integer
- with a warning */
- if ((op == '?' || TOK_ISCOND(op))
- && (is_integer_btype(bt1) || is_integer_btype(bt2)))
- tcc_warning("pointer/integer mismatch in %s",
- op == '?' ? "conditional expression" : "comparison");
- else if (op != '-' || !is_integer_btype(bt2))
- ret = 0;
- type = *(bt1 == VT_PTR ? type1 : type2);
- } else {
- CType *pt1 = pointed_type(type1);
- CType *pt2 = pointed_type(type2);
- int pbt1 = pt1->t & VT_BTYPE;
- int pbt2 = pt2->t & VT_BTYPE;
- int newquals, copied = 0;
- if (pbt1 != VT_VOID && pbt2 != VT_VOID
- && !compare_types(pt1, pt2, 1/*unqualif*/)) {
- if (op != '?' && !TOK_ISCOND(op))
- ret = 0;
- else
- type_incompatibility_warning(type1, type2,
- op == '?'
- ? "pointer type mismatch in conditional expression ('%s' and '%s')"
- : "pointer type mismatch in comparison('%s' and '%s')");
- }
- if (op == '?') {
- /* pointers to void get preferred, otherwise the
- pointed to types minus qualifs should be compatible */
- type = *((pbt1 == VT_VOID) ? type1 : type2);
- /* combine qualifs */
- newquals = ((pt1->t | pt2->t) & (VT_CONSTANT | VT_VOLATILE));
- if ((~pointed_type(&type)->t & (VT_CONSTANT | VT_VOLATILE))
- & newquals)
- {
- /* copy the pointer target symbol */
- type.ref = sym_push(SYM_FIELD, &type.ref->type,
- 0, type.ref->c);
- copied = 1;
- pointed_type(&type)->t |= newquals;
- }
- /* pointers to incomplete arrays get converted to
- pointers to completed ones if possible */
- if (pt1->t & VT_ARRAY
- && pt2->t & VT_ARRAY
- && pointed_type(&type)->ref->c < 0
- && (pt1->ref->c > 0 || pt2->ref->c > 0))
- {
- if (!copied)
- type.ref = sym_push(SYM_FIELD, &type.ref->type,
- 0, type.ref->c);
- pointed_type(&type)->ref =
- sym_push(SYM_FIELD, &pointed_type(&type)->ref->type,
- 0, pointed_type(&type)->ref->c);
- pointed_type(&type)->ref->c =
- 0 < pt1->ref->c ? pt1->ref->c : pt2->ref->c;
- }
- }
- }
- if (TOK_ISCOND(op))
- type.t = VT_SIZE_T;
- } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
- if (op != '?' || !compare_types(type1, type2, 1))
- ret = 0;
- type = *type1;
- } else if (is_float(bt1) || is_float(bt2)) {
- if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
- type.t = VT_LDOUBLE;
- } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
- type.t = VT_DOUBLE;
- } else {
- type.t = VT_FLOAT;
- }
- } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
- /* cast to biggest op */
- type.t = VT_LLONG | VT_LONG;
- if (bt1 == VT_LLONG)
- type.t &= t1;
- if (bt2 == VT_LLONG)
- type.t &= t2;
- /* convert to unsigned if it does not fit in a long long */
- if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED) ||
- (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_LLONG | VT_UNSIGNED))
- type.t |= VT_UNSIGNED;
- } else {
- /* integer operations */
- type.t = VT_INT | (VT_LONG & (t1 | t2));
- /* convert to unsigned if it does not fit in an integer */
- if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED) ||
- (t2 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (VT_INT | VT_UNSIGNED))
- type.t |= VT_UNSIGNED;
- }
- if (dest)
- *dest = type;
- return ret;
-}
-
-/* generic gen_op: handles types problems */
-ST_FUNC void gen_op(int op)
-{
- int t1, t2, bt1, bt2, t;
- CType type1, combtype;
-
-redo:
- t1 = vtop[-1].type.t;
- t2 = vtop[0].type.t;
- bt1 = t1 & VT_BTYPE;
- bt2 = t2 & VT_BTYPE;
-
- if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
- if (bt2 == VT_FUNC) {
- mk_pointer(&vtop->type);
- gaddrof();
- }
- if (bt1 == VT_FUNC) {
- vswap();
- mk_pointer(&vtop->type);
- gaddrof();
- vswap();
- }
- goto redo;
- } else if (!combine_types(&combtype, vtop - 1, vtop, op)) {
- tcc_error("invalid operand types for binary operation");
- } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
- /* at least one operand is a pointer */
- /* relational op: must be both pointers */
- int align;
- if (TOK_ISCOND(op))
- goto std_op;
- /* if both pointers, then it must be the '-' op */
- if (bt1 == VT_PTR && bt2 == VT_PTR) {
- if (op != '-')
- tcc_error("cannot use pointers here");
- vpush_type_size(pointed_type(&vtop[-1].type), &align);
- vrott(3);
- gen_opic(op);
- vtop->type.t = VT_PTRDIFF_T;
- vswap();
- gen_op(TOK_PDIV);
- } else {
- /* exactly one pointer : must be '+' or '-'. */
- if (op != '-' && op != '+')
- tcc_error("cannot use pointers here");
- /* Put pointer as first operand */
- if (bt2 == VT_PTR) {
- vswap();
- t = t1, t1 = t2, t2 = t;
- }
-#if PTR_SIZE == 4
- if ((vtop[0].type.t & VT_BTYPE) == VT_LLONG)
- /* XXX: truncate here because gen_opl can't handle ptr + long long */
- gen_cast_s(VT_INT);
-#endif
- type1 = vtop[-1].type;
- vpush_type_size(pointed_type(&vtop[-1].type), &align);
- gen_op('*');
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check && !CONST_WANTED) {
- /* if bounded pointers, we generate a special code to
- test bounds */
- if (op == '-') {
- vpushi(0);
- vswap();
- gen_op('-');
- }
- gen_bounded_ptr_add();
- } else
-#endif
- {
- gen_opic(op);
- }
- type1.t &= ~(VT_ARRAY|VT_VLA);
- /* put again type if gen_opic() swaped operands */
- vtop->type = type1;
- }
- } else {
- /* floats can only be used for a few operations */
- if (is_float(combtype.t)
- && op != '+' && op != '-' && op != '*' && op != '/'
- && !TOK_ISCOND(op))
- tcc_error("invalid operands for binary operation");
- else if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL) {
- t = bt1 == VT_LLONG ? VT_LLONG : VT_INT;
- if ((t1 & (VT_BTYPE | VT_UNSIGNED | VT_BITFIELD)) == (t | VT_UNSIGNED))
- t |= VT_UNSIGNED;
- t |= (VT_LONG & t1);
- combtype.t = t;
- }
- std_op:
- t = t2 = combtype.t;
- /* XXX: currently, some unsigned operations are explicit, so
- we modify them here */
- if (t & VT_UNSIGNED) {
- if (op == TOK_SAR)
- op = TOK_SHR;
- else if (op == '/')
- op = TOK_UDIV;
- else if (op == '%')
- op = TOK_UMOD;
- else if (op == TOK_LT)
- op = TOK_ULT;
- else if (op == TOK_GT)
- op = TOK_UGT;
- else if (op == TOK_LE)
- op = TOK_ULE;
- else if (op == TOK_GE)
- op = TOK_UGE;
- }
- vswap();
- gen_cast_s(t);
- vswap();
- /* special case for shifts and long long: we keep the shift as
- an integer */
- if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
- t2 = VT_INT;
- gen_cast_s(t2);
- if (is_float(t))
- gen_opif(op);
- else
- gen_opic(op);
- if (TOK_ISCOND(op)) {
- /* relational op: the result is an int */
- vtop->type.t = VT_INT;
- } else {
- vtop->type.t = t;
- }
- }
- // Make sure that we have converted to an rvalue:
- if (vtop->r & VT_LVAL)
- gv(is_float(vtop->type.t & VT_BTYPE) ? RC_FLOAT : RC_INT);
-}
-
-#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64 || defined TCC_TARGET_ARM
-#define gen_cvt_itof1 gen_cvt_itof
-#else
-/* generic itof for unsigned long long case */
-static void gen_cvt_itof1(int t)
-{
- if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
- (VT_LLONG | VT_UNSIGNED)) {
-
- if (t == VT_FLOAT)
- vpush_helper_func(TOK___floatundisf);
-#if LDOUBLE_SIZE != 8
- else if (t == VT_LDOUBLE)
- vpush_helper_func(TOK___floatundixf);
-#endif
- else
- vpush_helper_func(TOK___floatundidf);
- vrott(2);
- gfunc_call(1);
- vpushi(0);
- PUT_R_RET(vtop, t);
- } else {
- gen_cvt_itof(t);
- }
-}
-#endif
-
-#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
-#define gen_cvt_ftoi1 gen_cvt_ftoi
-#else
-/* generic ftoi for unsigned long long case */
-static void gen_cvt_ftoi1(int t)
-{
- int st;
- if (t == (VT_LLONG | VT_UNSIGNED)) {
- /* not handled natively */
- st = vtop->type.t & VT_BTYPE;
- if (st == VT_FLOAT)
- vpush_helper_func(TOK___fixunssfdi);
-#if LDOUBLE_SIZE != 8
- else if (st == VT_LDOUBLE)
- vpush_helper_func(TOK___fixunsxfdi);
-#endif
- else
- vpush_helper_func(TOK___fixunsdfdi);
- vrott(2);
- gfunc_call(1);
- vpushi(0);
- PUT_R_RET(vtop, t);
- } else {
- gen_cvt_ftoi(t);
- }
-}
-#endif
-
-/* special delayed cast for char/short */
-static void force_charshort_cast(void)
-{
- int sbt = BFGET(vtop->r, VT_MUSTCAST) == 2 ? VT_LLONG : VT_INT;
- int dbt = vtop->type.t;
- vtop->r &= ~VT_MUSTCAST;
- vtop->type.t = sbt;
- gen_cast_s(dbt == VT_BOOL ? VT_BYTE|VT_UNSIGNED : dbt);
- vtop->type.t = dbt;
-}
-
-static void gen_cast_s(int t)
-{
- CType type;
- type.t = t;
- type.ref = NULL;
- gen_cast(&type);
-}
-
-/* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
-static void gen_cast(CType *type)
-{
- int sbt, dbt, sf, df, c;
- int dbt_bt, sbt_bt, ds, ss, bits, trunc;
-
- /* special delayed cast for char/short */
- if (vtop->r & VT_MUSTCAST)
- force_charshort_cast();
-
- /* bitfields first get cast to ints */
- if (vtop->type.t & VT_BITFIELD)
- gv(RC_INT);
-
- dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
- sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
- if (sbt == VT_FUNC)
- sbt = VT_PTR;
-
-again:
- if (sbt != dbt) {
- sf = is_float(sbt);
- df = is_float(dbt);
- dbt_bt = dbt & VT_BTYPE;
- sbt_bt = sbt & VT_BTYPE;
- if (dbt_bt == VT_VOID)
- goto done;
- if (sbt_bt == VT_VOID) {
-error:
- cast_error(&vtop->type, type);
- }
-
- c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
-#if !defined TCC_IS_NATIVE && !defined TCC_IS_NATIVE_387
- /* don't try to convert to ldouble when cross-compiling
- (except when it's '0' which is needed for arm:gen_negf()) */
- if (dbt_bt == VT_LDOUBLE && !nocode_wanted && (sf || vtop->c.i != 0))
- c = 0;
-#endif
- if (c) {
- /* constant case: we can do it now */
- /* XXX: in ISOC, cannot do it if error in convert */
- if (sbt == VT_FLOAT)
- vtop->c.ld = vtop->c.f;
- else if (sbt == VT_DOUBLE)
- vtop->c.ld = vtop->c.d;
-
- if (df) {
- if (sbt_bt == VT_LLONG) {
- if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 63))
- vtop->c.ld = vtop->c.i;
- else
- vtop->c.ld = -(long double)-vtop->c.i;
- } else if(!sf) {
- if ((sbt & VT_UNSIGNED) || !(vtop->c.i >> 31))
- vtop->c.ld = (uint32_t)vtop->c.i;
- else
- vtop->c.ld = -(long double)-(uint32_t)vtop->c.i;
- }
-
- if (dbt == VT_FLOAT)
- vtop->c.f = (float)vtop->c.ld;
- else if (dbt == VT_DOUBLE)
- vtop->c.d = (double)vtop->c.ld;
- } else if (sf && dbt == VT_BOOL) {
- vtop->c.i = (vtop->c.ld != 0);
- } else {
- if(sf)
- vtop->c.i = vtop->c.ld;
- else if (sbt_bt == VT_LLONG || (PTR_SIZE == 8 && sbt == VT_PTR))
- ;
- else if (sbt & VT_UNSIGNED)
- vtop->c.i = (uint32_t)vtop->c.i;
- else
- vtop->c.i = ((uint32_t)vtop->c.i | -(vtop->c.i & 0x80000000));
-
- if (dbt_bt == VT_LLONG || (PTR_SIZE == 8 && dbt == VT_PTR))
- ;
- else if (dbt == VT_BOOL)
- vtop->c.i = (vtop->c.i != 0);
- else {
- uint32_t m = dbt_bt == VT_BYTE ? 0xff :
- dbt_bt == VT_SHORT ? 0xffff :
- 0xffffffff;
- vtop->c.i &= m;
- if (!(dbt & VT_UNSIGNED))
- vtop->c.i |= -(vtop->c.i & ((m >> 1) + 1));
- }
- }
- goto done;
-
- } else if (dbt == VT_BOOL
- && (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM))
- == (VT_CONST | VT_SYM)) {
- /* addresses are considered non-zero (see tcctest.c:sinit23) */
- vtop->r = VT_CONST;
- vtop->c.i = 1;
- goto done;
- }
-
- /* cannot generate code for global or static initializers */
- if (nocode_wanted & DATA_ONLY_WANTED)
- goto done;
-
- /* non constant case: generate code */
- if (dbt == VT_BOOL) {
- gen_test_zero(TOK_NE);
- goto done;
- }
-
- if (sf || df) {
- if (sf && df) {
- /* convert from fp to fp */
- gen_cvt_ftof(dbt);
- } else if (df) {
- /* convert int to fp */
- gen_cvt_itof1(dbt);
- } else {
- /* convert fp to int */
- sbt = dbt;
- if (dbt_bt != VT_LLONG && dbt_bt != VT_INT)
- sbt = VT_INT;
- gen_cvt_ftoi1(sbt);
- goto again; /* may need char/short cast */
- }
- goto done;
- }
-
- ds = btype_size(dbt_bt);
- ss = btype_size(sbt_bt);
- if (ds == 0 || ss == 0)
- goto error;
-
- if (IS_ENUM(type->t) && type->ref->c < 0)
- tcc_error("cast to incomplete type");
-
- /* same size and no sign conversion needed */
- if (ds == ss && ds >= 4)
- goto done;
- if (dbt_bt == VT_PTR || sbt_bt == VT_PTR) {
- tcc_warning("cast between pointer and integer of different size");
- if (sbt_bt == VT_PTR) {
- /* put integer type to allow logical operations below */
- vtop->type.t = (PTR_SIZE == 8 ? VT_LLONG : VT_INT);
- }
- }
-
- /* processor allows { int a = 0, b = *(char*)&a; }
- That means that if we cast to less width, we can just
- change the type and read it still later. */
- #define ALLOW_SUBTYPE_ACCESS 1
-
- if (ALLOW_SUBTYPE_ACCESS && (vtop->r & VT_LVAL)) {
- /* value still in memory */
- if (ds <= ss)
- goto done;
- /* ss <= 4 here */
- if (ds <= 4 && !(dbt == (VT_SHORT | VT_UNSIGNED) && sbt == VT_BYTE)) {
- gv(RC_INT);
- goto done; /* no 64bit envolved */
- }
- }
- gv(RC_INT);
-
- trunc = 0;
-#if PTR_SIZE == 4
- if (ds == 8) {
- /* generate high word */
- if (sbt & VT_UNSIGNED) {
- vpushi(0);
- gv(RC_INT);
- } else {
- gv_dup();
- vpushi(31);
- gen_op(TOK_SAR);
- }
- lbuild(dbt);
- } else if (ss == 8) {
- /* from long long: just take low order word */
- lexpand();
- vpop();
- }
- ss = 4;
-
-#elif PTR_SIZE == 8
- if (ds == 8) {
- /* need to convert from 32bit to 64bit */
- if (sbt & VT_UNSIGNED) {
-#if defined(TCC_TARGET_RISCV64)
- /* RISC-V keeps 32bit vals in registers sign-extended.
- So here we need a zero-extension. */
- trunc = 32;
-#else
- goto done;
-#endif
- } else {
- gen_cvt_sxtw();
- goto done;
- }
- ss = ds, ds = 4, dbt = sbt;
- } else if (ss == 8) {
- /* RISC-V keeps 32bit vals in registers sign-extended.
- So here we need a sign-extension for signed types and
- zero-extension. for unsigned types. */
-#if !defined(TCC_TARGET_RISCV64)
- trunc = 32; /* zero upper 32 bits for non RISC-V targets */
-#endif
- } else {
- ss = 4;
- }
-#endif
-
- if (ds >= ss)
- goto done;
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64 || defined TCC_TARGET_ARM64
- if (ss == 4) {
- gen_cvt_csti(dbt);
- goto done;
- }
-#endif
- bits = (ss - ds) * 8;
- /* for unsigned, gen_op will convert SAR to SHR */
- vtop->type.t = (ss == 8 ? VT_LLONG : VT_INT) | (dbt & VT_UNSIGNED);
- vpushi(bits);
- gen_op(TOK_SHL);
- vpushi(bits - trunc);
- gen_op(TOK_SAR);
- vpushi(trunc);
- gen_op(TOK_SHR);
- }
-done:
- vtop->type = *type;
- vtop->type.t &= ~ ( VT_CONSTANT | VT_VOLATILE | VT_ARRAY );
-}
-
-/* return type size as known at compile time. Put alignment at 'a' */
-ST_FUNC int type_size(CType *type, int *a)
-{
- Sym *s;
- int bt;
-
- bt = type->t & VT_BTYPE;
- if (bt == VT_STRUCT) {
- /* struct/union */
- s = type->ref;
- *a = s->r;
- return s->c;
- } else if (bt == VT_PTR) {
- if (type->t & VT_ARRAY) {
- int ts;
-
- s = type->ref;
- ts = type_size(&s->type, a);
-
- if (ts < 0 && s->c < 0)
- ts = -ts;
-
- return ts * s->c;
- } else {
- *a = PTR_SIZE;
- return PTR_SIZE;
- }
- } else if (IS_ENUM(type->t) && type->ref->c < 0) {
- *a = 0;
- return -1; /* incomplete enum */
- } else if (bt == VT_LDOUBLE) {
- *a = LDOUBLE_ALIGN;
- return LDOUBLE_SIZE;
- } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
-#ifdef TCC_TARGET_I386
-#ifdef TCC_TARGET_PE
- *a = 8;
-#else
- *a = 4;
-#endif
-#elif defined(TCC_TARGET_ARM)
-#ifdef TCC_ARM_EABI
- *a = 8;
-#else
- *a = 4;
-#endif
-#else
- *a = 8;
-#endif
- return 8;
- } else if (bt == VT_INT || bt == VT_FLOAT) {
- *a = 4;
- return 4;
- } else if (bt == VT_SHORT) {
- *a = 2;
- return 2;
- } else if (bt == VT_QLONG || bt == VT_QFLOAT) {
- *a = 8;
- return 16;
- } else {
- /* char, void, function, _Bool */
- *a = 1;
- return 1;
- }
-}
-
-/* push type size as known at runtime time on top of value stack. Put
- alignment at 'a' */
-static void vpush_type_size(CType *type, int *a)
-{
- if (type->t & VT_VLA) {
- type_size(&type->ref->type, a);
- vset(&int_type, VT_LOCAL|VT_LVAL, type->ref->c);
- } else {
- int size = type_size(type, a);
- if (size < 0)
- tcc_error("unknown type size");
-#if PTR_SIZE == 8
- vpushll(size);
-#else
- vpushi(size);
-#endif
- }
-}
-
-/* return the pointed type of t */
-static inline CType *pointed_type(CType *type)
-{
- return &type->ref->type;
-}
-
-/* modify type so that its it is a pointer to type. */
-ST_FUNC void mk_pointer(CType *type)
-{
- Sym *s;
- s = sym_push(SYM_FIELD, type, 0, -1);
- type->t = VT_PTR | (type->t & VT_STORAGE);
- type->ref = s;
-}
-
-/* return true if type1 and type2 are exactly the same (including
- qualifiers).
-*/
-static int is_compatible_types(CType *type1, CType *type2)
-{
- return compare_types(type1,type2,0);
-}
-
-/* return true if type1 and type2 are the same (ignoring qualifiers).
-*/
-static int is_compatible_unqualified_types(CType *type1, CType *type2)
-{
- return compare_types(type1,type2,1);
-}
-
-static void cast_error(CType *st, CType *dt)
-{
- type_incompatibility_error(st, dt, "cannot convert '%s' to '%s'");
-}
-
-/* verify type compatibility to store vtop in 'dt' type */
-static void verify_assign_cast(CType *dt)
-{
- CType *st, *type1, *type2;
- int dbt, sbt, qualwarn, lvl;
-
- st = &vtop->type; /* source type */
- dbt = dt->t & VT_BTYPE;
- sbt = st->t & VT_BTYPE;
- if (dt->t & VT_CONSTANT)
- tcc_warning("assignment of read-only location");
- switch(dbt) {
- case VT_VOID:
- if (sbt != dbt)
- tcc_error("assignment to void expression");
- break;
- case VT_PTR:
- /* special cases for pointers */
- /* '0' can also be a pointer */
- if (is_null_pointer(vtop))
- break;
- /* accept implicit pointer to integer cast with warning */
- if (is_integer_btype(sbt)) {
- tcc_warning("assignment makes pointer from integer without a cast");
- break;
- }
- type1 = pointed_type(dt);
- if (sbt == VT_PTR)
- type2 = pointed_type(st);
- else if (sbt == VT_FUNC)
- type2 = st; /* a function is implicitly a function pointer */
- else
- goto error;
- if (is_compatible_types(type1, type2))
- break;
- for (qualwarn = lvl = 0;; ++lvl) {
- if (((type2->t & VT_CONSTANT) && !(type1->t & VT_CONSTANT)) ||
- ((type2->t & VT_VOLATILE) && !(type1->t & VT_VOLATILE)))
- qualwarn = 1;
- dbt = type1->t & (VT_BTYPE|VT_LONG);
- sbt = type2->t & (VT_BTYPE|VT_LONG);
- if (dbt != VT_PTR || sbt != VT_PTR)
- break;
- type1 = pointed_type(type1);
- type2 = pointed_type(type2);
- }
- if (!is_compatible_unqualified_types(type1, type2)) {
- if ((dbt == VT_VOID || sbt == VT_VOID) && lvl == 0) {
- /* void * can match anything */
- } else if (dbt == sbt
- && is_integer_btype(sbt & VT_BTYPE)
- && IS_ENUM(type1->t) + IS_ENUM(type2->t)
- + !!((type1->t ^ type2->t) & VT_UNSIGNED) < 2) {
- /* Like GCC don't warn by default for merely changes
- in pointer target signedness. Do warn for different
- base types, though, in particular for unsigned enums
- and signed int targets. */
- } else {
- tcc_warning("assignment from incompatible pointer type");
- break;
- }
- }
- if (qualwarn)
- tcc_warning_c(warn_discarded_qualifiers)("assignment discards qualifiers from pointer target type");
- break;
- case VT_BYTE:
- case VT_SHORT:
- case VT_INT:
- case VT_LLONG:
- if (sbt == VT_PTR || sbt == VT_FUNC) {
- tcc_warning("assignment makes integer from pointer without a cast");
- } else if (sbt == VT_STRUCT) {
- goto case_VT_STRUCT;
- }
- /* XXX: more tests */
- break;
- case VT_STRUCT:
- case_VT_STRUCT:
- if (!is_compatible_unqualified_types(dt, st)) {
- error:
- cast_error(st, dt);
- }
- break;
- }
-}
-
-static void gen_assign_cast(CType *dt)
-{
- verify_assign_cast(dt);
- gen_cast(dt);
-}
-
-/* store vtop in lvalue pushed on stack */
-ST_FUNC void vstore(void)
-{
- int sbt, dbt, ft, r, size, align, bit_size, bit_pos, delayed_cast;
-
- ft = vtop[-1].type.t;
- sbt = vtop->type.t & VT_BTYPE;
- dbt = ft & VT_BTYPE;
- verify_assign_cast(&vtop[-1].type);
-
- if (sbt == VT_STRUCT) {
- /* if structure, only generate pointer */
- /* structure assignment : generate memcpy */
- size = type_size(&vtop->type, &align);
- /* destination, keep on stack() as result */
- vpushv(vtop - 1);
-#ifdef CONFIG_TCC_BCHECK
- if (vtop->r & VT_MUSTBOUND)
- gbound(); /* check would be wrong after gaddrof() */
-#endif
- vtop->type.t = VT_PTR;
- gaddrof();
- /* source */
- vswap();
-#ifdef CONFIG_TCC_BCHECK
- if (vtop->r & VT_MUSTBOUND)
- gbound();
-#endif
- vtop->type.t = VT_PTR;
- gaddrof();
-
-#ifdef TCC_TARGET_NATIVE_STRUCT_COPY
- if (1
-#ifdef CONFIG_TCC_BCHECK
- && !tcc_state->do_bounds_check
-#endif
- ) {
- gen_struct_copy(size);
- } else
-#endif
- {
- /* type size */
- vpushi(size);
- /* Use memmove, rather than memcpy, as dest and src may be same: */
-#ifdef TCC_ARM_EABI
- if(!(align & 7))
- vpush_helper_func(TOK_memmove8);
- else if(!(align & 3))
- vpush_helper_func(TOK_memmove4);
- else
-#endif
- vpush_helper_func(TOK_memmove);
- vrott(4);
- gfunc_call(3);
- }
-
- } else if (ft & VT_BITFIELD) {
- /* bitfield store handling */
-
- /* save lvalue as expression result (example: s.b = s.a = n;) */
- vdup(), vtop[-1] = vtop[-2];
-
- bit_pos = BIT_POS(ft);
- bit_size = BIT_SIZE(ft);
- /* remove bit field info to avoid loops */
- vtop[-1].type.t = ft & ~VT_STRUCT_MASK;
-
- if (dbt == VT_BOOL) {
- gen_cast(&vtop[-1].type);
- vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | VT_UNSIGNED);
- }
- r = adjust_bf(vtop - 1, bit_pos, bit_size);
- if (dbt != VT_BOOL) {
- gen_cast(&vtop[-1].type);
- dbt = vtop[-1].type.t & VT_BTYPE;
- }
- if (r == VT_STRUCT) {
- store_packed_bf(bit_pos, bit_size);
- } else {
- unsigned long long mask = (1ULL << bit_size) - 1;
- if (dbt != VT_BOOL) {
- /* mask source */
- if (dbt == VT_LLONG)
- vpushll(mask);
- else
- vpushi((unsigned)mask);
- gen_op('&');
- }
- /* shift source */
- vpushi(bit_pos);
- gen_op(TOK_SHL);
- vswap();
- /* duplicate destination */
- vdup();
- vrott(3);
- /* load destination, mask and or with source */
- if (dbt == VT_LLONG)
- vpushll(~(mask << bit_pos));
- else
- vpushi(~((unsigned)mask << bit_pos));
- gen_op('&');
- gen_op('|');
- /* store result */
- vstore();
- /* ... and discard */
- vpop();
- }
- } else if (dbt == VT_VOID) {
- --vtop;
- } else {
- /* optimize char/short casts */
- delayed_cast = 0;
- if ((dbt == VT_BYTE || dbt == VT_SHORT)
- && is_integer_btype(sbt)
- ) {
- if ((vtop->r & VT_MUSTCAST)
- && btype_size(dbt) > btype_size(sbt)
- )
- force_charshort_cast();
- delayed_cast = 1;
- } else {
- gen_cast(&vtop[-1].type);
- }
-
-#ifdef CONFIG_TCC_BCHECK
- /* bound check case */
- if (vtop[-1].r & VT_MUSTBOUND) {
- vswap();
- gbound();
- vswap();
- }
-#endif
- gv(RC_TYPE(dbt)); /* generate value */
-
- if (delayed_cast) {
- vtop->r |= BFVAL(VT_MUSTCAST, (sbt == VT_LLONG) + 1);
- //tcc_warning("deley cast %x -> %x", sbt, dbt);
- vtop->type.t = ft & VT_TYPE;
- }
-
- /* if lvalue was saved on stack, must read it */
- if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
- SValue sv;
- r = get_reg(RC_INT);
- sv.type.t = VT_PTRDIFF_T;
- sv.r = VT_LOCAL | VT_LVAL;
- sv.c.i = vtop[-1].c.i;
- load(r, &sv);
- vtop[-1].r = r | VT_LVAL;
- }
-
- r = vtop->r & VT_VALMASK;
- /* two word case handling :
- store second register at word + 4 (or +8 for x86-64) */
- if (USING_TWO_WORDS(dbt)) {
- int load_type = (dbt == VT_QFLOAT) ? VT_DOUBLE : VT_PTRDIFF_T;
- vtop[-1].type.t = load_type;
- store(r, vtop - 1);
- vswap();
- /* convert to int to increment easily */
- vtop->type.t = VT_PTRDIFF_T;
- gaddrof();
- vpushs(PTR_SIZE);
- gen_op('+');
- vtop->r |= VT_LVAL;
- vswap();
- vtop[-1].type.t = load_type;
- /* XXX: it works because r2 is spilled last ! */
- store(vtop->r2, vtop - 1);
- } else {
- /* single word */
- store(r, vtop - 1);
- }
- vswap();
- vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
- }
-}
-
-/* post defines POST/PRE add. c is the token ++ or -- */
-ST_FUNC void inc(int post, int c)
-{
- test_lvalue();
- vdup(); /* save lvalue */
- if (post) {
- gv_dup(); /* duplicate value */
- vrotb(3);
- vrotb(3);
- }
- /* add constant */
- vpushi(c - TOK_MID);
- gen_op('+');
- vstore(); /* store value */
- if (post)
- vpop(); /* if post op, return saved value */
-}
-
-ST_FUNC CString* parse_mult_str (const char *msg)
-{
- /* read the string */
- if (tok != TOK_STR)
- expect(msg);
- cstr_reset(&initstr);
- while (tok == TOK_STR) {
- /* XXX: add \0 handling too ? */
- cstr_cat(&initstr, tokc.str.data, -1);
- next();
- }
- cstr_ccat(&initstr, '\0');
- return &initstr;
-}
-
-/* If I is >= 1 and a power of two, returns log2(i)+1.
- If I is 0 returns 0. */
-ST_FUNC int exact_log2p1(int i)
-{
- int ret;
- if (!i)
- return 0;
- for (ret = 1; i >= 1 << 8; ret += 8)
- i >>= 8;
- if (i >= 1 << 4)
- ret += 4, i >>= 4;
- if (i >= 1 << 2)
- ret += 2, i >>= 2;
- if (i >= 1 << 1)
- ret++;
- return ret;
-}
-
-/* Parse __attribute__((...)) GNUC extension. */
-static void parse_attribute(AttributeDef *ad)
-{
- int t, n;
- char *astr;
-
-redo:
- if (tok != TOK_ATTRIBUTE1 && tok != TOK_ATTRIBUTE2)
- return;
- next();
- skip('(');
- skip('(');
- while (tok != ')') {
- if (tok < TOK_IDENT)
- expect("attribute name");
- t = tok;
- next();
- switch(t) {
- case TOK_CLEANUP1:
- case TOK_CLEANUP2:
- {
- Sym *s;
-
- skip('(');
- s = sym_find(tok);
- if (!s) {
- tcc_warning_c(warn_implicit_function_declaration)(
- "implicit declaration of function '%s'", get_tok_str(tok, &tokc));
- s = external_global_sym(tok, &func_old_type);
- } else if ((s->type.t & VT_BTYPE) != VT_FUNC)
- tcc_error("'%s' is not declared as function", get_tok_str(tok, &tokc));
- ad->cleanup_func = s;
- next();
- skip(')');
- break;
- }
- case TOK_CONSTRUCTOR1:
- case TOK_CONSTRUCTOR2:
- ad->f.func_ctor = 1;
- break;
- case TOK_DESTRUCTOR1:
- case TOK_DESTRUCTOR2:
- ad->f.func_dtor = 1;
- break;
- case TOK_ALWAYS_INLINE1:
- case TOK_ALWAYS_INLINE2:
- ad->f.func_alwinl = 1;
- break;
- case TOK_SECTION1:
- case TOK_SECTION2:
- skip('(');
- astr = parse_mult_str("section name")->data;
- ad->section = find_section(tcc_state, astr);
- skip(')');
- break;
- case TOK_ALIAS1:
- case TOK_ALIAS2:
- skip('(');
- astr = parse_mult_str("alias(\"target\")")->data;
- /* save string as token, for later */
- ad->alias_target = tok_alloc_const(astr);
- skip(')');
- break;
- case TOK_VISIBILITY1:
- case TOK_VISIBILITY2:
- skip('(');
- astr = parse_mult_str("visibility(\"default|hidden|internal|protected\")")->data;
- if (!strcmp (astr, "default"))
- ad->a.visibility = STV_DEFAULT;
- else if (!strcmp (astr, "hidden"))
- ad->a.visibility = STV_HIDDEN;
- else if (!strcmp (astr, "internal"))
- ad->a.visibility = STV_INTERNAL;
- else if (!strcmp (astr, "protected"))
- ad->a.visibility = STV_PROTECTED;
- else
- expect("visibility(\"default|hidden|internal|protected\")");
- skip(')');
- break;
- case TOK_ALIGNED1:
- case TOK_ALIGNED2:
- if (tok == '(') {
- next();
- n = expr_const();
- if (n <= 0 || (n & (n - 1)) != 0)
- tcc_error("alignment must be a positive power of two");
- skip(')');
- } else {
- n = MAX_ALIGN;
- }
- ad->a.aligned = exact_log2p1(n);
- if (n != 1 << (ad->a.aligned - 1))
- tcc_error("alignment of %d is larger than implemented", n);
- break;
- case TOK_PACKED1:
- case TOK_PACKED2:
- ad->a.packed = 1;
- break;
- case TOK_WEAK1:
- case TOK_WEAK2:
- ad->a.weak = 1;
- break;
- case TOK_NODEBUG1:
- case TOK_NODEBUG2:
- ad->a.nodebug = 1;
- break;
- case TOK_UNUSED1:
- case TOK_UNUSED2:
- /* currently, no need to handle it because tcc does not
- track unused objects */
- break;
- case TOK_NORETURN1:
- case TOK_NORETURN2:
- ad->f.func_noreturn = 1;
- break;
- case TOK_CDECL1:
- case TOK_CDECL2:
- case TOK_CDECL3:
- ad->f.func_call = FUNC_CDECL;
- break;
- case TOK_STDCALL1:
- case TOK_STDCALL2:
- case TOK_STDCALL3:
- ad->f.func_call = FUNC_STDCALL;
- break;
-#ifdef TCC_TARGET_I386
- case TOK_REGPARM1:
- case TOK_REGPARM2:
- skip('(');
- n = expr_const();
- if (n > 3)
- n = 3;
- else if (n < 0)
- n = 0;
- if (n > 0)
- ad->f.func_call = FUNC_FASTCALL1 + n - 1;
- skip(')');
- break;
- case TOK_FASTCALL1:
- case TOK_FASTCALL2:
- case TOK_FASTCALL3:
- ad->f.func_call = FUNC_FASTCALLW;
- break;
-#endif
- case TOK_MODE:
- skip('(');
- switch(tok) {
- case TOK_MODE_DI:
- ad->attr_mode = VT_LLONG + 1;
- break;
- case TOK_MODE_QI:
- ad->attr_mode = VT_BYTE + 1;
- break;
- case TOK_MODE_HI:
- ad->attr_mode = VT_SHORT + 1;
- break;
- case TOK_MODE_SI:
- case TOK_MODE_word:
- ad->attr_mode = VT_INT + 1;
- break;
- default:
- tcc_warning("__mode__(%s) not supported\n", get_tok_str(tok, NULL));
- break;
- }
- next();
- skip(')');
- break;
- case TOK_DLLEXPORT:
- ad->a.dllexport = 1;
- break;
- case TOK_NODECORATE:
- ad->a.nodecorate = 1;
- break;
- case TOK_DLLIMPORT:
- ad->a.dllimport = 1;
- break;
- default:
- tcc_warning_c(warn_unsupported)("'%s' attribute ignored", get_tok_str(t, NULL));
- /* skip parameters */
- if (tok == '(') {
- int parenthesis = 0;
- do {
- if (tok == '(')
- parenthesis++;
- else if (tok == ')')
- parenthesis--;
- next();
- } while (parenthesis && tok != -1);
- }
- break;
- }
- if (tok != ',')
- break;
- next();
- }
- skip(')');
- skip(')');
- goto redo;
-}
-
-static Sym * find_field (CType *type, int v, int *cumofs)
-{
- Sym *s = type->ref;
- int v1 = v | SYM_FIELD;
-
- while ((s = s->next) != NULL) {
- if (s->v == v1) {
- *cumofs += s->c;
- return s;
- }
- if ((s->type.t & VT_BTYPE) == VT_STRUCT
- && s->v >= (SYM_FIRST_ANOM | SYM_FIELD)) {
- /* try to find field in anonymous sub-struct/union */
- Sym *ret = find_field (&s->type, v1, cumofs);
- if (ret) {
- *cumofs += s->c;
- return ret;
- }
- }
- }
-
- if (!(v & SYM_FIELD)) { /* top-level call */
- s = type->ref;
- if (s->c < 0)
- tcc_error("dereferencing incomplete type '%s'",
- get_tok_str(s->v & ~SYM_STRUCT, 0));
- else
- tcc_error("field not found: %s",
- get_tok_str(v, &tokc));
- }
- return NULL;
-}
-
-static void check_fields (CType *type, int check)
-{
- Sym *s = type->ref;
-
- while ((s = s->next) != NULL) {
- int v = s->v & ~SYM_FIELD;
- if (v < SYM_FIRST_ANOM) {
- TokenSym *ts = table_ident[v - TOK_IDENT];
- if (check && (ts->tok & SYM_FIELD))
- tcc_error("duplicate member '%s'", get_tok_str(v, NULL));
- ts->tok ^= SYM_FIELD;
- } else if ((s->type.t & VT_BTYPE) == VT_STRUCT)
- check_fields (&s->type, check);
- }
-}
-
-static void struct_layout(CType *type, AttributeDef *ad)
-{
- int size, align, maxalign, offset, c, bit_pos, bit_size;
- int packed, a, bt, prevbt, prev_bit_size;
- int pcc = !tcc_state->ms_bitfields;
- int pragma_pack = *tcc_state->pack_stack_ptr;
- Sym *f;
-
- maxalign = 1;
- offset = 0;
- c = 0;
- bit_pos = 0;
- prevbt = VT_STRUCT; /* make it never match */
- prev_bit_size = 0;
-
-//#define BF_DEBUG
-
- for (f = type->ref->next; f; f = f->next) {
- if (f->type.t & VT_BITFIELD)
- bit_size = BIT_SIZE(f->type.t);
- else
- bit_size = -1;
- size = type_size(&f->type, &align);
- a = f->a.aligned ? 1 << (f->a.aligned - 1) : 0;
- packed = 0;
-
- if (pcc && bit_size == 0) {
- /* in pcc mode, packing does not affect zero-width bitfields */
-
- } else {
- /* in pcc mode, attribute packed overrides if set. */
- if (pcc && (f->a.packed || ad->a.packed))
- align = packed = 1;
-
- /* pragma pack overrides align if lesser and packs bitfields always */
- if (pragma_pack) {
- packed = 1;
- if (pragma_pack < align)
- align = pragma_pack;
- /* in pcc mode pragma pack also overrides individual align */
- if (pcc && pragma_pack < a)
- a = 0;
- }
- }
- /* some individual align was specified */
- if (a)
- align = a;
-
- if (type->ref->type.t == VT_UNION) {
- if (pcc && bit_size >= 0)
- size = (bit_size + 7) >> 3;
- offset = 0;
- if (size > c)
- c = size;
-
- } else if (bit_size < 0) {
- if (pcc)
- c += (bit_pos + 7) >> 3;
- c = (c + align - 1) & -align;
- offset = c;
- if (size > 0)
- c += size;
- bit_pos = 0;
- prevbt = VT_STRUCT;
- prev_bit_size = 0;
-
- } else {
- /* A bit-field. Layout is more complicated. There are two
- options: PCC (GCC) compatible and MS compatible */
- if (pcc) {
- /* In PCC layout a bit-field is placed adjacent to the
- preceding bit-fields, except if:
- - it has zero-width
- - an individual alignment was given
- - it would overflow its base type container and
- there is no packing */
- if (bit_size == 0) {
- new_field:
- c = (c + ((bit_pos + 7) >> 3) + align - 1) & -align;
- bit_pos = 0;
- } else if (f->a.aligned) {
- goto new_field;
- } else if (!packed) {
- int a8 = align * 8;
- int ofs = ((c * 8 + bit_pos) % a8 + bit_size + a8 - 1) / a8;
- if (ofs > size / align)
- goto new_field;
- }
-
- /* in pcc mode, long long bitfields have type int if they fit */
- if (size == 8 && bit_size <= 32)
- f->type.t = (f->type.t & ~VT_BTYPE) | VT_INT, size = 4;
-
- while (bit_pos >= align * 8)
- c += align, bit_pos -= align * 8;
- offset = c;
-
- /* In PCC layout named bit-fields influence the alignment
- of the containing struct using the base types alignment,
- except for packed fields (which here have correct align). */
- if (f->v & SYM_FIRST_ANOM
- // && bit_size // ??? gcc on ARM/rpi does that
- )
- align = 1;
-
- } else {
- bt = f->type.t & VT_BTYPE;
- if ((bit_pos + bit_size > size * 8)
- || (bit_size > 0) == (bt != prevbt)
- ) {
- c = (c + align - 1) & -align;
- offset = c;
- bit_pos = 0;
- /* In MS bitfield mode a bit-field run always uses
- at least as many bits as the underlying type.
- To start a new run it's also required that this
- or the last bit-field had non-zero width. */
- if (bit_size || prev_bit_size)
- c += size;
- }
- /* In MS layout the records alignment is normally
- influenced by the field, except for a zero-width
- field at the start of a run (but by further zero-width
- fields it is again). */
- if (bit_size == 0 && prevbt != bt)
- align = 1;
- prevbt = bt;
- prev_bit_size = bit_size;
- }
-
- f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT))
- | (bit_pos << VT_STRUCT_SHIFT);
- bit_pos += bit_size;
- }
- if (align > maxalign)
- maxalign = align;
-
-#ifdef BF_DEBUG
- printf("set field %s offset %-2d size %-2d align %-2d",
- get_tok_str(f->v & ~SYM_FIELD, NULL), offset, size, align);
- if (f->type.t & VT_BITFIELD) {
- printf(" pos %-2d bits %-2d",
- BIT_POS(f->type.t),
- BIT_SIZE(f->type.t)
- );
- }
- printf("\n");
-#endif
-
- f->c = offset;
- f->r = 0;
- }
-
- if (pcc)
- c += (bit_pos + 7) >> 3;
-
- /* store size and alignment */
- a = bt = ad->a.aligned ? 1 << (ad->a.aligned - 1) : 1;
- if (a < maxalign)
- a = maxalign;
- type->ref->r = a;
- if (pragma_pack && pragma_pack < maxalign && 0 == pcc) {
- /* can happen if individual align for some member was given. In
- this case MSVC ignores maxalign when aligning the size */
- a = pragma_pack;
- if (a < bt)
- a = bt;
- }
- c = (c + a - 1) & -a;
- type->ref->c = c;
-
-#ifdef BF_DEBUG
- printf("struct size %-2d align %-2d\n\n", c, a), fflush(stdout);
-#endif
-
- /* check whether we can access bitfields by their type */
- for (f = type->ref->next; f; f = f->next) {
- int s, px, cx, c0;
- CType t;
-
- if (0 == (f->type.t & VT_BITFIELD))
- continue;
- f->type.ref = f;
- f->auxtype = -1;
- bit_size = BIT_SIZE(f->type.t);
- if (bit_size == 0)
- continue;
- bit_pos = BIT_POS(f->type.t);
- size = type_size(&f->type, &align);
-
- if (bit_pos + bit_size <= size * 8 && f->c + size <= c
-#ifdef TCC_TARGET_ARM
- && !(f->c & (align - 1))
-#endif
- )
- continue;
-
- /* try to access the field using a different type */
- c0 = -1, s = align = 1;
- t.t = VT_BYTE;
- for (;;) {
- px = f->c * 8 + bit_pos;
- cx = (px >> 3) & -align;
- px = px - (cx << 3);
- if (c0 == cx)
- break;
- s = (px + bit_size + 7) >> 3;
- if (s > 4) {
- t.t = VT_LLONG;
- } else if (s > 2) {
- t.t = VT_INT;
- } else if (s > 1) {
- t.t = VT_SHORT;
- } else {
- t.t = VT_BYTE;
- }
- s = type_size(&t, &align);
- c0 = cx;
- }
-
- if (px + bit_size <= s * 8 && cx + s <= c
-#ifdef TCC_TARGET_ARM
- && !(cx & (align - 1))
-#endif
- ) {
- /* update offset and bit position */
- f->c = cx;
- bit_pos = px;
- f->type.t = (f->type.t & ~(0x3f << VT_STRUCT_SHIFT))
- | (bit_pos << VT_STRUCT_SHIFT);
- if (s != size)
- f->auxtype = t.t;
-#ifdef BF_DEBUG
- printf("FIX field %s offset %-2d size %-2d align %-2d "
- "pos %-2d bits %-2d\n",
- get_tok_str(f->v & ~SYM_FIELD, NULL),
- cx, s, align, px, bit_size);
-#endif
- } else {
- /* fall back to load/store single-byte wise */
- f->auxtype = VT_STRUCT;
-#ifdef BF_DEBUG
- printf("FIX field %s : load byte-wise\n",
- get_tok_str(f->v & ~SYM_FIELD, NULL));
-#endif
- }
- }
-}
-
-static void do_Static_assert(void);
-
-/* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */
-static void struct_decl(CType *type, int u)
-{
- int v, c, size, align, flexible;
- int bit_size, bsize, bt;
- Sym *s, *ss, **ps;
- AttributeDef ad, ad1;
- CType type1, btype;
-
- memset(&ad, 0, sizeof ad);
- next();
- parse_attribute(&ad);
- if (tok != '{') {
- v = tok;
- next();
- /* struct already defined ? return it */
- if (v < TOK_IDENT)
- expect("struct/union/enum name");
- s = struct_find(v);
- if (s && (s->sym_scope == local_scope || tok != '{')) {
- if (u == s->type.t)
- goto do_decl;
- if (u == VT_ENUM && IS_ENUM(s->type.t))
- goto do_decl;
- tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
- }
- } else {
- v = anon_sym++;
- }
- /* Record the original enum/struct/union token. */
- type1.t = u == VT_ENUM ? u | VT_INT | VT_UNSIGNED : u;
- type1.ref = NULL;
- /* we put an undefined size for struct/union */
- s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
- s->r = 0; /* default alignment is zero as gcc */
-do_decl:
- type->t = s->type.t;
- type->ref = s;
-
- if (tok == '{') {
- next();
- if (s->c != -1)
- tcc_error("struct/union/enum already defined");
- s->c = -2;
- /* cannot be empty */
- /* non empty enums are not allowed */
- ps = &s->next;
- if (u == VT_ENUM) {
- long long ll = 0, pl = 0, nl = 0;
- CType t;
- t.ref = s;
- /* enum symbols have static storage */
- t.t = VT_INT|VT_STATIC|VT_ENUM_VAL;
- for(;;) {
- v = tok;
- if (v < TOK_UIDENT)
- expect("identifier");
- ss = sym_find(v);
- if (ss && !local_stack)
- tcc_error("redefinition of enumerator '%s'",
- get_tok_str(v, NULL));
- next();
- if (tok == '=') {
- next();
- ll = expr_const64();
- }
- ss = sym_push(v, &t, VT_CONST, 0);
- ss->enum_val = ll;
- *ps = ss, ps = &ss->next;
- if (ll < nl)
- nl = ll;
- if (ll > pl)
- pl = ll;
- if (tok != ',')
- break;
- next();
- ll++;
- /* NOTE: we accept a trailing comma */
- if (tok == '}')
- break;
- }
- skip('}');
- /* set integral type of the enum */
- t.t = VT_INT;
- if (nl >= 0) {
- if (pl != (unsigned)pl)
- t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG);
- t.t |= VT_UNSIGNED;
- } else if (pl != (int)pl || nl != (int)nl)
- t.t = (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG);
- s->type.t = type->t = t.t | VT_ENUM;
- s->c = 0;
- /* set type for enum members */
- for (ss = s->next; ss; ss = ss->next) {
- ll = ss->enum_val;
- if (ll == (int)ll) /* default is int if it fits */
- continue;
- if (t.t & VT_UNSIGNED) {
- ss->type.t |= VT_UNSIGNED;
- if (ll == (unsigned)ll)
- continue;
- }
- ss->type.t = (ss->type.t & ~VT_BTYPE)
- | (LONG_SIZE==8 ? VT_LLONG|VT_LONG : VT_LLONG);
- }
- } else {
- c = 0;
- flexible = 0;
- while (tok != '}') {
- if (tok == TOK_STATIC_ASSERT) {
- do_Static_assert();
- continue;
- }
- if (!parse_btype(&btype, &ad1, 0)) {
- skip(';');
- continue;
- }
- while (1) {
- if (flexible)
- tcc_error("flexible array member '%s' not at the end of struct",
- get_tok_str(v, NULL));
- bit_size = -1;
- v = 0;
- type1 = btype;
- if (tok != ':') {
- if (tok != ';')
- type_decl(&type1, &ad1, &v, TYPE_DIRECT);
- if (v == 0) {
- if ((type1.t & VT_BTYPE) != VT_STRUCT)
- expect("identifier");
- else {
- int v = btype.ref->v;
- if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
- if (tcc_state->ms_extensions == 0)
- expect("identifier");
- }
- }
- }
- if (type_size(&type1, &align) < 0) {
- if ((u == VT_STRUCT) && (type1.t & VT_ARRAY) && c)
- flexible = 1;
- else
- tcc_error("field '%s' has incomplete type",
- get_tok_str(v, NULL));
- }
- if ((type1.t & VT_BTYPE) == VT_FUNC ||
- (type1.t & VT_BTYPE) == VT_VOID ||
- (type1.t & VT_STORAGE))
- tcc_error("invalid type for '%s'",
- get_tok_str(v, NULL));
- }
- if (tok == ':') {
- next();
- bit_size = expr_const();
- /* XXX: handle v = 0 case for messages */
- if (bit_size < 0)
- tcc_error("negative width in bit-field '%s'",
- get_tok_str(v, NULL));
- if (v && bit_size == 0)
- tcc_error("zero width for bit-field '%s'",
- get_tok_str(v, NULL));
- parse_attribute(&ad1);
- }
- size = type_size(&type1, &align);
- if (bit_size >= 0) {
- bt = type1.t & VT_BTYPE;
- if (bt != VT_INT &&
- bt != VT_BYTE &&
- bt != VT_SHORT &&
- bt != VT_BOOL &&
- bt != VT_LLONG)
- tcc_error("bitfields must have scalar type");
- bsize = size * 8;
- if (bit_size > bsize) {
- tcc_error("width of '%s' exceeds its type",
- get_tok_str(v, NULL));
- } else if (bit_size == bsize
- && !ad.a.packed && !ad1.a.packed) {
- /* no need for bit fields */
- ;
- } else if (bit_size == 64) {
- tcc_error("field width 64 not implemented");
- } else {
- type1.t = (type1.t & ~VT_STRUCT_MASK)
- | VT_BITFIELD
- | (bit_size << (VT_STRUCT_SHIFT + 6));
- }
- }
- if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
- /* Remember we've seen a real field to check
- for placement of flexible array member. */
- c = 1;
- }
- /* If member is a struct or bit-field, enforce
- placing into the struct (as anonymous). */
- if (v == 0 &&
- ((type1.t & VT_BTYPE) == VT_STRUCT ||
- bit_size >= 0)) {
- v = anon_sym++;
- }
- if (v) {
- ss = sym_push(v | SYM_FIELD, &type1, 0, 0);
- ss->a = ad1.a;
- *ps = ss;
- ps = &ss->next;
- }
- if (tok == ';' || tok == TOK_EOF)
- break;
- skip(',');
- }
- skip(';');
- }
- skip('}');
- parse_attribute(&ad);
- if (ad.cleanup_func) {
- tcc_warning("attribute '__cleanup__' ignored on type");
- }
- check_fields(type, 1);
- check_fields(type, 0);
- struct_layout(type, &ad);
- if (debug_modes)
- tcc_debug_fix_anon(tcc_state, type);
- }
- }
-}
-
-static void sym_to_attr(AttributeDef *ad, Sym *s)
-{
- merge_symattr(&ad->a, &s->a);
- merge_funcattr(&ad->f, &s->f);
-}
-
-/* Add type qualifiers to a type. If the type is an array then the qualifiers
- are added to the element type, copied because it could be a typedef. */
-static void parse_btype_qualify(CType *type, int qualifiers)
-{
- while (type->t & VT_ARRAY) {
- type->ref = sym_push(SYM_FIELD, &type->ref->type, 0, type->ref->c);
- type = &type->ref->type;
- }
- type->t |= qualifiers;
-}
-
-/* return 0 if no type declaration. otherwise, return the basic type
- and skip it.
- */
-static int parse_btype(CType *type, AttributeDef *ad, int ignore_label)
-{
- int t, u, bt, st, type_found, typespec_found, g, n;
- Sym *s;
- CType type1;
-
- memset(ad, 0, sizeof(AttributeDef));
- type_found = 0;
- typespec_found = 0;
- t = VT_INT;
- bt = st = -1;
- type->ref = NULL;
-
- while(1) {
- switch(tok) {
- case TOK_EXTENSION:
- /* currently, we really ignore extension */
- next();
- continue;
-
- /* basic types */
- case TOK_CHAR:
- u = VT_BYTE;
- basic_type:
- next();
- basic_type1:
- if (u == VT_SHORT || u == VT_LONG) {
- if (st != -1 || (bt != -1 && bt != VT_INT))
- tmbt: tcc_error("too many basic types");
- st = u;
- } else {
- if (bt != -1 || (st != -1 && u != VT_INT))
- goto tmbt;
- bt = u;
- }
- if (u != VT_INT)
- t = (t & ~(VT_BTYPE|VT_LONG)) | u;
- typespec_found = 1;
- break;
- case TOK_VOID:
- u = VT_VOID;
- goto basic_type;
- case TOK_SHORT:
- u = VT_SHORT;
- goto basic_type;
- case TOK_INT:
- u = VT_INT;
- goto basic_type;
- case TOK_ALIGNAS:
- { int n;
- AttributeDef ad1;
- next();
- skip('(');
- memset(&ad1, 0, sizeof(AttributeDef));
- if (parse_btype(&type1, &ad1, 0)) {
- type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
- if (ad1.a.aligned)
- n = 1 << (ad1.a.aligned - 1);
- else
- type_size(&type1, &n);
- } else {
- n = expr_const();
- if (n < 0 || (n & (n - 1)) != 0)
- tcc_error("alignment must be a positive power of two");
- }
- skip(')');
- ad->a.aligned = exact_log2p1(n);
- }
- continue;
- case TOK_LONG:
- if ((t & VT_BTYPE) == VT_DOUBLE) {
- t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE;
- } else if ((t & (VT_BTYPE|VT_LONG)) == VT_LONG) {
- t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LLONG;
- } else {
- u = VT_LONG;
- goto basic_type;
- }
- next();
- break;
-#ifdef TCC_TARGET_ARM64
- case TOK_UINT128:
- /* GCC's __uint128_t appears in some Linux header files. Make it a
- synonym for long double to get the size and alignment right. */
- u = VT_LDOUBLE;
- goto basic_type;
-#endif
- case TOK_BOOL:
- u = VT_BOOL;
- goto basic_type;
- case TOK_COMPLEX:
- tcc_error("_Complex is not yet supported");
- case TOK_FLOAT:
- u = VT_FLOAT;
- goto basic_type;
- case TOK_DOUBLE:
- if ((t & (VT_BTYPE|VT_LONG)) == VT_LONG) {
- t = (t & ~(VT_BTYPE|VT_LONG)) | VT_LDOUBLE;
- } else {
- u = VT_DOUBLE;
- goto basic_type;
- }
- next();
- break;
- case TOK_ENUM:
- struct_decl(&type1, VT_ENUM);
- basic_type2:
- u = type1.t;
- type->ref = type1.ref;
- goto basic_type1;
- case TOK_STRUCT:
- struct_decl(&type1, VT_STRUCT);
- goto basic_type2;
- case TOK_UNION:
- struct_decl(&type1, VT_UNION);
- goto basic_type2;
-
- /* type modifiers */
- case TOK__Atomic:
- next();
- type->t = t;
- parse_btype_qualify(type, VT_ATOMIC);
- t = type->t;
- if (tok == '(') {
- parse_expr_type(&type1);
- /* remove all storage modifiers except typedef */
- type1.t &= ~(VT_STORAGE&~VT_TYPEDEF);
- if (type1.ref)
- sym_to_attr(ad, type1.ref);
- goto basic_type2;
- }
- break;
- case TOK_CONST1:
- case TOK_CONST2:
- case TOK_CONST3:
- type->t = t;
- parse_btype_qualify(type, VT_CONSTANT);
- t = type->t;
- next();
- break;
- case TOK_VOLATILE1:
- case TOK_VOLATILE2:
- case TOK_VOLATILE3:
- type->t = t;
- parse_btype_qualify(type, VT_VOLATILE);
- t = type->t;
- next();
- break;
- case TOK_SIGNED1:
- case TOK_SIGNED2:
- case TOK_SIGNED3:
- if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == (VT_DEFSIGN|VT_UNSIGNED))
- tcc_error("signed and unsigned modifier");
- t |= VT_DEFSIGN;
- next();
- typespec_found = 1;
- break;
- case TOK_REGISTER:
- case TOK_AUTO:
- case TOK_RESTRICT1:
- case TOK_RESTRICT2:
- case TOK_RESTRICT3:
- next();
- break;
- case TOK_UNSIGNED:
- if ((t & (VT_DEFSIGN|VT_UNSIGNED)) == VT_DEFSIGN)
- tcc_error("signed and unsigned modifier");
- t |= VT_DEFSIGN | VT_UNSIGNED;
- next();
- typespec_found = 1;
- break;
-
- /* storage */
- case TOK_EXTERN:
- g = VT_EXTERN;
- goto storage;
- case TOK_STATIC:
- g = VT_STATIC;
- goto storage;
- case TOK_TYPEDEF:
- g = VT_TYPEDEF;
- goto storage;
- storage:
- if (t & (VT_EXTERN|VT_STATIC|VT_TYPEDEF) & ~g)
- tcc_error("multiple storage classes");
- t |= g;
- next();
- break;
- case TOK_INLINE1:
- case TOK_INLINE2:
- case TOK_INLINE3:
- t |= VT_INLINE;
- next();
- break;
- case TOK_NORETURN3:
- next();
- ad->f.func_noreturn = 1;
- break;
- /* GNUC attribute */
- case TOK_ATTRIBUTE1:
- case TOK_ATTRIBUTE2:
- parse_attribute(ad);
- if (ad->attr_mode) {
- u = ad->attr_mode -1;
- t = (t & ~(VT_BTYPE|VT_LONG)) | u;
- }
- continue;
- /* GNUC typeof */
- case TOK_TYPEOF1:
- case TOK_TYPEOF2:
- case TOK_TYPEOF3:
- next();
- parse_expr_type(&type1);
- /* remove all storage modifiers except typedef */
- type1.t &= ~(VT_STORAGE&~VT_TYPEDEF);
- if (type1.ref)
- sym_to_attr(ad, type1.ref);
- goto basic_type2;
- case TOK_THREAD_LOCAL:
- tcc_error("_Thread_local is not implemented");
- default:
- if (typespec_found)
- goto the_end;
- s = sym_find(tok);
- if (!s || !(s->type.t & VT_TYPEDEF))
- goto the_end;
-
- n = tok, next();
- if (tok == ':' && ignore_label) {
- /* ignore if it's a label */
- unget_tok(n);
- goto the_end;
- }
-
- t &= ~(VT_BTYPE|VT_LONG);
- u = t & ~(VT_CONSTANT | VT_VOLATILE), t ^= u;
- type->t = (s->type.t & ~VT_TYPEDEF) | u;
- type->ref = s->type.ref;
- if (t)
- parse_btype_qualify(type, t);
- t = type->t;
- /* get attributes from typedef */
- sym_to_attr(ad, s);
- typespec_found = 1;
- st = bt = -2;
- break;
- }
- type_found = 1;
- }
-the_end:
- if (tcc_state->char_is_unsigned) {
- if ((t & (VT_DEFSIGN|VT_BTYPE)) == VT_BYTE)
- t |= VT_UNSIGNED;
- }
- /* VT_LONG is used just as a modifier for VT_INT / VT_LLONG */
- bt = t & (VT_BTYPE|VT_LONG);
- if (bt == VT_LONG)
- t |= LONG_SIZE == 8 ? VT_LLONG : VT_INT;
-#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE
- if (bt == VT_LDOUBLE)
- t = (t & ~(VT_BTYPE|VT_LONG)) | (VT_DOUBLE|VT_LONG);
-#endif
- type->t = t;
- return type_found;
-}
-
-/* convert a function parameter type (array to pointer and function to
- function pointer) */
-static inline void convert_parameter_type(CType *pt)
-{
- /* remove const and volatile qualifiers (XXX: const could be used
- to indicate a const function parameter */
- pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
- /* array must be transformed to pointer according to ANSI C */
- pt->t &= ~VT_ARRAY;
- if ((pt->t & VT_BTYPE) == VT_FUNC) {
- mk_pointer(pt);
- }
-}
-
-ST_FUNC CString* parse_asm_str(void)
-{
- skip('(');
- return parse_mult_str("string constant");
-}
-
-/* Parse an asm label and return the token */
-static int asm_label_instr(void)
-{
- int v;
- char *astr;
-
- next();
- astr = parse_asm_str()->data;
- skip(')');
-#ifdef ASM_DEBUG
- printf("asm_alias: \"%s\"\n", astr);
-#endif
- v = tok_alloc_const(astr);
- return v;
-}
-
-static int post_type(CType *type, AttributeDef *ad, int storage, int td)
-{
- int n, l, t1, arg_size, align;
- Sym **plast, *s, *first;
- AttributeDef ad1;
- CType pt;
- TokenString *vla_array_tok = NULL;
- int *vla_array_str = NULL;
-
- if (tok == '(') {
- /* function type, or recursive declarator (return if so) */
- next();
- if (TYPE_DIRECT == (td & (TYPE_DIRECT|TYPE_ABSTRACT)))
- return 0;
- if (tok == ')')
- l = 0;
- else if (parse_btype(&pt, &ad1, 0))
- l = FUNC_NEW;
- else if (td & (TYPE_DIRECT|TYPE_ABSTRACT)) {
- merge_attr (ad, &ad1);
- return 0;
- } else
- l = FUNC_OLD;
-
- first = NULL;
- plast = &first;
- arg_size = 0;
- ++local_scope;
- if (l) {
- for(;;) {
- /* read param name and compute offset */
- if (l != FUNC_OLD) {
- if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
- break;
- type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT | TYPE_PARAM);
- if ((pt.t & VT_BTYPE) == VT_VOID)
- tcc_error("parameter declared as void");
- if (n == 0)
- n = SYM_FIELD;
- } else {
- n = tok;
- pt.t = VT_VOID; /* invalid type */
- pt.ref = NULL;
- next();
- }
- if (n < TOK_UIDENT)
- expect("identifier");
- convert_parameter_type(&pt);
- arg_size += (type_size(&pt, &align) + PTR_SIZE - 1) / PTR_SIZE;
- /* these symbols may be evaluated for VLArrays (see below, under
- nocode_wanted) which is why we push them here as normal symbols
- temporarily. Example: int func(int a, int b[++a]); */
- s = sym_push(n, &pt, VT_LOCAL|VT_LVAL, 0);
- *plast = s;
- plast = &s->next;
- if (tok == ')')
- break;
- skip(',');
- if (l == FUNC_NEW && tok == TOK_DOTS) {
- l = FUNC_ELLIPSIS;
- next();
- break;
- }
- if (l == FUNC_NEW && !parse_btype(&pt, &ad1, 0))
- tcc_error("invalid type");
- }
- } else
- /* if no parameters, then old type prototype */
- l = FUNC_OLD;
- skip(')');
- /* remove parameter symbols from token table, keep on stack */
- if (first) {
- sym_pop(local_stack ? &local_stack : &global_stack, first->prev, 1);
- for (s = first; s; s = s->next)
- s->v |= SYM_FIELD;
- }
- --local_scope;
- /* NOTE: const is ignored in returned type as it has a special
- meaning in gcc / C++ */
- type->t &= ~VT_CONSTANT;
- /* some ancient pre-K&R C allows a function to return an array
- and the array brackets to be put after the arguments, such
- that "int c()[]" means something like "int[] c()" */
- if (tok == '[') {
- next();
- skip(']'); /* only handle simple "[]" */
- mk_pointer(type);
- }
- /* we push a anonymous symbol which will contain the function prototype */
- ad->f.func_args = arg_size;
- ad->f.func_type = l;
- s = sym_push(SYM_FIELD, type, 0, 0);
- s->a = ad->a;
- s->f = ad->f;
- s->next = first;
- type->t = VT_FUNC;
- type->ref = s;
- } else if (tok == '[') {
- int saved_nocode_wanted = nocode_wanted;
- /* array definition */
- next();
- n = -1;
- t1 = 0;
- if (td & TYPE_PARAM) while (1) {
- /* XXX The optional type-quals and static should only be accepted
- in parameter decls. The '*' as well, and then even only
- in prototypes (not function defs). */
- switch (tok) {
- case TOK_RESTRICT1: case TOK_RESTRICT2: case TOK_RESTRICT3:
- case TOK_CONST1:
- case TOK_VOLATILE1:
- case TOK_STATIC:
- case '*':
- next();
- continue;
- default:
- break;
- }
- if (tok != ']') {
- /* Code generation is not done now but has to be done
- at start of function. Save code here for later use. */
- nocode_wanted = 1;
- skip_or_save_block(&vla_array_tok);
- unget_tok(0);
- vla_array_str = vla_array_tok->str;
- begin_macro(vla_array_tok, 2);
- next();
- gexpr();
- end_macro();
- next();
- goto check;
- }
- break;
-
- } else if (tok != ']') {
- if (!local_stack || (storage & VT_STATIC))
- vpushi(expr_const());
- else {
- /* VLAs (which can only happen with local_stack && !VT_STATIC)
- length must always be evaluated, even under nocode_wanted,
- so that its size slot is initialized (e.g. under sizeof
- or typeof). */
- nocode_wanted = 0;
- gexpr();
- }
-check:
- if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
- n = vtop->c.i;
- if (n < 0)
- tcc_error("invalid array size");
- } else {
- if (!is_integer_btype(vtop->type.t & VT_BTYPE))
- tcc_error("size of variable length array should be an integer");
- n = 0;
- t1 = VT_VLA;
- }
- }
- skip(']');
- /* parse next post type */
- post_type(type, ad, storage, (td & ~(TYPE_DIRECT|TYPE_ABSTRACT)) | TYPE_NEST);
-
- if ((type->t & VT_BTYPE) == VT_FUNC)
- tcc_error("declaration of an array of functions");
- if ((type->t & VT_BTYPE) == VT_VOID
- || type_size(type, &align) < 0)
- tcc_error("declaration of an array of incomplete type elements");
-
- t1 |= type->t & VT_VLA;
-
- if (t1 & VT_VLA) {
- if (n < 0) {
- if (td & TYPE_NEST)
- tcc_error("need explicit inner array size in VLAs");
- }
- else {
- loc -= type_size(&int_type, &align);
- loc &= -align;
- n = loc;
-
- vpush_type_size(type, &align);
- gen_op('*');
- vset(&int_type, VT_LOCAL|VT_LVAL, n);
- vswap();
- vstore();
- }
- }
- if (n != -1)
- vpop();
- nocode_wanted = saved_nocode_wanted;
-
- /* we push an anonymous symbol which will contain the array
- element type */
- s = sym_push(SYM_FIELD, type, 0, n);
- type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR;
- type->ref = s;
-
- if (vla_array_str) {
- if (t1 & VT_VLA)
- s->vla_array_str = vla_array_str;
- else
- tok_str_free_str(vla_array_str);
- }
- }
- return 1;
-}
-
-/* Parse a type declarator (except basic type), and return the type
- in 'type'. 'td' is a bitmask indicating which kind of type decl is
- expected. 'type' should contain the basic type. 'ad' is the
- attribute definition of the basic type. It can be modified by
- type_decl(). If this (possibly abstract) declarator is a pointer chain
- it returns the innermost pointed to type (equals *type, but is a different
- pointer), otherwise returns type itself, that's used for recursive calls. */
-static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
-{
- CType *post, *ret;
- int qualifiers, storage;
-
- /* recursive type, remove storage bits first, apply them later again */
- storage = type->t & VT_STORAGE;
- type->t &= ~VT_STORAGE;
- post = ret = type;
-
- while (tok == '*') {
- qualifiers = 0;
- redo:
- next();
- switch(tok) {
- case TOK__Atomic:
- qualifiers |= VT_ATOMIC;
- goto redo;
- case TOK_CONST1:
- case TOK_CONST2:
- case TOK_CONST3:
- qualifiers |= VT_CONSTANT;
- goto redo;
- case TOK_VOLATILE1:
- case TOK_VOLATILE2:
- case TOK_VOLATILE3:
- qualifiers |= VT_VOLATILE;
- goto redo;
- case TOK_RESTRICT1:
- case TOK_RESTRICT2:
- case TOK_RESTRICT3:
- goto redo;
- /* XXX: clarify attribute handling */
- case TOK_ATTRIBUTE1:
- case TOK_ATTRIBUTE2:
- parse_attribute(ad);
- break;
- }
- mk_pointer(type);
- type->t |= qualifiers;
- if (ret == type)
- /* innermost pointed to type is the one for the first derivation */
- ret = pointed_type(type);
- }
-
- if (tok == '(') {
- /* This is possibly a parameter type list for abstract declarators
- ('int ()'), use post_type for testing this. */
- if (!post_type(type, ad, 0, td)) {
- /* It's not, so it's a nested declarator, and the post operations
- apply to the innermost pointed to type (if any). */
- /* XXX: this is not correct to modify 'ad' at this point, but
- the syntax is not clear */
- parse_attribute(ad);
- post = type_decl(type, ad, v, td);
- skip(')');
- } else
- goto abstract;
- } else if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
- /* type identifier */
- *v = tok;
- next();
- } else {
- abstract:
- if (!(td & TYPE_ABSTRACT))
- expect("identifier");
- *v = 0;
- }
- post_type(post, ad, post != ret ? 0 : storage,
- td & ~(TYPE_DIRECT|TYPE_ABSTRACT));
- parse_attribute(ad);
- type->t |= storage;
- return ret;
-}
-
-/* indirection with full error checking and bound check */
-ST_FUNC void indir(void)
-{
- if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
- if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
- return;
- expect("pointer");
- }
- if (vtop->r & VT_LVAL)
- gv(RC_INT);
- vtop->type = *pointed_type(&vtop->type);
- /* Arrays and functions are never lvalues */
- if (!(vtop->type.t & (VT_ARRAY | VT_VLA))
- && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
- vtop->r |= VT_LVAL;
- /* if bound checking, the referenced pointer must be checked */
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- vtop->r |= VT_MUSTBOUND;
-#endif
- }
-}
-
-/* pass a parameter to a function and do type checking and casting */
-static void gfunc_param_typed(Sym *func, Sym *arg)
-{
- int func_type;
- CType type;
-
- func_type = func->f.func_type;
- if (func_type == FUNC_OLD ||
- (func_type == FUNC_ELLIPSIS && arg == NULL)) {
- /* default casting : only need to convert float to double */
- if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
- gen_cast_s(VT_DOUBLE);
- } else if (vtop->type.t & VT_BITFIELD) {
- type.t = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
- type.ref = vtop->type.ref;
- gen_cast(&type);
- } else if (vtop->r & VT_MUSTCAST) {
- force_charshort_cast();
- }
- } else if (arg == NULL) {
- tcc_error("too many arguments to function");
- } else {
- type = arg->type;
- type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
- gen_assign_cast(&type);
- }
-}
-
-/* parse an expression and return its type without any side effect. */
-static void expr_type(CType *type, void (*expr_fn)(void))
-{
- nocode_wanted++;
- expr_fn();
- *type = vtop->type;
- vpop();
- nocode_wanted--;
-}
-
-/* parse an expression of the form '(type)' or '(expr)' and return its
- type */
-static void parse_expr_type(CType *type)
-{
- int n;
- AttributeDef ad;
-
- skip('(');
- if (parse_btype(type, &ad, 0)) {
- type_decl(type, &ad, &n, TYPE_ABSTRACT);
- } else {
- expr_type(type, gexpr);
- }
- skip(')');
-}
-
-static void parse_type(CType *type)
-{
- AttributeDef ad;
- int n;
-
- if (!parse_btype(type, &ad, 0)) {
- expect("type");
- }
- type_decl(type, &ad, &n, TYPE_ABSTRACT);
-}
-
-static void parse_builtin_params(int nc, const char *args)
-{
- char c, sep = '(';
- CType type;
- if (nc)
- nocode_wanted++;
- next();
- if (*args == 0)
- skip(sep);
- while ((c = *args++)) {
- skip(sep);
- sep = ',';
- if (c == 't') {
- parse_type(&type);
- vpush(&type);
- continue;
- }
- expr_eq();
- type.ref = NULL;
- type.t = 0;
- switch (c) {
- case 'e':
- continue;
- case 'V':
- type.t = VT_CONSTANT;
- case 'v':
- type.t |= VT_VOID;
- mk_pointer (&type);
- break;
- case 'S':
- type.t = VT_CONSTANT;
- case 's':
- type.t |= char_type.t;
- mk_pointer (&type);
- break;
- case 'i':
- type.t = VT_INT;
- break;
- case 'l':
- type.t = VT_SIZE_T;
- break;
- default:
- break;
- }
- gen_assign_cast(&type);
- }
- skip(')');
- if (nc)
- nocode_wanted--;
-}
-
-static void parse_atomic(int atok)
-{
- int size, align, arg, t, save = 0;
- CType *atom, *atom_ptr, ct = {0};
- SValue store;
- char buf[40];
- static const char *const templates[] = {
- /*
- * Each entry consists of callback and function template.
- * The template represents argument types and return type.
- *
- * ? void (return-only)
- * b bool
- * a atomic
- * A read-only atomic
- * p pointer to memory
- * v value
- * l load pointer
- * s save pointer
- * m memory model
- */
-
- /* keep in order of appearance in tcctok.h: */
- /* __atomic_store */ "alm.?",
- /* __atomic_load */ "Asm.v",
- /* __atomic_exchange */ "alsm.v",
- /* __atomic_compare_exchange */ "aplbmm.b",
- /* __atomic_fetch_add */ "avm.v",
- /* __atomic_fetch_sub */ "avm.v",
- /* __atomic_fetch_or */ "avm.v",
- /* __atomic_fetch_xor */ "avm.v",
- /* __atomic_fetch_and */ "avm.v",
- /* __atomic_fetch_nand */ "avm.v",
- /* __atomic_and_fetch */ "avm.v",
- /* __atomic_sub_fetch */ "avm.v",
- /* __atomic_or_fetch */ "avm.v",
- /* __atomic_xor_fetch */ "avm.v",
- /* __atomic_and_fetch */ "avm.v",
- /* __atomic_nand_fetch */ "avm.v"
- };
- const char *template = templates[(atok - TOK___atomic_store)];
-
- atom = atom_ptr = NULL;
- size = 0; /* pacify compiler */
- next();
- skip('(');
- for (arg = 0;;) {
- expr_eq();
- switch (template[arg]) {
- case 'a':
- case 'A':
- atom_ptr = &vtop->type;
- if ((atom_ptr->t & VT_BTYPE) != VT_PTR)
- expect("pointer");
- atom = pointed_type(atom_ptr);
- size = type_size(atom, &align);
- if (size > 8
- || (size & (size - 1))
- || (atok > TOK___atomic_compare_exchange
- && (0 == btype_size(atom->t & VT_BTYPE)
- || (atom->t & VT_BTYPE) == VT_PTR)))
- expect("integral or integer-sized pointer target type");
- /* GCC does not care either: */
- /* if (!(atom->t & VT_ATOMIC))
- tcc_warning("pointer target declaration is missing '_Atomic'"); */
- break;
-
- case 'p':
- if ((vtop->type.t & VT_BTYPE) != VT_PTR
- || type_size(pointed_type(&vtop->type), &align) != size)
- tcc_error("pointer target type mismatch in argument %d", arg + 1);
- gen_assign_cast(atom_ptr);
- break;
- case 'v':
- gen_assign_cast(atom);
- break;
- case 'l':
- indir();
- gen_assign_cast(atom);
- break;
- case 's':
- save = 1;
- indir();
- store = *vtop;
- vpop();
- break;
- case 'm':
- gen_assign_cast(&int_type);
- break;
- case 'b':
- ct.t = VT_BOOL;
- gen_assign_cast(&ct);
- break;
- }
- if ('.' == template[++arg])
- break;
- skip(',');
- }
- skip(')');
-
- ct.t = VT_VOID;
- switch (template[arg + 1]) {
- case 'b':
- ct.t = VT_BOOL;
- break;
- case 'v':
- ct = *atom;
- break;
- }
-
- sprintf(buf, "%s_%d", get_tok_str(atok, 0), size);
- vpush_helper_func(tok_alloc_const(buf));
- vrott(arg - save + 1);
- gfunc_call(arg - save);
-
- vpush(&ct);
- PUT_R_RET(vtop, ct.t);
- t = ct.t & VT_BTYPE;
- if (t == VT_BYTE || t == VT_SHORT || t == VT_BOOL) {
-#ifdef PROMOTE_RET
- vtop->r |= BFVAL(VT_MUSTCAST, 1);
-#else
- vtop->type.t = VT_INT;
-#endif
- }
- gen_cast(&ct);
- if (save) {
- vpush(&ct);
- *vtop = store;
- vswap();
- vstore();
- }
-}
-
-ST_FUNC void unary(void)
-{
- int n, t, align, size, r, sizeof_caller;
- CType type;
- Sym *s;
- AttributeDef ad;
-
- /* generate line number info */
- if (debug_modes)
- tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
-
- sizeof_caller = in_sizeof;
- in_sizeof = 0;
- type.ref = NULL;
- /* XXX: GCC 2.95.3 does not generate a table although it should be
- better here */
- tok_next:
- switch(tok) {
- case TOK_EXTENSION:
- next();
- goto tok_next;
- case TOK_LCHAR:
-#ifdef TCC_TARGET_PE
- t = VT_SHORT|VT_UNSIGNED;
- goto push_tokc;
-#endif
- case TOK_CINT:
- case TOK_CCHAR:
- t = VT_INT;
- push_tokc:
- type.t = t;
- vsetc(&type, VT_CONST, &tokc);
- next();
- break;
- case TOK_CUINT:
- t = VT_INT | VT_UNSIGNED;
- goto push_tokc;
- case TOK_CLLONG:
- t = VT_LLONG;
- goto push_tokc;
- case TOK_CULLONG:
- t = VT_LLONG | VT_UNSIGNED;
- goto push_tokc;
- case TOK_CFLOAT:
- t = VT_FLOAT;
- goto push_tokc;
- case TOK_CDOUBLE:
- t = VT_DOUBLE;
- goto push_tokc;
- case TOK_CLDOUBLE:
-#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE
- t = VT_DOUBLE | VT_LONG;
-#else
- t = VT_LDOUBLE;
-#endif
- goto push_tokc;
- case TOK_CLONG:
- t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG;
- goto push_tokc;
- case TOK_CULONG:
- t = (LONG_SIZE == 8 ? VT_LLONG : VT_INT) | VT_LONG | VT_UNSIGNED;
- goto push_tokc;
- case TOK___FUNCTION__:
- if (!gnu_ext)
- goto tok_identifier;
- /* fall thru */
- case TOK___FUNC__:
- {
- Section *sec;
- int len;
- /* special function name identifier */
- len = strlen(funcname) + 1;
- /* generate char[len] type */
- type.t = char_type.t;
- if (tcc_state->warn_write_strings & WARN_ON)
- type.t |= VT_CONSTANT;
- mk_pointer(&type);
- type.t |= VT_ARRAY;
- type.ref->c = len;
- sec = rodata_section;
- vpush_ref(&type, sec, sec->data_offset, len);
- if (!NODATA_WANTED)
- memcpy(section_ptr_add(sec, len), funcname, len);
- next();
- }
- break;
- case TOK_LSTR:
-#ifdef TCC_TARGET_PE
- t = VT_SHORT | VT_UNSIGNED;
-#else
- t = VT_INT;
-#endif
- goto str_init;
- case TOK_STR:
- /* string parsing */
- t = char_type.t;
- str_init:
- if (tcc_state->warn_write_strings & WARN_ON)
- t |= VT_CONSTANT;
- type.t = t;
- mk_pointer(&type);
- type.t |= VT_ARRAY;
- memset(&ad, 0, sizeof(AttributeDef));
- ad.section = rodata_section;
- decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
- break;
- case '(':
- next();
- /* cast ? */
- if (parse_btype(&type, &ad, 0)) {
- type_decl(&type, &ad, &n, TYPE_ABSTRACT);
- skip(')');
- /* check ISOC99 compound literal */
- if (tok == '{') {
- /* data is allocated locally by default */
- if (global_expr)
- r = VT_CONST;
- else
- r = VT_LOCAL;
- /* all except arrays are lvalues */
- if (!(type.t & VT_ARRAY))
- r |= VT_LVAL;
- memset(&ad, 0, sizeof(AttributeDef));
- decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
- } else {
- if (sizeof_caller) {
- vpush(&type);
- return;
- }
- unary();
- gen_cast(&type);
- }
- } else if (tok == '{') {
- int saved_nocode_wanted = nocode_wanted;
- if (CONST_WANTED && !NOEVAL_WANTED)
- expect("constant");
- if (0 == local_scope)
- tcc_error("statement expression outside of function");
- /* save all registers */
- save_regs(0);
- /* statement expression : we do not accept break/continue
- inside as GCC does. We do retain the nocode_wanted state,
- as statement expressions can't ever be entered from the
- outside, so any reactivation of code emission (from labels
- or loop heads) can be disabled again after the end of it. */
- block(1);
- /* If the statement expr can be entered, then we retain the current
- nocode_wanted state (from e.g. a 'return 0;' in the stmt-expr).
- If it can't be entered then the state is that from before the
- statement expression. */
- if (saved_nocode_wanted)
- nocode_wanted = saved_nocode_wanted;
- skip(')');
- } else {
- gexpr();
- skip(')');
- }
- break;
- case '*':
- next();
- unary();
- indir();
- break;
- case '&':
- next();
- unary();
- /* functions names must be treated as function pointers,
- except for unary '&' and sizeof. Since we consider that
- functions are not lvalues, we only have to handle it
- there and in function calls. */
- /* arrays can also be used although they are not lvalues */
- if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
- !(vtop->type.t & (VT_ARRAY | VT_VLA)))
- test_lvalue();
- if (vtop->sym)
- vtop->sym->a.addrtaken = 1;
- mk_pointer(&vtop->type);
- gaddrof();
- break;
- case '!':
- next();
- unary();
- gen_test_zero(TOK_EQ);
- break;
- case '~':
- next();
- unary();
- vpushi(-1);
- gen_op('^');
- break;
- case '+':
- next();
- unary();
- if ((vtop->type.t & VT_BTYPE) == VT_PTR)
- tcc_error("pointer not accepted for unary plus");
- /* In order to force cast, we add zero, except for floating point
- where we really need an noop (otherwise -0.0 will be transformed
- into +0.0). */
- if (!is_float(vtop->type.t)) {
- vpushi(0);
- gen_op('+');
- }
- break;
- case TOK_SIZEOF:
- case TOK_ALIGNOF1:
- case TOK_ALIGNOF2:
- case TOK_ALIGNOF3:
- t = tok;
- next();
- in_sizeof++;
- expr_type(&type, unary); /* Perform a in_sizeof = 0; */
- if (t == TOK_SIZEOF) {
- vpush_type_size(&type, &align);
- gen_cast_s(VT_SIZE_T);
- } else {
- type_size(&type, &align);
- s = NULL;
- if (vtop[1].r & VT_SYM)
- s = vtop[1].sym; /* hack: accessing previous vtop */
- if (s && s->a.aligned)
- align = 1 << (s->a.aligned - 1);
- vpushs(align);
- }
- break;
-
- case TOK_builtin_expect:
- /* __builtin_expect is a no-op for now */
- parse_builtin_params(0, "ee");
- vpop();
- break;
- case TOK_builtin_types_compatible_p:
- parse_builtin_params(0, "tt");
- vtop[-1].type.t &= ~(VT_CONSTANT | VT_VOLATILE);
- vtop[0].type.t &= ~(VT_CONSTANT | VT_VOLATILE);
- n = is_compatible_types(&vtop[-1].type, &vtop[0].type);
- vtop -= 2;
- vpushi(n);
- break;
- case TOK_builtin_choose_expr:
- {
- int64_t c;
- next();
- skip('(');
- c = expr_const64();
- skip(',');
- if (!c) {
- nocode_wanted++;
- }
- expr_eq();
- if (!c) {
- vpop();
- nocode_wanted--;
- }
- skip(',');
- if (c) {
- nocode_wanted++;
- }
- expr_eq();
- if (c) {
- vpop();
- nocode_wanted--;
- }
- skip(')');
- }
- break;
- case TOK_builtin_constant_p:
- constant_p = 1;
- parse_builtin_params(1, "e");
- n = constant_p &&
- (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
- !((vtop->r & VT_SYM) && vtop->sym->a.addrtaken);
- vtop--;
- vpushi(n);
- break;
- case TOK_builtin_frame_address:
- case TOK_builtin_return_address:
- {
- int tok1 = tok;
- int64_t level;
- next();
- skip('(');
- level = expr_const64();
- if (level < 0) {
- tcc_error("%s only takes positive integers",
- tok1 == TOK_builtin_return_address ?
- "__builtin_return_address" :
- "__builtin_frame_address");
- }
- skip(')');
- type.t = VT_VOID;
- mk_pointer(&type);
- vset(&type, VT_LOCAL, 0); /* local frame */
- while (level--) {
-#ifdef TCC_TARGET_RISCV64
- vpushi(2*PTR_SIZE);
- gen_op('-');
-#endif
- mk_pointer(&vtop->type);
- indir(); /* -> parent frame */
- }
- if (tok1 == TOK_builtin_return_address) {
- // assume return address is just above frame pointer on stack
-#ifdef TCC_TARGET_ARM
- vpushi(2*PTR_SIZE);
- gen_op('+');
-#elif defined TCC_TARGET_RISCV64
- vpushi(PTR_SIZE);
- gen_op('-');
-#else
- vpushi(PTR_SIZE);
- gen_op('+');
-#endif
- mk_pointer(&vtop->type);
- indir();
- }
- }
- break;
-#ifdef TCC_TARGET_RISCV64
- case TOK_builtin_va_start:
- parse_builtin_params(0, "ee");
- r = vtop->r & VT_VALMASK;
- if (r == VT_LLOCAL)
- r = VT_LOCAL;
- if (r != VT_LOCAL)
- tcc_error("__builtin_va_start expects a local variable");
- gen_va_start();
- vstore();
- break;
-#endif
-#ifdef TCC_TARGET_X86_64
-#ifdef TCC_TARGET_PE
- case TOK_builtin_va_start:
- parse_builtin_params(0, "ee");
- r = vtop->r & VT_VALMASK;
- if (r == VT_LLOCAL)
- r = VT_LOCAL;
- if (r != VT_LOCAL)
- tcc_error("__builtin_va_start expects a local variable");
- vtop->r = r;
- vtop->type = char_pointer_type;
- vtop->c.i += 8;
- vstore();
- break;
-#else
- case TOK_builtin_va_arg_types:
- parse_builtin_params(0, "t");
- vpushi(classify_x86_64_va_arg(&vtop->type));
- vswap();
- vpop();
- break;
-#endif
-#endif
-
-#ifdef TCC_TARGET_ARM64
- case TOK_builtin_va_start: {
- parse_builtin_params(0, "ee");
- //xx check types
- gen_va_start();
- vpushi(0);
- vtop->type.t = VT_VOID;
- break;
- }
- case TOK_builtin_va_arg: {
- parse_builtin_params(0, "et");
- type = vtop->type;
- vpop();
- //xx check types
- gen_va_arg(&type);
- vtop->type = type;
- break;
- }
- case TOK___arm64_clear_cache: {
- parse_builtin_params(0, "ee");
- gen_clear_cache();
- vpushi(0);
- vtop->type.t = VT_VOID;
- break;
- }
-#endif
-
- /* atomic operations */
- case TOK___atomic_store:
- case TOK___atomic_load:
- case TOK___atomic_exchange:
- case TOK___atomic_compare_exchange:
- case TOK___atomic_fetch_add:
- case TOK___atomic_fetch_sub:
- case TOK___atomic_fetch_or:
- case TOK___atomic_fetch_xor:
- case TOK___atomic_fetch_and:
- case TOK___atomic_fetch_nand:
- case TOK___atomic_add_fetch:
- case TOK___atomic_sub_fetch:
- case TOK___atomic_or_fetch:
- case TOK___atomic_xor_fetch:
- case TOK___atomic_and_fetch:
- case TOK___atomic_nand_fetch:
- parse_atomic(tok);
- break;
-
- /* pre operations */
- case TOK_INC:
- case TOK_DEC:
- t = tok;
- next();
- unary();
- inc(0, t);
- break;
- case '-':
- next();
- unary();
- if (is_float(vtop->type.t)) {
- gen_opif(TOK_NEG);
- } else {
- vpushi(0);
- vswap();
- gen_op('-');
- }
- break;
- case TOK_LAND:
- if (!gnu_ext)
- goto tok_identifier;
- next();
- /* allow to take the address of a label */
- if (tok < TOK_UIDENT)
- expect("label identifier");
- s = label_find(tok);
- if (!s) {
- s = label_push(&global_label_stack, tok, LABEL_FORWARD);
- } else {
- if (s->r == LABEL_DECLARED)
- s->r = LABEL_FORWARD;
- }
- if ((s->type.t & VT_BTYPE) != VT_PTR) {
- s->type.t = VT_VOID;
- mk_pointer(&s->type);
- s->type.t |= VT_STATIC;
- }
- vpushsym(&s->type, s);
- next();
- break;
-
- case TOK_GENERIC:
- {
- CType controlling_type;
- int has_default = 0;
- int has_match = 0;
- int learn = 0;
- TokenString *str = NULL;
- int saved_nocode_wanted = nocode_wanted;
- nocode_wanted &= ~CONST_WANTED_MASK;
-
- next();
- skip('(');
- expr_type(&controlling_type, expr_eq);
- controlling_type.t &= ~(VT_CONSTANT | VT_VOLATILE | VT_ARRAY);
- if ((controlling_type.t & VT_BTYPE) == VT_FUNC)
- mk_pointer(&controlling_type);
-
- nocode_wanted = saved_nocode_wanted;
-
- for (;;) {
- learn = 0;
- skip(',');
- if (tok == TOK_DEFAULT) {
- if (has_default)
- tcc_error("too many 'default'");
- has_default = 1;
- if (!has_match)
- learn = 1;
- next();
- } else {
- AttributeDef ad_tmp;
- int itmp;
- CType cur_type;
-
- parse_btype(&cur_type, &ad_tmp, 0);
- type_decl(&cur_type, &ad_tmp, &itmp, TYPE_ABSTRACT);
- if (compare_types(&controlling_type, &cur_type, 0)) {
- if (has_match) {
- tcc_error("type match twice");
- }
- has_match = 1;
- learn = 1;
- }
- }
- skip(':');
- if (learn) {
- if (str)
- tok_str_free(str);
- skip_or_save_block(&str);
- } else {
- skip_or_save_block(NULL);
- }
- if (tok == ')')
- break;
- }
- if (!str) {
- char buf[60];
- type_to_str(buf, sizeof buf, &controlling_type, NULL);
- tcc_error("type '%s' does not match any association", buf);
- }
- begin_macro(str, 1);
- next();
- expr_eq();
- if (tok != TOK_EOF)
- expect(",");
- end_macro();
- next();
- break;
- }
- // special qnan , snan and infinity values
- case TOK___NAN__:
- n = 0x7fc00000;
-special_math_val:
- vpushi(n);
- vtop->type.t = VT_FLOAT;
- next();
- break;
- case TOK___SNAN__:
- n = 0x7f800001;
- goto special_math_val;
- case TOK___INF__:
- n = 0x7f800000;
- goto special_math_val;
-
- default:
- tok_identifier:
- t = tok;
- next();
- if (t < TOK_UIDENT)
- expect("identifier");
- s = sym_find(t);
- if (!s || IS_ASM_SYM(s)) {
- const char *name = get_tok_str(t, NULL);
- if (tok != '(')
- tcc_error("'%s' undeclared", name);
- /* for simple function calls, we tolerate undeclared
- external reference to int() function */
- tcc_warning_c(warn_implicit_function_declaration)(
- "implicit declaration of function '%s'", name);
- s = external_global_sym(t, &func_old_type);
- }
-
- r = s->r;
- /* A symbol that has a register is a local register variable,
- which starts out as VT_LOCAL value. */
- if ((r & VT_VALMASK) < VT_CONST)
- r = (r & ~VT_VALMASK) | VT_LOCAL;
-
- vset(&s->type, r, s->c);
- /* Point to s as backpointer (even without r&VT_SYM).
- Will be used by at least the x86 inline asm parser for
- regvars. */
- vtop->sym = s;
-
- if (r & VT_SYM) {
- vtop->c.i = 0;
- } else if (r == VT_CONST && IS_ENUM_VAL(s->type.t)) {
- vtop->c.i = s->enum_val;
- }
- break;
- }
-
- /* post operations */
- while (1) {
- if (tok == TOK_INC || tok == TOK_DEC) {
- inc(1, tok);
- next();
- } else if (tok == '.' || tok == TOK_ARROW || tok == TOK_CDOUBLE) {
- int qualifiers, cumofs = 0;
- /* field */
- if (tok == TOK_ARROW)
- indir();
- qualifiers = vtop->type.t & (VT_CONSTANT | VT_VOLATILE);
- test_lvalue();
- gaddrof();
- /* expect pointer on structure */
- if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
- expect("struct or union");
- if (tok == TOK_CDOUBLE)
- expect("field name");
- next();
- if (tok == TOK_CINT || tok == TOK_CUINT)
- expect("field name");
- s = find_field(&vtop->type, tok, &cumofs);
- /* add field offset to pointer */
- vtop->type = char_pointer_type; /* change type to 'char *' */
- vpushi(cumofs);
- gen_op('+');
- /* change type to field type, and set to lvalue */
- vtop->type = s->type;
- vtop->type.t |= qualifiers;
- /* an array is never an lvalue */
- if (!(vtop->type.t & VT_ARRAY)) {
- vtop->r |= VT_LVAL;
-#ifdef CONFIG_TCC_BCHECK
- /* if bound checking, the referenced pointer must be checked */
- if (tcc_state->do_bounds_check)
- vtop->r |= VT_MUSTBOUND;
-#endif
- }
- next();
- } else if (tok == '[') {
- next();
- gexpr();
- gen_op('+');
- indir();
- skip(']');
- } else if (tok == '(') {
- SValue ret;
- Sym *sa;
- int nb_args, ret_nregs, ret_align, regsize, variadic;
-
- /* function call */
- if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
- /* pointer test (no array accepted) */
- if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
- vtop->type = *pointed_type(&vtop->type);
- if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
- goto error_func;
- } else {
- error_func:
- expect("function pointer");
- }
- } else {
- vtop->r &= ~VT_LVAL; /* no lvalue */
- }
- /* get return type */
- s = vtop->type.ref;
- next();
- sa = s->next; /* first parameter */
- nb_args = regsize = 0;
- ret.r2 = VT_CONST;
- /* compute first implicit argument if a structure is returned */
- if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
- variadic = (s->f.func_type == FUNC_ELLIPSIS);
- ret_nregs = gfunc_sret(&s->type, variadic, &ret.type,
- &ret_align, &regsize);
- if (ret_nregs <= 0) {
- /* get some space for the returned structure */
- size = type_size(&s->type, &align);
-#ifdef TCC_TARGET_ARM64
- /* On arm64, a small struct is return in registers.
- It is much easier to write it to memory if we know
- that we are allowed to write some extra bytes, so
- round the allocated space up to a power of 2: */
- if (size < 16)
- while (size & (size - 1))
- size = (size | (size - 1)) + 1;
-#endif
- loc = (loc - size) & -align;
- ret.type = s->type;
- ret.r = VT_LOCAL | VT_LVAL;
- /* pass it as 'int' to avoid structure arg passing
- problems */
- vseti(VT_LOCAL, loc);
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- --loc;
-#endif
- ret.c = vtop->c;
- if (ret_nregs < 0)
- vtop--;
- else
- nb_args++;
- }
- } else {
- ret_nregs = 1;
- ret.type = s->type;
- }
-
- if (ret_nregs > 0) {
- /* return in register */
- ret.c.i = 0;
- PUT_R_RET(&ret, ret.type.t);
- }
- if (tok != ')') {
- for(;;) {
- expr_eq();
- gfunc_param_typed(s, sa);
- nb_args++;
- if (sa)
- sa = sa->next;
- if (tok == ')')
- break;
- skip(',');
- }
- }
- if (sa)
- tcc_error("too few arguments to function");
- skip(')');
- gfunc_call(nb_args);
-
- if (ret_nregs < 0) {
- vsetc(&ret.type, ret.r, &ret.c);
-#ifdef TCC_TARGET_RISCV64
- arch_transfer_ret_regs(1);
-#endif
- } else {
- /* return value */
- for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) {
- vsetc(&ret.type, r, &ret.c);
- vtop->r2 = ret.r2; /* Loop only happens when r2 is VT_CONST */
- }
-
- /* handle packed struct return */
- if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) {
- int addr, offset;
-
- size = type_size(&s->type, &align);
- /* We're writing whole regs often, make sure there's enough
- space. Assume register size is power of 2. */
- if (regsize > align)
- align = regsize;
- loc = (loc - size) & -align;
- addr = loc;
- offset = 0;
- for (;;) {
- vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset);
- vswap();
- vstore();
- vtop--;
- if (--ret_nregs == 0)
- break;
- offset += regsize;
- }
- vset(&s->type, VT_LOCAL | VT_LVAL, addr);
- }
-
- /* Promote char/short return values. This is matters only
- for calling function that were not compiled by TCC and
- only on some architectures. For those where it doesn't
- matter we expect things to be already promoted to int,
- but not larger. */
- t = s->type.t & VT_BTYPE;
- if (t == VT_BYTE || t == VT_SHORT || t == VT_BOOL) {
-#ifdef PROMOTE_RET
- vtop->r |= BFVAL(VT_MUSTCAST, 1);
-#else
- vtop->type.t = VT_INT;
-#endif
- }
- }
- if (s->f.func_noreturn) {
- if (debug_modes)
- tcc_tcov_block_end(tcc_state, -1);
- CODE_OFF();
- }
- } else {
- break;
- }
- }
-}
-
-#ifndef precedence_parser /* original top-down parser */
-
-static void expr_prod(void)
-{
- int t;
-
- unary();
- while ((t = tok) == '*' || t == '/' || t == '%') {
- next();
- unary();
- gen_op(t);
- }
-}
-
-static void expr_sum(void)
-{
- int t;
-
- expr_prod();
- while ((t = tok) == '+' || t == '-') {
- next();
- expr_prod();
- gen_op(t);
- }
-}
-
-static void expr_shift(void)
-{
- int t;
-
- expr_sum();
- while ((t = tok) == TOK_SHL || t == TOK_SAR) {
- next();
- expr_sum();
- gen_op(t);
- }
-}
-
-static void expr_cmp(void)
-{
- int t;
-
- expr_shift();
- while (((t = tok) >= TOK_ULE && t <= TOK_GT) ||
- t == TOK_ULT || t == TOK_UGE) {
- next();
- expr_shift();
- gen_op(t);
- }
-}
-
-static void expr_cmpeq(void)
-{
- int t;
-
- expr_cmp();
- while ((t = tok) == TOK_EQ || t == TOK_NE) {
- next();
- expr_cmp();
- gen_op(t);
- }
-}
-
-static void expr_and(void)
-{
- expr_cmpeq();
- while (tok == '&') {
- next();
- expr_cmpeq();
- gen_op('&');
- }
-}
-
-static void expr_xor(void)
-{
- expr_and();
- while (tok == '^') {
- next();
- expr_and();
- gen_op('^');
- }
-}
-
-static void expr_or(void)
-{
- expr_xor();
- while (tok == '|') {
- next();
- expr_xor();
- gen_op('|');
- }
-}
-
-static void expr_landor(int op);
-
-static void expr_land(void)
-{
- expr_or();
- if (tok == TOK_LAND)
- expr_landor(tok);
-}
-
-static void expr_lor(void)
-{
- expr_land();
- if (tok == TOK_LOR)
- expr_landor(tok);
-}
-
-# define expr_landor_next(op) op == TOK_LAND ? expr_or() : expr_land()
-#else /* defined precedence_parser */
-# define expr_landor_next(op) unary(), expr_infix(precedence(op) + 1)
-# define expr_lor() unary(), expr_infix(1)
-
-static int precedence(int tok)
-{
- switch (tok) {
- case TOK_LOR: return 1;
- case TOK_LAND: return 2;
- case '|': return 3;
- case '^': return 4;
- case '&': return 5;
- case TOK_EQ: case TOK_NE: return 6;
- relat: case TOK_ULT: case TOK_UGE: return 7;
- case TOK_SHL: case TOK_SAR: return 8;
- case '+': case '-': return 9;
- case '*': case '/': case '%': return 10;
- default:
- if (tok >= TOK_ULE && tok <= TOK_GT)
- goto relat;
- return 0;
- }
-}
-static unsigned char prec[256];
-static void init_prec(void)
-{
- int i;
- for (i = 0; i < 256; i++)
- prec[i] = precedence(i);
-}
-#define precedence(i) ((unsigned)i < 256 ? prec[i] : 0)
-
-static void expr_landor(int op);
-
-static void expr_infix(int p)
-{
- int t = tok, p2;
- while ((p2 = precedence(t)) >= p) {
- if (t == TOK_LOR || t == TOK_LAND) {
- expr_landor(t);
- } else {
- next();
- unary();
- if (precedence(tok) > p2)
- expr_infix(p2 + 1);
- gen_op(t);
- }
- t = tok;
- }
-}
-#endif
-
-/* Assuming vtop is a value used in a conditional context
- (i.e. compared with zero) return 0 if it's false, 1 if
- true and -1 if it can't be statically determined. */
-static int condition_3way(void)
-{
- int c = -1;
- if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
- (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) {
- vdup();
- gen_cast_s(VT_BOOL);
- c = vtop->c.i;
- vpop();
- }
- return c;
-}
-
-static void expr_landor(int op)
-{
- int t = 0, cc = 1, f = 0, i = op == TOK_LAND, c;
- for(;;) {
- c = f ? i : condition_3way();
- if (c < 0)
- save_regs(1), cc = 0;
- else if (c != i)
- nocode_wanted++, f = 1;
- if (tok != op)
- break;
- if (c < 0)
- t = gvtst(i, t);
- else
- vpop();
- next();
- expr_landor_next(op);
- }
- if (cc || f) {
- vpop();
- vpushi(i ^ f);
- gsym(t);
- nocode_wanted -= f;
- } else {
- gvtst_set(i, t);
- }
-}
-
-static int is_cond_bool(SValue *sv)
-{
- if ((sv->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST
- && (sv->type.t & VT_BTYPE) == VT_INT)
- return (unsigned)sv->c.i < 2;
- if (sv->r == VT_CMP)
- return 1;
- return 0;
-}
-
-static void expr_cond(void)
-{
- int tt, u, r1, r2, rc, t1, t2, islv, c, g;
- SValue sv;
- CType type;
-
- expr_lor();
- if (tok == '?') {
- next();
- c = condition_3way();
- g = (tok == ':' && gnu_ext);
- tt = 0;
- if (!g) {
- if (c < 0) {
- save_regs(1);
- tt = gvtst(1, 0);
- } else {
- vpop();
- }
- } else if (c < 0) {
- /* needed to avoid having different registers saved in
- each branch */
- save_regs(1);
- gv_dup();
- tt = gvtst(0, 0);
- }
-
- if (c == 0)
- nocode_wanted++;
- if (!g)
- gexpr();
-
- if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
- mk_pointer(&vtop->type);
- sv = *vtop; /* save value to handle it later */
- vtop--; /* no vpop so that FP stack is not flushed */
-
- if (g) {
- u = tt;
- } else if (c < 0) {
- u = gjmp(0);
- gsym(tt);
- } else
- u = 0;
-
- if (c == 0)
- nocode_wanted--;
- if (c == 1)
- nocode_wanted++;
- skip(':');
- expr_cond();
-
- if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
- mk_pointer(&vtop->type);
-
- /* cast operands to correct type according to ISOC rules */
- if (!combine_types(&type, &sv, vtop, '?'))
- type_incompatibility_error(&sv.type, &vtop->type,
- "type mismatch in conditional expression (have '%s' and '%s')");
-
- if (c < 0 && is_cond_bool(vtop) && is_cond_bool(&sv)) {
- /* optimize "if (f ? a > b : c || d) ..." for example, where normally
- "a < b" and "c || d" would be forced to "(int)0/1" first, whereas
- this code jumps directly to the if's then/else branches. */
- t1 = gvtst(0, 0);
- t2 = gjmp(0);
- gsym(u);
- vpushv(&sv);
- /* combine jump targets of 2nd op with VT_CMP of 1st op */
- gvtst_set(0, t1);
- gvtst_set(1, t2);
- gen_cast(&type);
- // tcc_warning("two conditions expr_cond");
- return;
- }
-
- /* keep structs lvalue by transforming `(expr ? a : b)` to `*(expr ? &a : &b)` so
- that `(expr ? a : b).mem` does not error with "lvalue expected" */
- islv = (vtop->r & VT_LVAL) && (sv.r & VT_LVAL) && VT_STRUCT == (type.t & VT_BTYPE);
-
- /* now we convert second operand */
- if (c != 1) {
- gen_cast(&type);
- if (islv) {
- mk_pointer(&vtop->type);
- gaddrof();
- } else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
- gaddrof();
- }
-
- rc = RC_TYPE(type.t);
- /* for long longs, we use fixed registers to avoid having
- to handle a complicated move */
- if (USING_TWO_WORDS(type.t))
- rc = RC_RET(type.t);
-
- tt = r2 = 0;
- if (c < 0) {
- r2 = gv(rc);
- tt = gjmp(0);
- }
- gsym(u);
- if (c == 1)
- nocode_wanted--;
-
- /* this is horrible, but we must also convert first
- operand */
- if (c != 0) {
- *vtop = sv;
- gen_cast(&type);
- if (islv) {
- mk_pointer(&vtop->type);
- gaddrof();
- } else if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
- gaddrof();
- }
-
- if (c < 0) {
- r1 = gv(rc);
- move_reg(r2, r1, islv ? VT_PTR : type.t);
- vtop->r = r2;
- gsym(tt);
- }
-
- if (islv)
- indir();
- }
-}
-
-static void expr_eq(void)
-{
- int t;
-
- expr_cond();
- if ((t = tok) == '=' || TOK_ASSIGN(t)) {
- test_lvalue();
- next();
- if (t == '=') {
- expr_eq();
- } else {
- vdup();
- expr_eq();
- gen_op(TOK_ASSIGN_OP(t));
- }
- vstore();
- }
-}
-
-ST_FUNC void gexpr(void)
-{
- while (1) {
- expr_eq();
- if (tok != ',')
- break;
- constant_p &= (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
- !((vtop->r & VT_SYM) && vtop->sym->a.addrtaken);
- vpop();
- next();
- }
-}
-
-/* parse a constant expression and return value in vtop. */
-static void expr_const1(void)
-{
- nocode_wanted += CONST_WANTED_BIT;
- expr_cond();
- nocode_wanted -= CONST_WANTED_BIT;
-}
-
-/* parse an integer constant and return its value. */
-static inline int64_t expr_const64(void)
-{
- int64_t c;
- expr_const1();
- if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM | VT_NONCONST)) != VT_CONST)
- expect("constant expression");
- c = vtop->c.i;
- vpop();
- return c;
-}
-
-/* parse an integer constant and return its value.
- Complain if it doesn't fit 32bit (signed or unsigned). */
-ST_FUNC int expr_const(void)
-{
- int c;
- int64_t wc = expr_const64();
- c = wc;
- if (c != wc && (unsigned)c != wc)
- tcc_error("constant exceeds 32 bit");
- return c;
-}
-
-/* ------------------------------------------------------------------------- */
-/* return from function */
-
-#ifndef TCC_TARGET_ARM64
-static void gfunc_return(CType *func_type)
-{
- if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
- CType type, ret_type;
- int ret_align, ret_nregs, regsize;
- ret_nregs = gfunc_sret(func_type, func_var, &ret_type,
- &ret_align, &regsize);
- if (ret_nregs < 0) {
-#ifdef TCC_TARGET_RISCV64
- arch_transfer_ret_regs(0);
-#endif
- } else if (0 == ret_nregs) {
- /* if returning structure, must copy it to implicit
- first pointer arg location */
- type = *func_type;
- mk_pointer(&type);
- vset(&type, VT_LOCAL | VT_LVAL, func_vc);
- indir();
- vswap();
- /* copy structure value to pointer */
- vstore();
- } else {
- /* returning structure packed into registers */
- int size, addr, align, rc;
- size = type_size(func_type,&align);
- if ((vtop->r != (VT_LOCAL | VT_LVAL) ||
- (vtop->c.i & (ret_align-1)))
- && (align & (ret_align-1))) {
- loc = (loc - size) & -ret_align;
- addr = loc;
- type = *func_type;
- vset(&type, VT_LOCAL | VT_LVAL, addr);
- vswap();
- vstore();
- vpop();
- vset(&ret_type, VT_LOCAL | VT_LVAL, addr);
- }
- vtop->type = ret_type;
- rc = RC_RET(ret_type.t);
- if (ret_nregs == 1)
- gv(rc);
- else {
- for (;;) {
- vdup();
- gv(rc);
- vpop();
- if (--ret_nregs == 0)
- break;
- /* We assume that when a structure is returned in multiple
- registers, their classes are consecutive values of the
- suite s(n) = 2^n */
- rc <<= 1;
- vtop->c.i += regsize;
- }
- }
- }
- } else {
- gv(RC_RET(func_type->t));
- }
- vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
-}
-#endif
-
-static void check_func_return(void)
-{
- if ((func_vt.t & VT_BTYPE) == VT_VOID)
- return;
- if (!strcmp (funcname, "main")
- && (func_vt.t & VT_BTYPE) == VT_INT) {
- /* main returns 0 by default */
- vpushi(0);
- gen_assign_cast(&func_vt);
- gfunc_return(&func_vt);
- } else {
- tcc_warning("function might return no value: '%s'", funcname);
- }
-}
-
-/* ------------------------------------------------------------------------- */
-/* switch/case */
-
-static int case_cmpi(const void *pa, const void *pb)
-{
- int64_t a = (*(struct case_t**) pa)->v1;
- int64_t b = (*(struct case_t**) pb)->v1;
- return a < b ? -1 : a > b;
-}
-
-static int case_cmpu(const void *pa, const void *pb)
-{
- uint64_t a = (uint64_t)(*(struct case_t**) pa)->v1;
- uint64_t b = (uint64_t)(*(struct case_t**) pb)->v1;
- return a < b ? -1 : a > b;
-}
-
-static void gtst_addr(int t, int a)
-{
- gsym_addr(gvtst(0, t), a);
-}
-
-static void gcase(struct case_t **base, int len, int *bsym)
-{
- struct case_t *p;
- int e;
- int ll = (vtop->type.t & VT_BTYPE) == VT_LLONG;
- while (len > 8) {
- /* binary search */
- p = base[len/2];
- vdup();
- if (ll)
- vpushll(p->v2);
- else
- vpushi(p->v2);
- gen_op(TOK_LE);
- e = gvtst(1, 0);
- vdup();
- if (ll)
- vpushll(p->v1);
- else
- vpushi(p->v1);
- gen_op(TOK_GE);
- gtst_addr(0, p->sym); /* v1 <= x <= v2 */
- /* x < v1 */
- gcase(base, len/2, bsym);
- /* x > v2 */
- gsym(e);
- e = len/2 + 1;
- base += e; len -= e;
- }
- /* linear scan */
- while (len--) {
- p = *base++;
- vdup();
- if (ll)
- vpushll(p->v2);
- else
- vpushi(p->v2);
- if (p->v1 == p->v2) {
- gen_op(TOK_EQ);
- gtst_addr(0, p->sym);
- } else {
- gen_op(TOK_LE);
- e = gvtst(1, 0);
- vdup();
- if (ll)
- vpushll(p->v1);
- else
- vpushi(p->v1);
- gen_op(TOK_GE);
- gtst_addr(0, p->sym);
- gsym(e);
- }
- }
- *bsym = gjmp(*bsym);
-}
-
-/* ------------------------------------------------------------------------- */
-/* __attribute__((cleanup(fn))) */
-
-static void try_call_scope_cleanup(Sym *stop)
-{
- Sym *cls = cur_scope->cl.s;
-
- for (; cls != stop; cls = cls->ncl) {
- Sym *fs = cls->next;
- Sym *vs = cls->prev_tok;
-
- vpushsym(&fs->type, fs);
- vset(&vs->type, vs->r, vs->c);
- vtop->sym = vs;
- mk_pointer(&vtop->type);
- gaddrof();
- gfunc_call(1);
- }
-}
-
-static void try_call_cleanup_goto(Sym *cleanupstate)
-{
- Sym *oc, *cc;
- int ocd, ccd;
-
- if (!cur_scope->cl.s)
- return;
-
- /* search NCA of both cleanup chains given parents and initial depth */
- ocd = cleanupstate ? cleanupstate->v & ~SYM_FIELD : 0;
- for (ccd = cur_scope->cl.n, oc = cleanupstate; ocd > ccd; --ocd, oc = oc->ncl)
- ;
- for (cc = cur_scope->cl.s; ccd > ocd; --ccd, cc = cc->ncl)
- ;
- for (; cc != oc; cc = cc->ncl, oc = oc->ncl, --ccd)
- ;
-
- try_call_scope_cleanup(cc);
-}
-
-/* call 'func' for each __attribute__((cleanup(func))) */
-static void block_cleanup(struct scope *o)
-{
- int jmp = 0;
- Sym *g, **pg;
- for (pg = &pending_gotos; (g = *pg) && g->c > o->cl.n;) {
- if (g->prev_tok->r & LABEL_FORWARD) {
- Sym *pcl = g->next;
- if (!jmp)
- jmp = gjmp(0);
- gsym(pcl->jnext);
- try_call_scope_cleanup(o->cl.s);
- pcl->jnext = gjmp(0);
- if (!o->cl.n)
- goto remove_pending;
- g->c = o->cl.n;
- pg = &g->prev;
- } else {
- remove_pending:
- *pg = g->prev;
- sym_free(g);
- }
- }
- gsym(jmp);
- try_call_scope_cleanup(o->cl.s);
-}
-
-/* ------------------------------------------------------------------------- */
-/* VLA */
-
-static void vla_restore(int loc)
-{
- if (loc)
- gen_vla_sp_restore(loc);
-}
-
-static void vla_leave(struct scope *o)
-{
- struct scope *c = cur_scope, *v = NULL;
- for (; c != o && c; c = c->prev)
- if (c->vla.num)
- v = c;
- if (v)
- vla_restore(v->vla.locorig);
-}
-
-/* ------------------------------------------------------------------------- */
-/* local scopes */
-
-static void new_scope(struct scope *o)
-{
- /* copy and link previous scope */
- *o = *cur_scope;
- o->prev = cur_scope;
- cur_scope = o;
- cur_scope->vla.num = 0;
-
- /* record local declaration stack position */
- o->lstk = local_stack;
- o->llstk = local_label_stack;
- ++local_scope;
-}
-
-static void prev_scope(struct scope *o, int is_expr)
-{
- vla_leave(o->prev);
-
- if (o->cl.s != o->prev->cl.s)
- block_cleanup(o->prev);
-
- /* pop locally defined labels */
- label_pop(&local_label_stack, o->llstk, is_expr);
-
- /* In the is_expr case (a statement expression is finished here),
- vtop might refer to symbols on the local_stack. Either via the
- type or via vtop->sym. We can't pop those nor any that in turn
- might be referred to. To make it easier we don't roll back
- any symbols in that case; some upper level call to block() will
- do that. We do have to remove such symbols from the lookup
- tables, though. sym_pop will do that. */
-
- /* pop locally defined symbols */
- pop_local_syms(o->lstk, is_expr);
- cur_scope = o->prev;
- --local_scope;
-}
-
-/* leave a scope via break/continue(/goto) */
-static void leave_scope(struct scope *o)
-{
- if (!o)
- return;
- try_call_scope_cleanup(o->cl.s);
- vla_leave(o);
-}
-
-/* short versiona for scopes with 'if/do/while/switch' which can
- declare only types (of struct/union/enum) */
-static void new_scope_s(struct scope *o)
-{
- o->lstk = local_stack;
- ++local_scope;
-}
-
-static void prev_scope_s(struct scope *o)
-{
- sym_pop(&local_stack, o->lstk, 0);
- --local_scope;
-}
-
-/* ------------------------------------------------------------------------- */
-/* call block from 'for do while' loops */
-
-static void lblock(int *bsym, int *csym)
-{
- struct scope *lo = loop_scope, *co = cur_scope;
- int *b = co->bsym, *c = co->csym;
- if (csym) {
- co->csym = csym;
- loop_scope = co;
- }
- co->bsym = bsym;
- block(0);
- co->bsym = b;
- if (csym) {
- co->csym = c;
- loop_scope = lo;
- }
-}
-
-static void block(int is_expr)
-{
- int a, b, c, d, e, t;
- struct scope o;
- Sym *s;
-
- if (is_expr) {
- /* default return value is (void) */
- vpushi(0);
- vtop->type.t = VT_VOID;
- }
-
-again:
- t = tok;
- /* If the token carries a value, next() might destroy it. Only with
- invalid code such as f(){"123"4;} */
- if (TOK_HAS_VALUE(t))
- goto expr;
- next();
-
- if (debug_modes)
- tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_begin (tcc_state);
-
- if (t == TOK_IF) {
- new_scope_s(&o);
- skip('(');
- gexpr();
- skip(')');
- a = gvtst(1, 0);
- block(0);
- if (tok == TOK_ELSE) {
- d = gjmp(0);
- gsym(a);
- next();
- block(0);
- gsym(d); /* patch else jmp */
- } else {
- gsym(a);
- }
- prev_scope_s(&o);
-
- } else if (t == TOK_WHILE) {
- new_scope_s(&o);
- d = gind();
- skip('(');
- gexpr();
- skip(')');
- a = gvtst(1, 0);
- b = 0;
- lblock(&a, &b);
- gjmp_addr(d);
- gsym_addr(b, d);
- gsym(a);
- prev_scope_s(&o);
-
- } else if (t == '{') {
- if (debug_modes)
- tcc_debug_stabn(tcc_state, N_LBRAC, ind - func_ind);
- new_scope(&o);
-
- /* handle local labels declarations */
- while (tok == TOK_LABEL) {
- do {
- next();
- if (tok < TOK_UIDENT)
- expect("label identifier");
- label_push(&local_label_stack, tok, LABEL_DECLARED);
- next();
- } while (tok == ',');
- skip(';');
- }
-
- while (tok != '}') {
- decl(VT_LOCAL);
- if (tok != '}') {
- if (is_expr)
- vpop();
- block(is_expr);
- }
- }
-
- prev_scope(&o, is_expr);
- if (debug_modes)
- tcc_debug_stabn(tcc_state, N_RBRAC, ind - func_ind);
- if (local_scope)
- next();
- else if (!nocode_wanted)
- check_func_return();
-
- } else if (t == TOK_RETURN) {
- b = (func_vt.t & VT_BTYPE) != VT_VOID;
- if (tok != ';') {
- gexpr();
- if (b) {
- gen_assign_cast(&func_vt);
- } else {
- if (vtop->type.t != VT_VOID)
- tcc_warning("void function returns a value");
- vtop--;
- }
- } else if (b) {
- tcc_warning("'return' with no value");
- b = 0;
- }
- leave_scope(root_scope);
- if (b)
- gfunc_return(&func_vt);
- skip(';');
- /* jump unless last stmt in top-level block */
- if (tok != '}' || local_scope != 1)
- rsym = gjmp(rsym);
- if (debug_modes)
- tcc_tcov_block_end (tcc_state, -1);
- CODE_OFF();
-
- } else if (t == TOK_BREAK) {
- /* compute jump */
- if (!cur_scope->bsym)
- tcc_error("cannot break");
- if (cur_switch && cur_scope->bsym == cur_switch->bsym)
- leave_scope(cur_switch->scope);
- else
- leave_scope(loop_scope);
- *cur_scope->bsym = gjmp(*cur_scope->bsym);
- skip(';');
-
- } else if (t == TOK_CONTINUE) {
- /* compute jump */
- if (!cur_scope->csym)
- tcc_error("cannot continue");
- leave_scope(loop_scope);
- *cur_scope->csym = gjmp(*cur_scope->csym);
- skip(';');
-
- } else if (t == TOK_FOR) {
- new_scope(&o);
-
- skip('(');
- if (tok != ';') {
- /* c99 for-loop init decl? */
- if (!decl(VT_JMP)) {
- /* no, regular for-loop init expr */
- gexpr();
- vpop();
- }
- }
- skip(';');
- a = b = 0;
- c = d = gind();
- if (tok != ';') {
- gexpr();
- a = gvtst(1, 0);
- }
- skip(';');
- if (tok != ')') {
- e = gjmp(0);
- d = gind();
- gexpr();
- vpop();
- gjmp_addr(c);
- gsym(e);
- }
- skip(')');
- lblock(&a, &b);
- gjmp_addr(d);
- gsym_addr(b, d);
- gsym(a);
- prev_scope(&o, 0);
-
- } else if (t == TOK_DO) {
- new_scope_s(&o);
- a = b = 0;
- d = gind();
- lblock(&a, &b);
- gsym(b);
- skip(TOK_WHILE);
- skip('(');
- gexpr();
- skip(')');
- skip(';');
- c = gvtst(0, 0);
- gsym_addr(c, d);
- gsym(a);
- prev_scope_s(&o);
-
- } else if (t == TOK_SWITCH) {
- struct switch_t *sw;
-
- sw = tcc_mallocz(sizeof *sw);
- sw->bsym = &a;
- sw->scope = cur_scope;
- sw->prev = cur_switch;
- sw->nocode_wanted = nocode_wanted;
- cur_switch = sw;
-
- new_scope_s(&o);
- skip('(');
- gexpr();
- skip(')');
- sw->sv = *vtop--; /* save switch value */
- a = 0;
- b = gjmp(0); /* jump to first case */
- lblock(&a, NULL);
- a = gjmp(a); /* add implicit break */
- /* case lookup */
- gsym(b);
- prev_scope_s(&o);
-
- if (sw->nocode_wanted)
- goto skip_switch;
- if (sw->sv.type.t & VT_UNSIGNED)
- qsort(sw->p, sw->n, sizeof(void*), case_cmpu);
- else
- qsort(sw->p, sw->n, sizeof(void*), case_cmpi);
- for (b = 1; b < sw->n; b++)
- if (sw->sv.type.t & VT_UNSIGNED
- ? (uint64_t)sw->p[b - 1]->v2 >= (uint64_t)sw->p[b]->v1
- : sw->p[b - 1]->v2 >= sw->p[b]->v1)
- tcc_error("duplicate case value");
- vpushv(&sw->sv);
- gv(RC_INT);
- d = 0, gcase(sw->p, sw->n, &d);
- vpop();
- if (sw->def_sym)
- gsym_addr(d, sw->def_sym);
- else
- gsym(d);
- skip_switch:
- /* break label */
- gsym(a);
-
- dynarray_reset(&sw->p, &sw->n);
- cur_switch = sw->prev;
- tcc_free(sw);
-
- } else if (t == TOK_CASE) {
- struct case_t *cr = tcc_malloc(sizeof(struct case_t));
- if (!cur_switch)
- expect("switch");
- cr->v1 = cr->v2 = expr_const64();
- if (gnu_ext && tok == TOK_DOTS) {
- next();
- cr->v2 = expr_const64();
- if ((!(cur_switch->sv.type.t & VT_UNSIGNED) && cr->v2 < cr->v1)
- || (cur_switch->sv.type.t & VT_UNSIGNED && (uint64_t)cr->v2 < (uint64_t)cr->v1))
- tcc_warning("empty case range");
- }
- /* case and default are unreachable from a switch under nocode_wanted */
- if (!cur_switch->nocode_wanted)
- cr->sym = gind();
- dynarray_add(&cur_switch->p, &cur_switch->n, cr);
- skip(':');
- is_expr = 0;
- goto block_after_label;
-
- } else if (t == TOK_DEFAULT) {
- if (!cur_switch)
- expect("switch");
- if (cur_switch->def_sym)
- tcc_error("too many 'default'");
- cur_switch->def_sym = cur_switch->nocode_wanted ? 1 : gind();
- skip(':');
- is_expr = 0;
- goto block_after_label;
-
- } else if (t == TOK_GOTO) {
- vla_restore(cur_scope->vla.locorig);
- if (tok == '*' && gnu_ext) {
- /* computed goto */
- next();
- gexpr();
- if ((vtop->type.t & VT_BTYPE) != VT_PTR)
- expect("pointer");
- ggoto();
-
- } else if (tok >= TOK_UIDENT) {
- s = label_find(tok);
- /* put forward definition if needed */
- if (!s)
- s = label_push(&global_label_stack, tok, LABEL_FORWARD);
- else if (s->r == LABEL_DECLARED)
- s->r = LABEL_FORWARD;
-
- if (s->r & LABEL_FORWARD) {
- /* start new goto chain for cleanups, linked via label->next */
- if (cur_scope->cl.s && !nocode_wanted) {
- sym_push2(&pending_gotos, SYM_FIELD, 0, cur_scope->cl.n);
- pending_gotos->prev_tok = s;
- s = sym_push2(&s->next, SYM_FIELD, 0, 0);
- pending_gotos->next = s;
- }
- s->jnext = gjmp(s->jnext);
- } else {
- try_call_cleanup_goto(s->cleanupstate);
- gjmp_addr(s->jnext);
- }
- next();
-
- } else {
- expect("label identifier");
- }
- skip(';');
-
- } else if (t == TOK_ASM1 || t == TOK_ASM2 || t == TOK_ASM3) {
- asm_instr();
-
- } else {
- if (tok == ':' && t >= TOK_UIDENT) {
- /* label case */
- next();
- s = label_find(t);
- if (s) {
- if (s->r == LABEL_DEFINED)
- tcc_error("duplicate label '%s'", get_tok_str(s->v, NULL));
- s->r = LABEL_DEFINED;
- if (s->next) {
- Sym *pcl; /* pending cleanup goto */
- for (pcl = s->next; pcl; pcl = pcl->prev)
- gsym(pcl->jnext);
- sym_pop(&s->next, NULL, 0);
- } else
- gsym(s->jnext);
- } else {
- s = label_push(&global_label_stack, t, LABEL_DEFINED);
- }
- s->jnext = gind();
- s->cleanupstate = cur_scope->cl.s;
-
- block_after_label:
- {
- /* Accept attributes after labels (e.g. 'unused') */
- AttributeDef ad_tmp;
- parse_attribute(&ad_tmp);
- }
- if (debug_modes)
- tcc_tcov_reset_ind(tcc_state);
- vla_restore(cur_scope->vla.loc);
- if (tok != '}')
- goto again;
- /* we accept this, but it is a mistake */
- tcc_warning_c(warn_all)("deprecated use of label at end of compound statement");
-
- } else {
- /* expression case */
- if (t != ';') {
- unget_tok(t);
- expr:
- if (is_expr) {
- vpop();
- gexpr();
- } else {
- gexpr();
- vpop();
- }
- skip(';');
- }
- }
- }
-
- if (debug_modes)
- tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_end (tcc_state, 0);
-}
-
-/* This skips over a stream of tokens containing balanced {} and ()
- pairs, stopping at outer ',' ';' and '}' (or matching '}' if we started
- with a '{'). If STR then allocates and stores the skipped tokens
- in *STR. This doesn't check if () and {} are nested correctly,
- i.e. "({)}" is accepted. */
-static void skip_or_save_block(TokenString **str)
-{
- int braces = tok == '{';
- int level = 0;
- if (str)
- *str = tok_str_alloc();
-
- while (1) {
- int t = tok;
- if (level == 0
- && (t == ','
- || t == ';'
- || t == '}'
- || t == ')'
- || t == ']'))
- break;
- if (t == TOK_EOF) {
- if (str || level > 0)
- tcc_error("unexpected end of file");
- else
- break;
- }
- if (str)
- tok_str_add_tok(*str);
- next();
- if (t == '{' || t == '(' || t == '[') {
- level++;
- } else if (t == '}' || t == ')' || t == ']') {
- level--;
- if (level == 0 && braces && t == '}')
- break;
- }
- }
- if (str) {
- tok_str_add(*str, -1);
- tok_str_add(*str, 0);
- }
-}
-
-#define EXPR_CONST 1
-#define EXPR_ANY 2
-
-static void parse_init_elem(int expr_type)
-{
- int saved_global_expr;
- switch(expr_type) {
- case EXPR_CONST:
- /* compound literals must be allocated globally in this case */
- saved_global_expr = global_expr;
- global_expr = 1;
- expr_const1();
- global_expr = saved_global_expr;
- /* NOTE: symbols are accepted, as well as lvalue for anon symbols
- (compound literals). */
- if (((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST
- && ((vtop->r & (VT_SYM|VT_LVAL)) != (VT_SYM|VT_LVAL)
- || vtop->sym->v < SYM_FIRST_ANOM))
-#ifdef TCC_TARGET_PE
- || ((vtop->r & VT_SYM) && vtop->sym->a.dllimport)
-#endif
- )
- tcc_error("initializer element is not constant");
- break;
- case EXPR_ANY:
- expr_eq();
- break;
- }
-}
-
-#if 1
-static void init_assert(init_params *p, int offset)
-{
- if (p->sec ? !NODATA_WANTED && offset > p->sec->data_offset
- : !nocode_wanted && offset > p->local_offset)
- tcc_internal_error("initializer overflow");
-}
-#else
-#define init_assert(sec, offset)
-#endif
-
-/* put zeros for variable based init */
-static void init_putz(init_params *p, unsigned long c, int size)
-{
- init_assert(p, c + size);
- if (p->sec) {
- /* nothing to do because globals are already set to zero */
- } else {
- vpush_helper_func(TOK_memset);
- vseti(VT_LOCAL, c);
-#ifdef TCC_TARGET_ARM
- vpushs(size);
- vpushi(0);
-#else
- vpushi(0);
- vpushs(size);
-#endif
- gfunc_call(3);
- }
-}
-
-#define DIF_FIRST 1
-#define DIF_SIZE_ONLY 2
-#define DIF_HAVE_ELEM 4
-#define DIF_CLEAR 8
-
-/* delete relocations for specified range c ... c + size. Unfortunatly
- in very special cases, relocations may occur unordered */
-static void decl_design_delrels(Section *sec, int c, int size)
-{
- ElfW_Rel *rel, *rel2, *rel_end;
- if (!sec || !sec->reloc)
- return;
- rel = rel2 = (ElfW_Rel*)sec->reloc->data;
- rel_end = (ElfW_Rel*)(sec->reloc->data + sec->reloc->data_offset);
- while (rel < rel_end) {
- if (rel->r_offset >= c && rel->r_offset < c + size) {
- sec->reloc->data_offset -= sizeof *rel;
- } else {
- if (rel2 != rel)
- memcpy(rel2, rel, sizeof *rel);
- ++rel2;
- }
- ++rel;
- }
-}
-
-static void decl_design_flex(init_params *p, Sym *ref, int index)
-{
- if (ref == p->flex_array_ref) {
- if (index >= ref->c)
- ref->c = index + 1;
- } else if (ref->c < 0)
- tcc_error("flexible array has zero size in this context");
-}
-
-/* t is the array or struct type. c is the array or struct
- address. cur_field is the pointer to the current
- field, for arrays the 'c' member contains the current start
- index. 'flags' is as in decl_initializer.
- 'al' contains the already initialized length of the
- current container (starting at c). This returns the new length of that. */
-static int decl_designator(init_params *p, CType *type, unsigned long c,
- Sym **cur_field, int flags, int al)
-{
- Sym *s, *f;
- int index, index_last, align, l, nb_elems, elem_size;
- unsigned long corig = c;
-
- elem_size = 0;
- nb_elems = 1;
-
- if (flags & DIF_HAVE_ELEM)
- goto no_designator;
-
- if (gnu_ext && tok >= TOK_UIDENT) {
- l = tok, next();
- if (tok == ':')
- goto struct_field;
- unget_tok(l);
- }
-
- /* NOTE: we only support ranges for last designator */
- while (nb_elems == 1 && (tok == '[' || tok == '.')) {
- if (tok == '[') {
- if (!(type->t & VT_ARRAY))
- expect("array type");
- next();
- index = index_last = expr_const();
- if (tok == TOK_DOTS && gnu_ext) {
- next();
- index_last = expr_const();
- }
- skip(']');
- s = type->ref;
- decl_design_flex(p, s, index_last);
- if (index < 0 || index_last >= s->c || index_last < index)
- tcc_error("index exceeds array bounds or range is empty");
- if (cur_field)
- (*cur_field)->c = index_last;
- type = pointed_type(type);
- elem_size = type_size(type, &align);
- c += index * elem_size;
- nb_elems = index_last - index + 1;
- } else {
- int cumofs;
- next();
- l = tok;
- struct_field:
- next();
- if ((type->t & VT_BTYPE) != VT_STRUCT)
- expect("struct/union type");
- cumofs = 0;
- f = find_field(type, l, &cumofs);
- if (cur_field)
- *cur_field = f;
- type = &f->type;
- c += cumofs;
- }
- cur_field = NULL;
- }
- if (!cur_field) {
- if (tok == '=') {
- next();
- } else if (!gnu_ext) {
- expect("=");
- }
- } else {
- no_designator:
- if (type->t & VT_ARRAY) {
- index = (*cur_field)->c;
- s = type->ref;
- decl_design_flex(p, s, index);
- if (index >= s->c)
- tcc_error("too many initializers");
- type = pointed_type(type);
- elem_size = type_size(type, &align);
- c += index * elem_size;
- } else {
- f = *cur_field;
- /* Skip bitfield padding. Also with size 32 and 64. */
- while (f && (f->v & SYM_FIRST_ANOM) &&
- is_integer_btype(f->type.t & VT_BTYPE))
- *cur_field = f = f->next;
- if (!f)
- tcc_error("too many initializers");
- type = &f->type;
- c += f->c;
- }
- }
-
- if (!elem_size) /* for structs */
- elem_size = type_size(type, &align);
-
- /* Using designators the same element can be initialized more
- than once. In that case we need to delete possibly already
- existing relocations. */
- if (!(flags & DIF_SIZE_ONLY) && c - corig < al) {
- decl_design_delrels(p->sec, c, elem_size * nb_elems);
- flags &= ~DIF_CLEAR; /* mark stack dirty too */
- }
-
- decl_initializer(p, type, c, flags & ~DIF_FIRST);
-
- if (!(flags & DIF_SIZE_ONLY) && nb_elems > 1) {
- Sym aref = {0};
- CType t1;
- int i;
- if (p->sec || (type->t & VT_ARRAY)) {
- /* make init_putv/vstore believe it were a struct */
- aref.c = elem_size;
- t1.t = VT_STRUCT, t1.ref = &aref;
- type = &t1;
- }
- if (p->sec)
- vpush_ref(type, p->sec, c, elem_size);
- else
- vset(type, VT_LOCAL|VT_LVAL, c);
- for (i = 1; i < nb_elems; i++) {
- vdup();
- init_putv(p, type, c + elem_size * i);
- }
- vpop();
- }
-
- c += nb_elems * elem_size;
- if (c - corig > al)
- al = c - corig;
- return al;
-}
-
-/* store a value or an expression directly in global data or in local array */
-static void init_putv(init_params *p, CType *type, unsigned long c)
-{
- int bt;
- void *ptr;
- CType dtype;
- int size, align;
- Section *sec = p->sec;
- uint64_t val;
-
- dtype = *type;
- dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
-
- size = type_size(type, &align);
- if (type->t & VT_BITFIELD)
- size = (BIT_POS(type->t) + BIT_SIZE(type->t) + 7) / 8;
- init_assert(p, c + size);
-
- if (sec) {
- /* XXX: not portable */
- /* XXX: generate error if incorrect relocation */
- gen_assign_cast(&dtype);
- bt = type->t & VT_BTYPE;
-
- if ((vtop->r & VT_SYM)
- && bt != VT_PTR
- && (bt != (PTR_SIZE == 8 ? VT_LLONG : VT_INT)
- || (type->t & VT_BITFIELD))
- && !((vtop->r & VT_CONST) && vtop->sym->v >= SYM_FIRST_ANOM)
- )
- tcc_error("initializer element is not computable at load time");
-
- if (NODATA_WANTED) {
- vtop--;
- return;
- }
-
- ptr = sec->data + c;
- val = vtop->c.i;
-
- /* XXX: make code faster ? */
- if ((vtop->r & (VT_SYM|VT_CONST)) == (VT_SYM|VT_CONST) &&
- vtop->sym->v >= SYM_FIRST_ANOM &&
- /* XXX This rejects compound literals like
- '(void *){ptr}'. The problem is that '&sym' is
- represented the same way, which would be ruled out
- by the SYM_FIRST_ANOM check above, but also '"string"'
- in 'char *p = "string"' is represented the same
- with the type being VT_PTR and the symbol being an
- anonymous one. That is, there's no difference in vtop
- between '(void *){x}' and '&(void *){x}'. Ignore
- pointer typed entities here. Hopefully no real code
- will ever use compound literals with scalar type. */
- (vtop->type.t & VT_BTYPE) != VT_PTR) {
- /* These come from compound literals, memcpy stuff over. */
- Section *ssec;
- ElfSym *esym;
- ElfW_Rel *rel;
- esym = elfsym(vtop->sym);
- ssec = tcc_state->sections[esym->st_shndx];
- memmove (ptr, ssec->data + esym->st_value + (int)vtop->c.i, size);
- if (ssec->reloc) {
- /* We need to copy over all memory contents, and that
- includes relocations. Use the fact that relocs are
- created it order, so look from the end of relocs
- until we hit one before the copied region. */
- unsigned long relofs = ssec->reloc->data_offset;
- while (relofs >= sizeof(*rel)) {
- relofs -= sizeof(*rel);
- rel = (ElfW_Rel*)(ssec->reloc->data + relofs);
- if (rel->r_offset >= esym->st_value + size)
- continue;
- if (rel->r_offset < esym->st_value)
- break;
- put_elf_reloca(symtab_section, sec,
- c + rel->r_offset - esym->st_value,
- ELFW(R_TYPE)(rel->r_info),
- ELFW(R_SYM)(rel->r_info),
-#if PTR_SIZE == 8
- rel->r_addend
-#else
- 0
-#endif
- );
- }
- }
- } else {
- if (type->t & VT_BITFIELD) {
- int bit_pos, bit_size, bits, n;
- unsigned char *p, v, m;
- bit_pos = BIT_POS(vtop->type.t);
- bit_size = BIT_SIZE(vtop->type.t);
- p = (unsigned char*)ptr + (bit_pos >> 3);
- bit_pos &= 7, bits = 0;
- while (bit_size) {
- n = 8 - bit_pos;
- if (n > bit_size)
- n = bit_size;
- v = val >> bits << bit_pos;
- m = ((1 << n) - 1) << bit_pos;
- *p = (*p & ~m) | (v & m);
- bits += n, bit_size -= n, bit_pos = 0, ++p;
- }
- } else
- switch(bt) {
- case VT_BOOL:
- *(char *)ptr = val != 0;
- break;
- case VT_BYTE:
- *(char *)ptr = val;
- break;
- case VT_SHORT:
- write16le(ptr, val);
- break;
- case VT_FLOAT:
- write32le(ptr, val);
- break;
- case VT_DOUBLE:
- write64le(ptr, val);
- break;
- case VT_LDOUBLE:
-#if defined TCC_IS_NATIVE_387
- /* Host and target platform may be different but both have x87.
- On windows, tcc does not use VT_LDOUBLE, except when it is a
- cross compiler. In this case a mingw gcc as host compiler
- comes here with 10-byte long doubles, while msvc or tcc won't.
- tcc itself can still translate by asm.
- In any case we avoid possibly random bytes 11 and 12.
- */
- if (sizeof (long double) >= 10)
- memcpy(ptr, &vtop->c.ld, 10);
-#ifdef __TINYC__
- else if (sizeof (long double) == sizeof (double))
- __asm__("fldl %1\nfstpt %0\n" : "=m" (*ptr) : "m" (vtop->c.ld));
-#endif
- else
-#endif
- /* For other platforms it should work natively, but may not work
- for cross compilers */
- if (sizeof(long double) == LDOUBLE_SIZE)
- memcpy(ptr, &vtop->c.ld, LDOUBLE_SIZE);
- else if (sizeof(double) == LDOUBLE_SIZE)
- *(double*)ptr = (double)vtop->c.ld;
- else if (0 == memcmp(ptr, &vtop->c.ld, LDOUBLE_SIZE))
- ; /* nothing to do for 0.0 */
-#ifndef TCC_CROSS_TEST
- else
- tcc_error("can't cross compile long double constants");
-#endif
- break;
-
-#if PTR_SIZE == 8
- /* intptr_t may need a reloc too, see tcctest.c:relocation_test() */
- case VT_LLONG:
- case VT_PTR:
- if (vtop->r & VT_SYM)
- greloca(sec, vtop->sym, c, R_DATA_PTR, val);
- else
- write64le(ptr, val);
- break;
- case VT_INT:
- write32le(ptr, val);
- break;
-#else
- case VT_LLONG:
- write64le(ptr, val);
- break;
- case VT_PTR:
- case VT_INT:
- if (vtop->r & VT_SYM)
- greloc(sec, vtop->sym, c, R_DATA_PTR);
- write32le(ptr, val);
- break;
-#endif
- default:
- //tcc_internal_error("unexpected type");
- break;
- }
- }
- vtop--;
- } else {
- vset(&dtype, VT_LOCAL|VT_LVAL, c);
- vswap();
- vstore();
- vpop();
- }
-}
-
-/* 't' contains the type and storage info. 'c' is the offset of the
- object in section 'sec'. If 'sec' is NULL, it means stack based
- allocation. 'flags & DIF_FIRST' is true if array '{' must be read (multi
- dimension implicit array init handling). 'flags & DIF_SIZE_ONLY' is true if
- size only evaluation is wanted (only for arrays). */
-static void decl_initializer(init_params *p, CType *type, unsigned long c, int flags)
-{
- int len, n, no_oblock, i;
- int size1, align1;
- Sym *s, *f;
- Sym indexsym;
- CType *t1;
-
- /* generate line number info */
- if (debug_modes && !p->sec)
- tcc_debug_line(tcc_state), tcc_tcov_check_line (tcc_state, 1);
-
- if (!(flags & DIF_HAVE_ELEM) && tok != '{' &&
- /* In case of strings we have special handling for arrays, so
- don't consume them as initializer value (which would commit them
- to some anonymous symbol). */
- tok != TOK_LSTR && tok != TOK_STR &&
- (!(flags & DIF_SIZE_ONLY)
- /* a struct may be initialized from a struct of same type, as in
- struct {int x,y;} a = {1,2}, b = {3,4}, c[] = {a,b};
- In that case we need to parse the element in order to check
- it for compatibility below */
- || (type->t & VT_BTYPE) == VT_STRUCT)
- ) {
- int ncw_prev = nocode_wanted;
- if ((flags & DIF_SIZE_ONLY) && !p->sec)
- ++nocode_wanted;
- parse_init_elem(!p->sec ? EXPR_ANY : EXPR_CONST);
- nocode_wanted = ncw_prev;
- flags |= DIF_HAVE_ELEM;
- }
-
- if (type->t & VT_ARRAY) {
- no_oblock = 1;
- if (((flags & DIF_FIRST) && tok != TOK_LSTR && tok != TOK_STR) ||
- tok == '{') {
- skip('{');
- no_oblock = 0;
- }
-
- s = type->ref;
- n = s->c;
- t1 = pointed_type(type);
- size1 = type_size(t1, &align1);
-
- /* only parse strings here if correct type (otherwise: handle
- them as ((w)char *) expressions */
- if ((tok == TOK_LSTR &&
-#ifdef TCC_TARGET_PE
- (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
-#else
- (t1->t & VT_BTYPE) == VT_INT
-#endif
- ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
- len = 0;
- cstr_reset(&initstr);
- if (size1 != (tok == TOK_STR ? 1 : sizeof(nwchar_t)))
- tcc_error("unhandled string literal merging");
- while (tok == TOK_STR || tok == TOK_LSTR) {
- if (initstr.size)
- initstr.size -= size1;
- if (tok == TOK_STR)
- len += tokc.str.size;
- else
- len += tokc.str.size / sizeof(nwchar_t);
- len--;
- cstr_cat(&initstr, tokc.str.data, tokc.str.size);
- next();
- }
- if (tok != ')' && tok != '}' && tok != ',' && tok != ';'
- && tok != TOK_EOF) {
- /* Not a lone literal but part of a bigger expression. */
- unget_tok(size1 == 1 ? TOK_STR : TOK_LSTR);
- tokc.str.size = initstr.size;
- tokc.str.data = initstr.data;
- goto do_init_array;
- }
-
- decl_design_flex(p, s, len);
- if (!(flags & DIF_SIZE_ONLY)) {
- int nb = n, ch;
- if (len < nb)
- nb = len;
- if (len > nb)
- tcc_warning("initializer-string for array is too long");
- /* in order to go faster for common case (char
- string in global variable, we handle it
- specifically */
- if (p->sec && size1 == 1) {
- init_assert(p, c + nb);
- if (!NODATA_WANTED)
- memcpy(p->sec->data + c, initstr.data, nb);
- } else {
- for(i=0;i<n;i++) {
- if (i >= nb) {
- /* only add trailing zero if enough storage (no
- warning in this case since it is standard) */
- if (flags & DIF_CLEAR)
- break;
- if (n - i >= 4) {
- init_putz(p, c + i * size1, (n - i) * size1);
- break;
- }
- ch = 0;
- } else if (size1 == 1)
- ch = ((unsigned char *)initstr.data)[i];
- else
- ch = ((nwchar_t *)initstr.data)[i];
- vpushi(ch);
- init_putv(p, t1, c + i * size1);
- }
- }
- }
- } else {
-
- do_init_array:
- indexsym.c = 0;
- f = &indexsym;
-
- do_init_list:
- /* zero memory once in advance */
- if (!(flags & (DIF_CLEAR | DIF_SIZE_ONLY))) {
- init_putz(p, c, n*size1);
- flags |= DIF_CLEAR;
- }
-
- len = 0;
- /* GNU extension: if the initializer is empty for a flex array,
- it's size is zero. We won't enter the loop, so set the size
- now. */
- decl_design_flex(p, s, len);
- while (tok != '}' || (flags & DIF_HAVE_ELEM)) {
- len = decl_designator(p, type, c, &f, flags, len);
- flags &= ~DIF_HAVE_ELEM;
- if (type->t & VT_ARRAY) {
- ++indexsym.c;
- /* special test for multi dimensional arrays (may not
- be strictly correct if designators are used at the
- same time) */
- if (no_oblock && len >= n*size1)
- break;
- } else {
- if (s->type.t == VT_UNION)
- f = NULL;
- else
- f = f->next;
- if (no_oblock && f == NULL)
- break;
- }
-
- if (tok == '}')
- break;
- skip(',');
- }
- }
- if (!no_oblock)
- skip('}');
-
- } else if ((flags & DIF_HAVE_ELEM)
- /* Use i_c_parameter_t, to strip toplevel qualifiers.
- The source type might have VT_CONSTANT set, which is
- of course assignable to non-const elements. */
- && is_compatible_unqualified_types(type, &vtop->type)) {
- goto one_elem;
-
- } else if ((type->t & VT_BTYPE) == VT_STRUCT) {
- no_oblock = 1;
- if ((flags & DIF_FIRST) || tok == '{') {
- skip('{');
- no_oblock = 0;
- }
- s = type->ref;
- f = s->next;
- n = s->c;
- size1 = 1;
- goto do_init_list;
-
- } else if (tok == '{') {
- if (flags & DIF_HAVE_ELEM)
- skip(';');
- next();
- decl_initializer(p, type, c, flags & ~DIF_HAVE_ELEM);
- skip('}');
-
- } else one_elem: if ((flags & DIF_SIZE_ONLY)) {
- /* If we supported only ISO C we wouldn't have to accept calling
- this on anything than an array if DIF_SIZE_ONLY (and even then
- only on the outermost level, so no recursion would be needed),
- because initializing a flex array member isn't supported.
- But GNU C supports it, so we need to recurse even into
- subfields of structs and arrays when DIF_SIZE_ONLY is set. */
- /* just skip expression */
- if (flags & DIF_HAVE_ELEM)
- vpop();
- else
- skip_or_save_block(NULL);
-
- } else {
- if (!(flags & DIF_HAVE_ELEM)) {
- /* This should happen only when we haven't parsed
- the init element above for fear of committing a
- string constant to memory too early. */
- if (tok != TOK_STR && tok != TOK_LSTR)
- expect("string constant");
- parse_init_elem(!p->sec ? EXPR_ANY : EXPR_CONST);
- }
- if (!p->sec && (flags & DIF_CLEAR) /* container was already zero'd */
- && (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST
- && vtop->c.i == 0
- && btype_size(type->t & VT_BTYPE) /* not for fp constants */
- )
- vpop();
- else
- init_putv(p, type, c);
- }
-}
-
-/* parse an initializer for type 't' if 'has_init' is non zero, and
- allocate space in local or global data space ('r' is either
- VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
- variable 'v' of scope 'scope' is declared before initializers
- are parsed. If 'v' is zero, then a reference to the new object
- is put in the value stack. If 'has_init' is 2, a special parsing
- is done to handle string constants. */
-static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
- int has_init, int v, int global)
-{
- int size, align, addr;
- TokenString *init_str = NULL;
-
- Section *sec;
- Sym *flexible_array;
- Sym *sym;
- int saved_nocode_wanted = nocode_wanted;
-#ifdef CONFIG_TCC_BCHECK
- int bcheck = tcc_state->do_bounds_check && !NODATA_WANTED;
-#endif
- init_params p = {0};
-
- /* Always allocate static or global variables */
- if (v && (r & VT_VALMASK) == VT_CONST)
- nocode_wanted |= DATA_ONLY_WANTED;
-
- flexible_array = NULL;
- size = type_size(type, &align);
-
- /* exactly one flexible array may be initialized, either the
- toplevel array or the last member of the toplevel struct */
-
- if (size < 0) {
- /* If the base type itself was an array type of unspecified size
- (like in 'typedef int arr[]; arr x = {1};') then we will
- overwrite the unknown size by the real one for this decl.
- We need to unshare the ref symbol holding that size. */
- type->ref = sym_push(SYM_FIELD, &type->ref->type, 0, type->ref->c);
- p.flex_array_ref = type->ref;
-
- } else if (has_init && (type->t & VT_BTYPE) == VT_STRUCT) {
- Sym *field = type->ref->next;
- if (field) {
- while (field->next)
- field = field->next;
- if (field->type.t & VT_ARRAY && field->type.ref->c < 0) {
- flexible_array = field;
- p.flex_array_ref = field->type.ref;
- size = -1;
- }
- }
- }
-
- if (size < 0) {
- /* If unknown size, do a dry-run 1st pass */
- if (!has_init)
- tcc_error("unknown type size");
- if (has_init == 2) {
- /* only get strings */
- init_str = tok_str_alloc();
- while (tok == TOK_STR || tok == TOK_LSTR) {
- tok_str_add_tok(init_str);
- next();
- }
- tok_str_add(init_str, -1);
- tok_str_add(init_str, 0);
- } else
- skip_or_save_block(&init_str);
- unget_tok(0);
-
- /* compute size */
- begin_macro(init_str, 1);
- next();
- decl_initializer(&p, type, 0, DIF_FIRST | DIF_SIZE_ONLY);
- /* prepare second initializer parsing */
- macro_ptr = init_str->str;
- next();
-
- /* if still unknown size, error */
- size = type_size(type, &align);
- if (size < 0)
- tcc_error("unknown type size");
-
- /* If there's a flex member and it was used in the initializer
- adjust size. */
- if (flexible_array && flexible_array->type.ref->c > 0)
- size += flexible_array->type.ref->c
- * pointed_size(&flexible_array->type);
- }
-
- /* take into account specified alignment if bigger */
- if (ad->a.aligned) {
- int speca = 1 << (ad->a.aligned - 1);
- if (speca > align)
- align = speca;
- } else if (ad->a.packed) {
- align = 1;
- }
-
- if (!v && NODATA_WANTED)
- size = 0, align = 1;
-
- if ((r & VT_VALMASK) == VT_LOCAL) {
- sec = NULL;
-#ifdef CONFIG_TCC_BCHECK
- if (bcheck && v) {
- /* add padding between stack variables for bound checking */
- loc -= align;
- }
-#endif
- loc = (loc - size) & -align;
- addr = loc;
- p.local_offset = addr + size;
-#ifdef CONFIG_TCC_BCHECK
- if (bcheck && v) {
- /* add padding between stack variables for bound checking */
- loc -= align;
- }
-#endif
- if (v) {
- /* local variable */
-#ifdef CONFIG_TCC_ASM
- if (ad->asm_label) {
- int reg = asm_parse_regvar(ad->asm_label);
- if (reg >= 0)
- r = (r & ~VT_VALMASK) | reg;
- }
-#endif
- sym = sym_push(v, type, r, addr);
- if (ad->cleanup_func) {
- Sym *cls = sym_push2(&all_cleanups,
- SYM_FIELD | ++cur_scope->cl.n, 0, 0);
- cls->prev_tok = sym;
- cls->next = ad->cleanup_func;
- cls->ncl = cur_scope->cl.s;
- cur_scope->cl.s = cls;
- }
-
- sym->a = ad->a;
- } else {
- /* push local reference */
- vset(type, r, addr);
- }
- } else {
- sym = NULL;
- if (v && global) {
- /* see if the symbol was already defined */
- sym = sym_find(v);
- if (sym) {
- if (p.flex_array_ref && (sym->type.t & type->t & VT_ARRAY)
- && sym->type.ref->c > type->ref->c) {
- /* flex array was already declared with explicit size
- extern int arr[10];
- int arr[] = { 1,2,3 }; */
- type->ref->c = sym->type.ref->c;
- size = type_size(type, &align);
- }
- patch_storage(sym, ad, type);
- /* we accept several definitions of the same global variable. */
- if (!has_init && sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)
- goto no_alloc;
- }
- }
-
- /* allocate symbol in corresponding section */
- sec = ad->section;
- if (!sec) {
- CType *tp = type;
- while ((tp->t & (VT_BTYPE|VT_ARRAY)) == (VT_PTR|VT_ARRAY))
- tp = &tp->ref->type;
- if (tp->t & VT_CONSTANT) {
- sec = rodata_section;
- } else if (has_init) {
- sec = data_section;
- /*if (tcc_state->g_debug & 4)
- tcc_warning("rw data: %s", get_tok_str(v, 0));*/
- } else if (tcc_state->nocommon)
- sec = bss_section;
- }
-
- if (sec) {
- addr = section_add(sec, size, align);
-#ifdef CONFIG_TCC_BCHECK
- /* add padding if bound check */
- if (bcheck)
- section_add(sec, 1, 1);
-#endif
- } else {
- addr = align; /* SHN_COMMON is special, symbol value is align */
- sec = common_section;
- }
-
- if (v) {
- if (!sym) {
- sym = sym_push(v, type, r | VT_SYM, 0);
- patch_storage(sym, ad, NULL);
- }
- /* update symbol definition */
- put_extern_sym(sym, sec, addr, size);
- } else {
- /* push global reference */
- vpush_ref(type, sec, addr, size);
- sym = vtop->sym;
- vtop->r |= r;
- }
-
-#ifdef CONFIG_TCC_BCHECK
- /* handles bounds now because the symbol must be defined
- before for the relocation */
- if (bcheck) {
- addr_t *bounds_ptr;
-
- greloca(bounds_section, sym, bounds_section->data_offset, R_DATA_PTR, 0);
- /* then add global bound info */
- bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(addr_t));
- bounds_ptr[0] = 0; /* relocated */
- bounds_ptr[1] = size;
- }
-#endif
- }
-
- if (type->t & VT_VLA) {
- int a;
-
- if (NODATA_WANTED)
- goto no_alloc;
-
- /* save before-VLA stack pointer if needed */
- if (cur_scope->vla.num == 0) {
- if (cur_scope->prev && cur_scope->prev->vla.num) {
- cur_scope->vla.locorig = cur_scope->prev->vla.loc;
- } else {
- gen_vla_sp_save(loc -= PTR_SIZE);
- cur_scope->vla.locorig = loc;
- }
- }
-
- vpush_type_size(type, &a);
- gen_vla_alloc(type, a);
-#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
- /* on _WIN64, because of the function args scratch area, the
- result of alloca differs from RSP and is returned in RAX. */
- gen_vla_result(addr), addr = (loc -= PTR_SIZE);
-#endif
- gen_vla_sp_save(addr);
- cur_scope->vla.loc = addr;
- cur_scope->vla.num++;
- } else if (has_init) {
- p.sec = sec;
- decl_initializer(&p, type, addr, DIF_FIRST);
- /* patch flexible array member size back to -1, */
- /* for possible subsequent similar declarations */
- if (flexible_array)
- flexible_array->type.ref->c = -1;
- }
-
- no_alloc:
- /* restore parse state if needed */
- if (init_str) {
- end_macro();
- next();
- }
-
- nocode_wanted = saved_nocode_wanted;
-}
-
-/* generate vla code saved in post_type() */
-static void func_vla_arg_code(Sym *arg)
-{
- int align;
- TokenString *vla_array_tok = NULL;
-
- if (arg->type.ref)
- func_vla_arg_code(arg->type.ref);
-
- if ((arg->type.t & VT_VLA) && arg->type.ref->vla_array_str) {
- loc -= type_size(&int_type, &align);
- loc &= -align;
- arg->type.ref->c = loc;
-
- unget_tok(0);
- vla_array_tok = tok_str_alloc();
- vla_array_tok->str = arg->type.ref->vla_array_str;
- begin_macro(vla_array_tok, 1);
- next();
- gexpr();
- end_macro();
- next();
- vpush_type_size(&arg->type.ref->type, &align);
- gen_op('*');
- vset(&int_type, VT_LOCAL|VT_LVAL, arg->type.ref->c);
- vswap();
- vstore();
- vpop();
- }
-}
-
-static void func_vla_arg(Sym *sym)
-{
- Sym *arg;
-
- for (arg = sym->type.ref->next; arg; arg = arg->next)
- if (arg->type.t & VT_VLA)
- func_vla_arg_code(arg);
-}
-
-/* parse a function defined by symbol 'sym' and generate its code in
- 'cur_text_section' */
-static void gen_function(Sym *sym)
-{
- struct scope f = { 0 };
- cur_scope = root_scope = &f;
- nocode_wanted = 0;
- ind = cur_text_section->data_offset;
- if (sym->a.aligned) {
- size_t newoff = section_add(cur_text_section, 0,
- 1 << (sym->a.aligned - 1));
- gen_fill_nops(newoff - ind);
- }
- /* NOTE: we patch the symbol size later */
- put_extern_sym(sym, cur_text_section, ind, 0);
- if (sym->type.ref->f.func_ctor)
- add_array (tcc_state, ".init_array", sym->c);
- if (sym->type.ref->f.func_dtor)
- add_array (tcc_state, ".fini_array", sym->c);
-
- funcname = get_tok_str(sym->v, NULL);
- func_ind = ind;
- func_vt = sym->type.ref->type;
- func_var = sym->type.ref->f.func_type == FUNC_ELLIPSIS;
-
- /* put debug symbol */
- tcc_debug_funcstart(tcc_state, sym);
- /* push a dummy symbol to enable local sym storage */
- sym_push2(&local_stack, SYM_FIELD, 0, 0);
- local_scope = 1; /* for function parameters */
- gfunc_prolog(sym);
- tcc_debug_prolog_epilog(tcc_state, 0);
- local_scope = 0;
- rsym = 0;
- clear_temp_local_var_list();
- func_vla_arg(sym);
- block(0);
- gsym(rsym);
- nocode_wanted = 0;
- /* reset local stack */
- pop_local_syms(NULL, 0);
- tcc_debug_prolog_epilog(tcc_state, 1);
- gfunc_epilog();
- cur_text_section->data_offset = ind;
- local_scope = 0;
- label_pop(&global_label_stack, NULL, 0);
- sym_pop(&all_cleanups, NULL, 0);
- /* patch symbol size */
- elfsym(sym)->st_size = ind - func_ind;
- /* end of function */
- tcc_debug_funcend(tcc_state, ind - func_ind);
- /* It's better to crash than to generate wrong code */
- cur_text_section = NULL;
- funcname = ""; /* for safety */
- func_vt.t = VT_VOID; /* for safety */
- func_var = 0; /* for safety */
- ind = 0; /* for safety */
- func_ind = -1;
- nocode_wanted = DATA_ONLY_WANTED;
- check_vstack();
- /* do this after funcend debug info */
- next();
-}
-
-static void gen_inline_functions(TCCState *s)
-{
- Sym *sym;
- int inline_generated, i;
- struct InlineFunc *fn;
-
- tcc_open_bf(s, ":inline:", 0);
- /* iterate while inline function are referenced */
- do {
- inline_generated = 0;
- for (i = 0; i < s->nb_inline_fns; ++i) {
- fn = s->inline_fns[i];
- sym = fn->sym;
- if (sym && (sym->c || !(sym->type.t & VT_INLINE))) {
- /* the function was used or forced (and then not internal):
- generate its code and convert it to a normal function */
- fn->sym = NULL;
- tcc_debug_putfile(s, fn->filename);
- begin_macro(fn->func_str, 1);
- next();
- cur_text_section = text_section;
- gen_function(sym);
- end_macro();
-
- inline_generated = 1;
- }
- }
- } while (inline_generated);
- tcc_close();
-}
-
-static void free_inline_functions(TCCState *s)
-{
- int i;
- /* free tokens of unused inline functions */
- for (i = 0; i < s->nb_inline_fns; ++i) {
- struct InlineFunc *fn = s->inline_fns[i];
- if (fn->sym)
- tok_str_free(fn->func_str);
- }
- dynarray_reset(&s->inline_fns, &s->nb_inline_fns);
-}
-
-static void do_Static_assert(void)
-{
- int c;
- const char *msg;
-
- next();
- skip('(');
- c = expr_const();
- msg = "_Static_assert fail";
- if (tok == ',') {
- next();
- msg = parse_mult_str("string constant")->data;
- }
- skip(')');
- if (c == 0)
- tcc_error("%s", msg);
- skip(';');
-}
-
-/* 'l' is VT_LOCAL or VT_CONST to define default storage type
- or VT_CMP if parsing old style parameter list
- or VT_JMP if parsing c99 for decl: for (int i = 0, ...) */
-static int decl(int l)
-{
- int v, has_init, r, oldint;
- CType type, btype;
- Sym *sym;
- AttributeDef ad, adbase;
-
- while (1) {
-
- if (tok == TOK_STATIC_ASSERT) {
- do_Static_assert();
- continue;
- }
-
- oldint = 0;
- if (!parse_btype(&btype, &adbase, l == VT_LOCAL)) {
- if (l == VT_JMP)
- return 0;
- /* skip redundant ';' if not in old parameter decl scope */
- if (tok == ';' && l != VT_CMP) {
- next();
- continue;
- }
- if (l != VT_CONST)
- break;
- if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
- /* global asm block */
- asm_global_instr();
- continue;
- }
- if (tok >= TOK_UIDENT) {
- /* special test for old K&R protos without explicit int
- type. Only accepted when defining global data */
- btype.t = VT_INT;
- oldint = 1;
- } else {
- if (tok != TOK_EOF)
- expect("declaration");
- break;
- }
- }
-
- if (tok == ';') {
- if ((btype.t & VT_BTYPE) == VT_STRUCT) {
- v = btype.ref->v;
- if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM)
- tcc_warning("unnamed struct/union that defines no instances");
- next();
- continue;
- }
- if (IS_ENUM(btype.t)) {
- next();
- continue;
- }
- }
-
- while (1) { /* iterate thru each declaration */
- type = btype;
- ad = adbase;
- type_decl(&type, &ad, &v, TYPE_DIRECT);
-#if 0
- {
- char buf[500];
- type_to_str(buf, sizeof(buf), &type, get_tok_str(v, NULL));
- printf("type = '%s'\n", buf);
- }
-#endif
- if ((type.t & VT_BTYPE) == VT_FUNC) {
- if ((type.t & VT_STATIC) && (l != VT_CONST))
- tcc_error("function without file scope cannot be static");
- /* if old style function prototype, we accept a
- declaration list */
- sym = type.ref;
- if (sym->f.func_type == FUNC_OLD && l == VT_CONST) {
- func_vt = type;
- decl(VT_CMP);
- }
-#if defined TCC_TARGET_MACHO || defined TARGETOS_ANDROID
- if (sym->f.func_alwinl
- && ((type.t & (VT_EXTERN | VT_INLINE))
- == (VT_EXTERN | VT_INLINE))) {
- /* always_inline functions must be handled as if they
- don't generate multiple global defs, even if extern
- inline, i.e. GNU inline semantics for those. Rewrite
- them into static inline. */
- type.t &= ~VT_EXTERN;
- type.t |= VT_STATIC;
- }
-#endif
- /* always compile 'extern inline' */
- if (type.t & VT_EXTERN)
- type.t &= ~VT_INLINE;
-
- } else if (oldint) {
- tcc_warning("type defaults to int");
- }
-
- if (gnu_ext && (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
- ad.asm_label = asm_label_instr();
- /* parse one last attribute list, after asm label */
- parse_attribute(&ad);
- #if 0
- /* gcc does not allow __asm__("label") with function definition,
- but why not ... */
- if (tok == '{')
- expect(";");
- #endif
- }
-
-#ifdef TCC_TARGET_PE
- if (ad.a.dllimport || ad.a.dllexport) {
- if (type.t & VT_STATIC)
- tcc_error("cannot have dll linkage with static");
- if (type.t & VT_TYPEDEF) {
- tcc_warning("'%s' attribute ignored for typedef",
- ad.a.dllimport ? (ad.a.dllimport = 0, "dllimport") :
- (ad.a.dllexport = 0, "dllexport"));
- } else if (ad.a.dllimport) {
- if ((type.t & VT_BTYPE) == VT_FUNC)
- ad.a.dllimport = 0;
- else
- type.t |= VT_EXTERN;
- }
- }
-#endif
- if (tok == '{') {
- if (l != VT_CONST)
- tcc_error("cannot use local functions");
- if ((type.t & VT_BTYPE) != VT_FUNC)
- expect("function definition");
-
- /* reject abstract declarators in function definition
- make old style params without decl have int type */
- sym = type.ref;
- while ((sym = sym->next) != NULL) {
- if (!(sym->v & ~SYM_FIELD))
- expect("identifier");
- if (sym->type.t == VT_VOID)
- sym->type = int_type;
- }
-
- /* apply post-declaraton attributes */
- merge_funcattr(&type.ref->f, &ad.f);
-
- /* put function symbol */
- type.t &= ~VT_EXTERN;
- sym = external_sym(v, &type, 0, &ad);
-
- /* static inline functions are just recorded as a kind
- of macro. Their code will be emitted at the end of
- the compilation unit only if they are used */
- if (sym->type.t & VT_INLINE) {
- struct InlineFunc *fn;
- fn = tcc_malloc(sizeof *fn + strlen(file->filename));
- strcpy(fn->filename, file->filename);
- fn->sym = sym;
- skip_or_save_block(&fn->func_str);
- dynarray_add(&tcc_state->inline_fns,
- &tcc_state->nb_inline_fns, fn);
- } else {
- /* compute text section */
- cur_text_section = ad.section;
- if (!cur_text_section)
- cur_text_section = text_section;
- gen_function(sym);
- }
- break;
- } else {
- if (l == VT_CMP) {
- /* find parameter in function parameter list */
- for (sym = func_vt.ref->next; sym; sym = sym->next)
- if ((sym->v & ~SYM_FIELD) == v)
- goto found;
- tcc_error("declaration for parameter '%s' but no such parameter",
- get_tok_str(v, NULL));
- found:
- if (type.t & VT_STORAGE) /* 'register' is okay */
- tcc_error("storage class specified for '%s'",
- get_tok_str(v, NULL));
- if (sym->type.t != VT_VOID)
- tcc_error("redefinition of parameter '%s'",
- get_tok_str(v, NULL));
- convert_parameter_type(&type);
- sym->type = type;
- } else if (type.t & VT_TYPEDEF) {
- /* save typedefed type */
- /* XXX: test storage specifiers ? */
- sym = sym_find(v);
- if (sym && sym->sym_scope == local_scope) {
- if (!is_compatible_types(&sym->type, &type)
- || !(sym->type.t & VT_TYPEDEF))
- tcc_error("incompatible redefinition of '%s'",
- get_tok_str(v, NULL));
- sym->type = type;
- } else {
- sym = sym_push(v, &type, 0, 0);
- }
- sym->a = ad.a;
- if ((type.t & VT_BTYPE) == VT_FUNC)
- merge_funcattr(&sym->type.ref->f, &ad.f);
- if (debug_modes)
- tcc_debug_typedef (tcc_state, sym);
- } else if ((type.t & VT_BTYPE) == VT_VOID
- && !(type.t & VT_EXTERN)) {
- tcc_error("declaration of void object");
- } else {
- r = 0;
- if ((type.t & VT_BTYPE) == VT_FUNC) {
- /* external function definition */
- /* specific case for func_call attribute */
- merge_funcattr(&type.ref->f, &ad.f);
- } else if (!(type.t & VT_ARRAY)) {
- /* not lvalue if array */
- r |= VT_LVAL;
- }
- has_init = (tok == '=');
- if (has_init && (type.t & VT_VLA))
- tcc_error("variable length array cannot be initialized");
- if (((type.t & VT_EXTERN) && (!has_init || l != VT_CONST))
- || (type.t & VT_BTYPE) == VT_FUNC
- /* as with GCC, uninitialized global arrays with no size
- are considered extern: */
- || ((type.t & VT_ARRAY) && !has_init
- && l == VT_CONST && type.ref->c < 0)
- ) {
- /* external variable or function */
- type.t |= VT_EXTERN;
- sym = external_sym(v, &type, r, &ad);
- if (ad.alias_target) {
- /* Aliases need to be emitted when their target
- symbol is emitted, even if perhaps unreferenced.
- We only support the case where the base is
- already defined, otherwise we would need
- deferring to emit the aliases until the end of
- the compile unit. */
- Sym *alias_target = sym_find(ad.alias_target);
- ElfSym *esym = elfsym(alias_target);
- if (!esym)
- tcc_error("unsupported forward __alias__ attribute");
- put_extern_sym2(sym, esym->st_shndx,
- esym->st_value, esym->st_size, 1);
- }
- } else {
- if (l == VT_CONST || (type.t & VT_STATIC))
- r |= VT_CONST;
- else
- r |= VT_LOCAL;
- if (has_init)
- next();
- else if (l == VT_CONST)
- /* uninitialized global variables may be overridden */
- type.t |= VT_EXTERN;
- decl_initializer_alloc(&type, &ad, r, has_init, v, l == VT_CONST);
- }
- }
- if (tok != ',') {
- if (l == VT_JMP)
- return 1;
- skip(';');
- break;
- }
- next();
- }
- }
- }
- return 0;
-}
-
-/* ------------------------------------------------------------------------- */
-#undef gjmp_addr
-#undef gjmp
-/* ------------------------------------------------------------------------- */
diff --git a/tinycc/tcclib.h b/tinycc/tcclib.h
deleted file mode 100644
index 8d59e4c..0000000
--- a/tinycc/tcclib.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* Simple libc header for TCC
- *
- * Add any function you want from the libc there. This file is here
- * only for your convenience so that you do not need to put the whole
- * glibc include files on your floppy disk
- */
-#ifndef _TCCLIB_H
-#define _TCCLIB_H
-
-#include <stddef.h>
-#include <stdarg.h>
-
-/* stdlib.h */
-void *calloc(size_t nmemb, size_t size);
-void *malloc(size_t size);
-void free(void *ptr);
-void *realloc(void *ptr, size_t size);
-int atoi(const char *nptr);
-long int strtol(const char *nptr, char **endptr, int base);
-unsigned long int strtoul(const char *nptr, char **endptr, int base);
-void exit(int);
-
-/* stdio.h */
-typedef struct __FILE FILE;
-#define EOF (-1)
-extern FILE *stdin;
-extern FILE *stdout;
-extern FILE *stderr;
-FILE *fopen(const char *path, const char *mode);
-FILE *fdopen(int fildes, const char *mode);
-FILE *freopen(const char *path, const char *mode, FILE *stream);
-int fclose(FILE *stream);
-size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
-size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
-int fgetc(FILE *stream);
-char *fgets(char *s, int size, FILE *stream);
-int getc(FILE *stream);
-int getchar(void);
-char *gets(char *s);
-int ungetc(int c, FILE *stream);
-int fflush(FILE *stream);
-int putchar (int c);
-
-int printf(const char *format, ...);
-int fprintf(FILE *stream, const char *format, ...);
-int sprintf(char *str, const char *format, ...);
-int snprintf(char *str, size_t size, const char *format, ...);
-int asprintf(char **strp, const char *format, ...);
-int dprintf(int fd, const char *format, ...);
-int vprintf(const char *format, va_list ap);
-int vfprintf(FILE *stream, const char *format, va_list ap);
-int vsprintf(char *str, const char *format, va_list ap);
-int vsnprintf(char *str, size_t size, const char *format, va_list ap);
-int vasprintf(char **strp, const char *format, va_list ap);
-int vdprintf(int fd, const char *format, va_list ap);
-
-void perror(const char *s);
-
-/* string.h */
-char *strcat(char *dest, const char *src);
-char *strchr(const char *s, int c);
-char *strrchr(const char *s, int c);
-char *strcpy(char *dest, const char *src);
-void *memcpy(void *dest, const void *src, size_t n);
-void *memmove(void *dest, const void *src, size_t n);
-void *memset(void *s, int c, size_t n);
-char *strdup(const char *s);
-size_t strlen(const char *s);
-
-/* dlfcn.h */
-#define RTLD_LAZY 0x001
-#define RTLD_NOW 0x002
-#define RTLD_GLOBAL 0x100
-
-void *dlopen(const char *filename, int flag);
-const char *dlerror(void);
-void *dlsym(void *handle, char *symbol);
-int dlclose(void *handle);
-
-#endif /* _TCCLIB_H */
diff --git a/tinycc/tccmacho.c b/tinycc/tccmacho.c
deleted file mode 100644
index 4d282dd..0000000
--- a/tinycc/tccmacho.c
+++ /dev/null
@@ -1,2480 +0,0 @@
-/*
- * Mach-O file handling for TCC
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-#include "tcc.h"
-
-/* In order to make life easy for us we are generating Mach-O files which
- don't make use of some modern features, but which aren't entirely classic
- either in that they do use some modern features. We're also only
- generating 64bit Mach-O files, and only native endian at that.
-
- In particular we're generating executables that don't make use of
- DYLD_INFO for dynamic linking info, as that requires us building a
- trie of exported names. We're simply using classic symbol tables which
- are still supported by modern dyld.
-
- But we do use LC_MAIN, which is a "modern" feature in order to not have
- to setup our own crt code. We're not using lazy linking, so even function
- calls are resolved at startup. */
-
-#if !defined TCC_TARGET_X86_64 && !defined TCC_TARGET_ARM64
-#error Platform not supported
-#endif
-
-/* XXX: this file uses tcc_error() to the effect of exit(1) */
-#undef _tcc_error
-
-#define DEBUG_MACHO 0
-#define dprintf if (DEBUG_MACHO) printf
-
-#define MH_EXECUTE (0x2)
-#define MH_DYLDLINK (0x4)
-#define MH_DYLIB (0x6)
-#define MH_PIE (0x200000)
-
-#define CPU_SUBTYPE_LIB64 (0x80000000)
-#define CPU_SUBTYPE_X86_ALL (3)
-#define CPU_SUBTYPE_ARM64_ALL (0)
-
-#define CPU_ARCH_ABI64 (0x01000000)
-
-#define CPU_TYPE_X86 (7)
-#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64)
-#define CPU_TYPE_ARM (12)
-#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
-
-struct fat_header {
- uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */
- uint32_t nfat_arch; /* number of structs that follow */
-};
-
-struct fat_arch {
- int cputype; /* cpu specifier (int) */
- int cpusubtype; /* machine specifier (int) */
- uint32_t offset; /* file offset to this object file */
- uint32_t size; /* size of this object file */
- uint32_t align; /* alignment as a power of 2 */
-};
-
-#define FAT_MAGIC 0xcafebabe
-#define FAT_CIGAM 0xbebafeca
-#define FAT_MAGIC_64 0xcafebabf
-#define FAT_CIGAM_64 0xbfbafeca
-
-struct mach_header {
- uint32_t magic; /* mach magic number identifier */
- int cputype; /* cpu specifier */
- int cpusubtype; /* machine specifier */
- uint32_t filetype; /* type of file */
- uint32_t ncmds; /* number of load commands */
- uint32_t sizeofcmds; /* the size of all the load commands */
- uint32_t flags; /* flags */
-};
-
-struct mach_header_64 {
- struct mach_header mh;
- uint32_t reserved; /* reserved, pad to 64bit */
-};
-
-/* Constant for the magic field of the mach_header (32-bit architectures) */
-#define MH_MAGIC 0xfeedface /* the mach magic number */
-#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */
-#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
-#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */
-
-struct load_command {
- uint32_t cmd; /* type of load command */
- uint32_t cmdsize; /* total size of command in bytes */
-};
-
-#define LC_REQ_DYLD 0x80000000
-#define LC_SYMTAB 0x2
-#define LC_DYSYMTAB 0xb
-#define LC_LOAD_DYLIB 0xc
-#define LC_ID_DYLIB 0xd
-#define LC_LOAD_DYLINKER 0xe
-#define LC_SEGMENT_64 0x19
-#define LC_RPATH (0x1c | LC_REQ_DYLD)
-#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD)
-#define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD)
-#define LC_MAIN (0x28|LC_REQ_DYLD)
-#define LC_SOURCE_VERSION 0x2A
-#define LC_BUILD_VERSION 0x32
-#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD)
-#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD)
-
-#define SG_READ_ONLY 0x10 /* This segment is made read-only after fixups */
-
-typedef int vm_prot_t;
-
-struct segment_command_64 { /* for 64-bit architectures */
- uint32_t cmd; /* LC_SEGMENT_64 */
- uint32_t cmdsize; /* includes sizeof section_64 structs */
- char segname[16]; /* segment name */
- uint64_t vmaddr; /* memory address of this segment */
- uint64_t vmsize; /* memory size of this segment */
- uint64_t fileoff; /* file offset of this segment */
- uint64_t filesize; /* amount to map from the file */
- vm_prot_t maxprot; /* maximum VM protection */
- vm_prot_t initprot; /* initial VM protection */
- uint32_t nsects; /* number of sections in segment */
- uint32_t flags; /* flags */
-};
-
-struct section_64 { /* for 64-bit architectures */
- char sectname[16]; /* name of this section */
- char segname[16]; /* segment this section goes in */
- uint64_t addr; /* memory address of this section */
- uint64_t size; /* size in bytes of this section */
- uint32_t offset; /* file offset of this section */
- uint32_t align; /* section alignment (power of 2) */
- uint32_t reloff; /* file offset of relocation entries */
- uint32_t nreloc; /* number of relocation entries */
- uint32_t flags; /* flags (section type and attributes)*/
- uint32_t reserved1; /* reserved (for offset or index) */
- uint32_t reserved2; /* reserved (for count or sizeof) */
- uint32_t reserved3; /* reserved */
-};
-
-enum {
- DYLD_CHAINED_IMPORT = 1,
-};
-
-struct dyld_chained_fixups_header {
- uint32_t fixups_version; ///< 0
- uint32_t starts_offset; ///< Offset of dyld_chained_starts_in_image.
- uint32_t imports_offset; ///< Offset of imports table in chain_data.
- uint32_t symbols_offset; ///< Offset of symbol strings in chain_data.
- uint32_t imports_count; ///< Number of imported symbol names.
- uint32_t imports_format; ///< DYLD_CHAINED_IMPORT*
- uint32_t symbols_format; ///< 0 => uncompressed, 1 => zlib compressed
-};
-
-struct dyld_chained_starts_in_image
-{
- uint32_t seg_count;
- uint32_t seg_info_offset[1]; // each entry is offset into this struct for that segment
- // followed by pool of dyld_chain_starts_in_segment data
-};
-
-enum {
- DYLD_CHAINED_PTR_64 = 2, // target is vmaddr
- DYLD_CHAINED_PTR_64_OFFSET = 6, // target is vm offset
-};
-
-enum {
- DYLD_CHAINED_PTR_START_NONE = 0xFFFF, // used in page_start[] to denote a page with no fixups
-};
-
-#define SEG_PAGE_SIZE 16384
-
-struct dyld_chained_starts_in_segment
-{
- uint32_t size; // size of this (amount kernel needs to copy)
- uint16_t page_size; // 0x1000 or 0x4000
- uint16_t pointer_format; // DYLD_CHAINED_PTR_*
- uint64_t segment_offset; // offset in memory to start of segment
- uint32_t max_valid_pointer; // for 32-bit OS, any value beyond this is not a pointer
- uint16_t page_count; // how many pages are in array
- uint16_t page_start[1]; // each entry is offset in each page of first element in chain
- // or DYLD_CHAINED_PTR_START_NONE if no fixups on page
-};
-
-enum BindSpecialDylib {
- BIND_SPECIAL_DYLIB_FLAT_LOOKUP = -2,
-};
-
-struct dyld_chained_import
-{
- uint32_t lib_ordinal : 8,
- weak_import : 1,
- name_offset : 23;
-};
-
-struct dyld_chained_ptr_64_rebase
-{
- uint64_t target : 36, // vmaddr, 64GB max image size
- high8 : 8, // top 8 bits set to this after slide added
- reserved : 7, // all zeros
- next : 12, // 4-byte stride
- bind : 1; // == 0
-};
-
-struct dyld_chained_ptr_64_bind
-{
- uint64_t ordinal : 24,
- addend : 8, // 0 thru 255
- reserved : 19, // all zeros
- next : 12, // 4-byte stride
- bind : 1; // == 1
-};
-
-#define S_REGULAR 0x0
-#define S_ZEROFILL 0x1
-#define S_NON_LAZY_SYMBOL_POINTERS 0x6
-#define S_LAZY_SYMBOL_POINTERS 0x7
-#define S_SYMBOL_STUBS 0x8
-#define S_MOD_INIT_FUNC_POINTERS 0x9
-#define S_MOD_TERM_FUNC_POINTERS 0xa
-
-#define S_ATTR_PURE_INSTRUCTIONS 0x80000000
-#define S_ATTR_SOME_INSTRUCTIONS 0x00000400
-#define S_ATTR_DEBUG 0x02000000
-
-
-typedef uint32_t lc_str;
-
-struct dylib_command {
- uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB,
- LC_REEXPORT_DYLIB */
- uint32_t cmdsize; /* includes pathname string */
- lc_str name; /* library's path name */
- uint32_t timestamp; /* library's build time stamp */
- uint32_t current_version; /* library's current version number */
- uint32_t compatibility_version; /* library's compatibility vers number*/
-};
-
-struct rpath_command {
- uint32_t cmd; /* LC_RPATH */
- uint32_t cmdsize; /* includes string */
- lc_str path; /* path to add to run path */
-};
-
-struct dylinker_command {
- uint32_t cmd; /* LC_ID_DYLINKER, LC_LOAD_DYLINKER or
- LC_DYLD_ENVIRONMENT */
- uint32_t cmdsize; /* includes pathname string */
- lc_str name; /* dynamic linker's path name */
-};
-
-struct linkedit_data_command {
- uint32_t cmd; /* LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO,
- LC_FUNCTION_STARTS, LC_DATA_IN_CODE,
- LC_DYLIB_CODE_SIGN_DRS,
- LC_LINKER_OPTIMIZATION_HINT,
- LC_DYLD_EXPORTS_TRIE, or
- LC_DYLD_CHAINED_FIXUPS. */
- uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */
- uint32_t dataoff; /* file offset of data in __LINKEDIT segment */
- uint32_t datasize; /* file size of data in __LINKEDIT segment */
-};
-
-#define PLATFORM_MACOS 1
-
-struct build_version_command {
- uint32_t cmd; /* LC_BUILD_VERSION */
- uint32_t cmdsize; /* sizeof(struct build_version_command) plus */
- /* ntools * sizeof(struct build_tool_version) */
- uint32_t platform; /* platform */
- uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
- uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
- uint32_t ntools; /* number of tool entries following this */
-};
-
-struct source_version_command {
- uint32_t cmd; /* LC_SOURCE_VERSION */
- uint32_t cmdsize; /* 16 */
- uint64_t version; /* A.B.C.D.E packed as a24.b10.c10.d10.e10 */
-};
-
-struct symtab_command {
- uint32_t cmd; /* LC_SYMTAB */
- uint32_t cmdsize; /* sizeof(struct symtab_command) */
- uint32_t symoff; /* symbol table offset */
- uint32_t nsyms; /* number of symbol table entries */
- uint32_t stroff; /* string table offset */
- uint32_t strsize; /* string table size in bytes */
-};
-
-struct dysymtab_command {
- uint32_t cmd; /* LC_DYSYMTAB */
- uint32_t cmdsize; /* sizeof(struct dysymtab_command) */
-
- uint32_t ilocalsym; /* index to local symbols */
- uint32_t nlocalsym; /* number of local symbols */
-
- uint32_t iextdefsym;/* index to externally defined symbols */
- uint32_t nextdefsym;/* number of externally defined symbols */
-
- uint32_t iundefsym; /* index to undefined symbols */
- uint32_t nundefsym; /* number of undefined symbols */
-
- uint32_t tocoff; /* file offset to table of contents */
- uint32_t ntoc; /* number of entries in table of contents */
-
- uint32_t modtaboff; /* file offset to module table */
- uint32_t nmodtab; /* number of module table entries */
-
- uint32_t extrefsymoff; /* offset to referenced symbol table */
- uint32_t nextrefsyms; /* number of referenced symbol table entries */
-
- uint32_t indirectsymoff;/* file offset to the indirect symbol table */
- uint32_t nindirectsyms; /* number of indirect symbol table entries */
-
- uint32_t extreloff; /* offset to external relocation entries */
- uint32_t nextrel; /* number of external relocation entries */
- uint32_t locreloff; /* offset to local relocation entries */
- uint32_t nlocrel; /* number of local relocation entries */
-};
-
-#define BIND_OPCODE_DONE 0x00
-#define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30
-#define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40
-#define BIND_OPCODE_SET_TYPE_IMM 0x50
-#define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70
-#define BIND_OPCODE_DO_BIND 0x90
-
-#define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1
-
-#define BIND_TYPE_POINTER 1
-#define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2
-
-#define REBASE_OPCODE_DONE 0x00
-#define REBASE_OPCODE_SET_TYPE_IMM 0x10
-#define REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x20
-#define REBASE_OPCODE_DO_REBASE_IMM_TIMES 0x50
-
-#define REBASE_TYPE_POINTER 1
-
-#define EXPORT_SYMBOL_FLAGS_KIND_REGULAR 0x00
-#define EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE 0x02
-#define EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION 0x04
-
-struct dyld_info_command {
- uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */
- uint32_t cmdsize; /* sizeof(struct dyld_info_command) */
- uint32_t rebase_off; /* file offset to rebase info */
- uint32_t rebase_size; /* size of rebase info */
- uint32_t bind_off; /* file offset to binding info */
- uint32_t bind_size; /* size of binding info */
- uint32_t weak_bind_off; /* file offset to weak binding info */
- uint32_t weak_bind_size; /* size of weak binding info */
- uint32_t lazy_bind_off; /* file offset to lazy binding info */
- uint32_t lazy_bind_size; /* size of lazy binding infs */
- uint32_t export_off; /* file offset to lazy binding info */
- uint32_t export_size; /* size of lazy binding infs */
-};
-
-#define INDIRECT_SYMBOL_LOCAL 0x80000000
-
-struct entry_point_command {
- uint32_t cmd; /* LC_MAIN only used in MH_EXECUTE filetypes */
- uint32_t cmdsize; /* 24 */
- uint64_t entryoff; /* file (__TEXT) offset of main() */
- uint64_t stacksize;/* if not zero, initial stack size */
-};
-
-enum skind {
- sk_unknown = 0,
- sk_discard,
- sk_text,
- sk_stubs,
- sk_stub_helper,
- sk_ro_data,
- sk_uw_info,
- sk_nl_ptr, // non-lazy pointers, aka GOT
- sk_debug_info,
- sk_debug_abbrev,
- sk_debug_line,
- sk_debug_aranges,
- sk_debug_str,
- sk_debug_line_str,
- sk_stab,
- sk_stab_str,
- sk_la_ptr, // lazy pointers
- sk_init,
- sk_fini,
- sk_rw_data,
- sk_bss,
- sk_linkedit,
- sk_last
-};
-
-struct nlist_64 {
- uint32_t n_strx; /* index into the string table */
- uint8_t n_type; /* type flag, see below */
- uint8_t n_sect; /* section number or NO_SECT */
- uint16_t n_desc; /* see <mach-o/stab.h> */
- uint64_t n_value; /* value of this symbol (or stab offset) */
-};
-
-#define N_UNDF 0x0
-#define N_ABS 0x2
-#define N_EXT 0x1
-#define N_SECT 0xe
-
-#define N_WEAK_REF 0x0040
-#define N_WEAK_DEF 0x0080
-
-struct macho {
- struct mach_header_64 mh;
- int *seg2lc, nseg;
- struct load_command **lc;
- struct entry_point_command *ep;
- int nlc;
- struct {
- Section *s;
- int machosect;
- } sk_to_sect[sk_last];
- int *elfsectomacho;
- int *e2msym;
- Section *symtab, *strtab, *indirsyms, *stubs, *exports;
- uint32_t ilocal, iextdef, iundef;
- int stubsym, n_got, nr_plt;
- int segment[sk_last];
-#ifdef CONFIG_NEW_MACHO
- Section *chained_fixups;
- int n_bind;
- int n_bind_rebase;
- struct bind_rebase {
- int section;
- int bind;
- ElfW_Rel rel;
- } *bind_rebase;
-#else
- Section *rebase, *binding, *weak_binding, *lazy_binding;
- Section *stub_helper, *la_symbol_ptr;
- struct dyld_info_command *dyldinfo;
- int helpsym, lasym, dyld_private, dyld_stub_binder;
- int n_lazy_bind;
- struct s_lazy_bind {
- int section;
- int bind_offset;
- int la_symbol_offset;
- ElfW_Rel rel;
- } *s_lazy_bind;
- int n_rebase;
- struct s_rebase {
- int section;
- ElfW_Rel rel;
- } *s_rebase;
- int n_bind;
- struct bind {
- int section;
- ElfW_Rel rel;
- } *bind;
-#endif
-};
-
-#define SHT_LINKEDIT (SHT_LOOS + 42)
-#define SHN_FROMDLL (SHN_LOOS + 2) /* Symbol is undefined, comes from a DLL */
-
-static void * add_lc(struct macho *mo, uint32_t cmd, uint32_t cmdsize)
-{
- struct load_command *lc = tcc_mallocz(cmdsize);
- lc->cmd = cmd;
- lc->cmdsize = cmdsize;
- mo->lc = tcc_realloc(mo->lc, sizeof(mo->lc[0]) * (mo->nlc + 1));
- mo->lc[mo->nlc++] = lc;
- return lc;
-}
-
-static struct segment_command_64 * add_segment(struct macho *mo, const char *name)
-{
- struct segment_command_64 *sc = add_lc(mo, LC_SEGMENT_64, sizeof(*sc));
- strncpy(sc->segname, name, 16);
- mo->seg2lc = tcc_realloc(mo->seg2lc, sizeof(*mo->seg2lc) * (mo->nseg + 1));
- mo->seg2lc[mo->nseg++] = mo->nlc - 1;
- return sc;
-}
-
-static struct segment_command_64 * get_segment(struct macho *mo, int i)
-{
- return (struct segment_command_64 *) (mo->lc[mo->seg2lc[i]]);
-}
-
-static int add_section(struct macho *mo, struct segment_command_64 **_seg, const char *name)
-{
- struct segment_command_64 *seg = *_seg;
- int ret = seg->nsects;
- struct section_64 *sec;
- seg->nsects++;
- seg->cmdsize += sizeof(*sec);
- seg = tcc_realloc(seg, sizeof(*seg) + seg->nsects * sizeof(*sec));
- sec = (struct section_64*)((char*)seg + sizeof(*seg)) + ret;
- memset(sec, 0, sizeof(*sec));
- strncpy(sec->sectname, name, 16);
- strncpy(sec->segname, seg->segname, 16);
- *_seg = seg;
- return ret;
-}
-
-static struct section_64 *get_section(struct segment_command_64 *seg, int i)
-{
- return (struct section_64*)((char*)seg + sizeof(*seg)) + i;
-}
-
-static void * add_dylib(struct macho *mo, char *name)
-{
- struct dylib_command *lc;
- int sz = (sizeof(*lc) + strlen(name) + 1 + 7) & -8;
- lc = add_lc(mo, LC_LOAD_DYLIB, sz);
- lc->name = sizeof(*lc);
- strcpy((char*)lc + lc->name, name);
- lc->timestamp = 2;
- lc->current_version = 1 << 16;
- lc->compatibility_version = 1 << 16;
- return lc;
-}
-
-static int uleb128_size (unsigned long long value)
-{
- int size = 0;
-
- do {
- value >>= 7;
- size++;
- } while (value != 0);
- return size;
-}
-
-static void write_uleb128(Section *section, uint64_t value)
-{
- do {
- unsigned char byte = value & 0x7f;
- uint8_t *ptr = section_ptr_add(section, 1);
-
- value >>= 7;
- *ptr = byte | (value ? 0x80 : 0);
- } while (value != 0);
-}
-
-static void tcc_macho_add_destructor(TCCState *s1)
-{
- int init_sym, mh_execute_header, at_exit_sym;
- Section *s;
- ElfW_Rel *rel;
- uint8_t *ptr;
-
- mh_execute_header = put_elf_sym(s1->symtab, -4096, 0,
- ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT), 0,
- text_section->sh_num, "__mh_execute_header");
- s = find_section(s1, ".fini_array");
- if (s->data_offset == 0)
- return;
- init_sym = put_elf_sym(s1->symtab, text_section->data_offset, 0,
- ELFW(ST_INFO)(STB_LOCAL, STT_FUNC), 0,
- text_section->sh_num, "___GLOBAL_init_65535");
- at_exit_sym = put_elf_sym(s1->symtab, 0, 0,
- ELFW(ST_INFO)(STB_GLOBAL, STT_FUNC), 0,
- SHN_UNDEF, "___cxa_atexit");
-#ifdef TCC_TARGET_X86_64
- ptr = section_ptr_add(text_section, 4);
- ptr[0] = 0x55; // pushq %rbp
- ptr[1] = 0x48; // movq %rsp, %rbp
- ptr[2] = 0x89;
- ptr[3] = 0xe5;
- for_each_elem(s->reloc, 0, rel, ElfW_Rel) {
- int sym_index = ELFW(R_SYM)(rel->r_info);
-
- ptr = section_ptr_add(text_section, 26);
- ptr[0] = 0x48; // lea destructor(%rip),%rax
- ptr[1] = 0x8d;
- ptr[2] = 0x05;
- put_elf_reloca(s1->symtab, text_section,
- text_section->data_offset - 23,
- R_X86_64_PC32, sym_index, -4);
- ptr[7] = 0x48; // mov %rax,%rdi
- ptr[8] = 0x89;
- ptr[9] = 0xc7;
- ptr[10] = 0x31; // xorl %ecx, %ecx
- ptr[11] = 0xc9;
- ptr[12] = 0x89; // movl %ecx, %esi
- ptr[13] = 0xce;
- ptr[14] = 0x48; // lea mh_execute_header(%rip),%rdx
- ptr[15] = 0x8d;
- ptr[16] = 0x15;
- put_elf_reloca(s1->symtab, text_section,
- text_section->data_offset - 9,
- R_X86_64_PC32, mh_execute_header, -4);
- ptr[21] = 0xe8; // call __cxa_atexit
- put_elf_reloca(s1->symtab, text_section,
- text_section->data_offset - 4,
- R_X86_64_PLT32, at_exit_sym, -4);
- }
- ptr = section_ptr_add(text_section, 2);
- ptr[0] = 0x5d; // pop %rbp
- ptr[1] = 0xc3; // ret
-#elif defined TCC_TARGET_ARM64
- ptr = section_ptr_add(text_section, 8);
- write32le(ptr, 0xa9bf7bfd); // stp x29, x30, [sp, #-16]!
- write32le(ptr + 4, 0x910003fd); // mov x29, sp
- for_each_elem(s->reloc, 0, rel, ElfW_Rel) {
- int sym_index = ELFW(R_SYM)(rel->r_info);
-
- ptr = section_ptr_add(text_section, 24);
- put_elf_reloc(s1->symtab, text_section,
- text_section->data_offset - 24,
- R_AARCH64_ADR_PREL_PG_HI21, sym_index);
- write32le(ptr, 0x90000000); // adrp x0, destructor@page
- put_elf_reloc(s1->symtab, text_section,
- text_section->data_offset - 20,
- R_AARCH64_LDST8_ABS_LO12_NC, sym_index);
- write32le(ptr + 4, 0x91000000); // add x0,x0,destructor@pageoff
- write32le(ptr + 8, 0xd2800001); // mov x1, #0
- put_elf_reloc(s1->symtab, text_section,
- text_section->data_offset - 12,
- R_AARCH64_ADR_PREL_PG_HI21, mh_execute_header);
- write32le(ptr + 12, 0x90000002); // adrp x2, mh_execute_header@page
- put_elf_reloc(s1->symtab, text_section,
- text_section->data_offset - 8,
- R_AARCH64_LDST8_ABS_LO12_NC, mh_execute_header);
- write32le(ptr + 16, 0x91000042); // add x2,x2,mh_execute_header@pageoff
- put_elf_reloc(s1->symtab, text_section,
- text_section->data_offset - 4,
- R_AARCH64_CALL26, at_exit_sym);
- write32le(ptr + 20, 0x94000000); // bl __cxa_atexit
- }
- ptr = section_ptr_add(text_section, 8);
- write32le(ptr, 0xa8c17bfd); // ldp x29, x30, [sp], #16
- write32le(ptr + 4, 0xd65f03c0); // ret
-#endif
- s->reloc->data_offset = s->data_offset = 0;
- s->sh_flags &= ~SHF_ALLOC;
- add_array (s1, ".init_array", init_sym);
-}
-
-#ifdef CONFIG_NEW_MACHO
-static void bind_rebase_add(struct macho *mo, int bind, int sh_info,
- ElfW_Rel *rel, struct sym_attr *attr)
-{
- mo->bind_rebase = tcc_realloc(mo->bind_rebase, (mo->n_bind_rebase + 1) *
- sizeof(struct bind_rebase));
- mo->bind_rebase[mo->n_bind_rebase].section = sh_info;
- mo->bind_rebase[mo->n_bind_rebase].bind = bind;
- mo->bind_rebase[mo->n_bind_rebase].rel = *rel;
- if (attr)
- mo->bind_rebase[mo->n_bind_rebase].rel.r_offset = attr->got_offset;
- mo->n_bind_rebase++;
- mo->n_bind += bind;
-}
-
-static void check_relocs(TCCState *s1, struct macho *mo)
-{
- Section *s;
- ElfW_Rel *rel, save_rel;
- ElfW(Sym) *sym;
- int i, j, type, gotplt_entry, sym_index, for_code;
- uint32_t *pi, *goti;
- struct sym_attr *attr;
-
- goti = NULL;
- mo->nr_plt = mo->n_got = 0;
- for (i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
- if (s->sh_type != SHT_RELX ||
- !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7))
- continue;
- for_each_elem(s, 0, rel, ElfW_Rel) {
- save_rel = *rel;
- type = ELFW(R_TYPE)(rel->r_info);
- gotplt_entry = gotplt_entry_type(type);
- for_code = code_reloc(type);
- /* We generate a non-lazy pointer for used undefined symbols
- and for defined symbols that must have a place for their
- address due to codegen (i.e. a reloc requiring a got slot). */
- sym_index = ELFW(R_SYM)(rel->r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- if (sym->st_shndx == SHN_UNDEF
- || gotplt_entry == ALWAYS_GOTPLT_ENTRY) {
- attr = get_sym_attr(s1, sym_index, 1);
- if (!attr->dyn_index) {
- attr->got_offset = s1->got->data_offset;
- attr->plt_offset = -1;
- attr->dyn_index = 1; /* used as flag */
- section_ptr_add(s1->got, PTR_SIZE);
- put_elf_reloc(s1->symtab, s1->got, attr->got_offset,
- R_JMP_SLOT, sym_index);
- goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti));
- if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
- if (sym->st_shndx == SHN_UNDEF)
- tcc_error("undefined local symbo: '%s'",
- (char *) symtab_section->link->data + sym->st_name);
- goti[mo->n_got++] = INDIRECT_SYMBOL_LOCAL;
- } else {
- goti[mo->n_got++] = mo->e2msym[sym_index];
- if (sym->st_shndx == SHN_UNDEF
-#ifdef TCC_TARGET_X86_64
- && type == R_X86_64_GOTPCREL
-#elif defined TCC_TARGET_ARM64
- && type == R_AARCH64_ADR_GOT_PAGE
-#endif
- ) {
- attr->plt_offset = -mo->n_bind_rebase - 2;
- bind_rebase_add(mo, 1, s1->got->reloc->sh_info, &save_rel, attr);
- s1->got->reloc->data_offset -= sizeof (ElfW_Rel);
- }
- if (for_code && sym->st_shndx == SHN_UNDEF)
- s1->got->reloc->data_offset -= sizeof (ElfW_Rel);
- }
- }
- if (for_code && sym->st_shndx == SHN_UNDEF) {
- if ((int)attr->plt_offset < -1) {
- /* remove above bind and replace with plt */
- mo->bind_rebase[-attr->plt_offset - 2].bind = 2;
- attr->plt_offset = -1;
- }
- if (attr->plt_offset == -1) {
- uint8_t *jmp;
-
- attr->plt_offset = mo->stubs->data_offset;
-#ifdef TCC_TARGET_X86_64
- if (type != R_X86_64_PLT32)
- continue;
- jmp = section_ptr_add(mo->stubs, 6);
- jmp[0] = 0xff; /* jmpq *ofs(%rip) */
- jmp[1] = 0x25;
- put_elf_reloc(s1->symtab, mo->stubs,
- attr->plt_offset + 2,
- R_X86_64_GOTPCREL, sym_index);
-#elif defined TCC_TARGET_ARM64
- if (type != R_AARCH64_CALL26)
- continue;
- jmp = section_ptr_add(mo->stubs, 12);
- put_elf_reloc(s1->symtab, mo->stubs,
- attr->plt_offset,
- R_AARCH64_ADR_GOT_PAGE, sym_index);
- write32le(jmp, // adrp x16, #sym
- 0x90000010);
- put_elf_reloc(s1->symtab, mo->stubs,
- attr->plt_offset + 4,
- R_AARCH64_LD64_GOT_LO12_NC, sym_index);
- write32le(jmp + 4, // ld x16,[x16, #sym]
- 0xf9400210);
- write32le(jmp + 8, // br x16
- 0xd61f0200);
-#endif
- bind_rebase_add(mo, 1, s1->got->reloc->sh_info, &save_rel, attr);
- pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
- *pi = mo->e2msym[sym_index];
- mo->nr_plt++;
- }
- rel->r_info = ELFW(R_INFO)(mo->stubsym, type);
- rel->r_addend += attr->plt_offset;
- }
- }
- if (type == R_DATA_PTR || type == R_JMP_SLOT)
- bind_rebase_add(mo, sym->st_shndx == SHN_UNDEF ? 1 : 0,
- s->sh_info, &save_rel, NULL);
- }
- }
- /* remove deleted binds */
- for (i = 0, j = 0; i < mo->n_bind_rebase; i++)
- if (mo->bind_rebase[i].bind == 2)
- mo->n_bind--;
- else
- mo->bind_rebase[j++] = mo->bind_rebase[i];
- mo->n_bind_rebase = j;
- pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi));
- memcpy(pi, goti, mo->n_got * sizeof(*pi));
- tcc_free(goti);
-}
-
-#else
-
-static void check_relocs(TCCState *s1, struct macho *mo)
-{
- uint8_t *jmp;
- Section *s;
- ElfW_Rel *rel, save_rel;
- ElfW(Sym) *sym;
- int i, type, gotplt_entry, sym_index, for_code;
- int bind_offset, la_symbol_offset;
- uint32_t *pi, *goti;
- struct sym_attr *attr;
-
-#ifdef TCC_TARGET_X86_64
- jmp = section_ptr_add(mo->stub_helper, 16);
- jmp[0] = 0x4c; /* leaq _dyld_private(%rip), %r11 */
- jmp[1] = 0x8d;
- jmp[2] = 0x1d;
- put_elf_reloca(s1->symtab, mo->stub_helper, 3,
- R_X86_64_PC32, mo->dyld_private, -4);
- jmp[7] = 0x41; /* pushq %r11 */
- jmp[8] = 0x53;
- jmp[9] = 0xff; /* jmpq *dyld_stub_binder@GOT(%rip) */
- jmp[10] = 0x25;
- put_elf_reloca(s1->symtab, mo->stub_helper, 11,
- R_X86_64_GOTPCREL, mo->dyld_stub_binder, -4);
- jmp[15] = 0x90; /* nop */
-#elif defined TCC_TARGET_ARM64
- jmp = section_ptr_add(mo->stub_helper, 24);
- put_elf_reloc(s1->symtab, mo->stub_helper, 0,
- R_AARCH64_ADR_PREL_PG_HI21, mo->dyld_private);
- write32le(jmp, 0x90000011); // adrp x17, _dyld_private@page
- put_elf_reloc(s1->symtab, mo->stub_helper, 4,
- R_AARCH64_LDST64_ABS_LO12_NC, mo->dyld_private);
- write32le(jmp + 4, 0x91000231); // add x17,x17,_dyld_private@pageoff
- write32le(jmp + 8, 0xa9bf47f0); // stp x16/x17, [sp, #-16]!
- put_elf_reloc(s1->symtab, mo->stub_helper, 12,
- R_AARCH64_ADR_GOT_PAGE, mo->dyld_stub_binder);
- write32le(jmp + 12, 0x90000010); // adrp x16, dyld_stub_binder@page
- put_elf_reloc(s1->symtab, mo->stub_helper, 16,
- R_AARCH64_LD64_GOT_LO12_NC, mo->dyld_stub_binder);
- write32le(jmp + 16, 0xf9400210); // ldr x16,[x16,dyld_stub_binder@pageoff]
- write32le(jmp + 20, 0xd61f0200); // br x16
-#endif
-
- goti = NULL;
- mo->nr_plt = mo->n_got = 0;
- for (i = 1; i < s1->nb_sections; i++) {
- s = s1->sections[i];
- if (s->sh_type != SHT_RELX ||
- !strncmp(s1->sections[s->sh_info]->name, ".debug_", 7))
- continue;
- for_each_elem(s, 0, rel, ElfW_Rel) {
- save_rel = *rel;
- type = ELFW(R_TYPE)(rel->r_info);
- gotplt_entry = gotplt_entry_type(type);
- for_code = code_reloc(type);
- /* We generate a non-lazy pointer for used undefined symbols
- and for defined symbols that must have a place for their
- address due to codegen (i.e. a reloc requiring a got slot). */
- sym_index = ELFW(R_SYM)(rel->r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- if (sym->st_shndx == SHN_UNDEF
- || gotplt_entry == ALWAYS_GOTPLT_ENTRY) {
- attr = get_sym_attr(s1, sym_index, 1);
- if (!attr->dyn_index) {
- attr->got_offset = s1->got->data_offset;
- attr->plt_offset = -1;
- attr->dyn_index = 1; /* used as flag */
- section_ptr_add(s1->got, PTR_SIZE);
- put_elf_reloc(s1->symtab, s1->got, attr->got_offset,
- R_JMP_SLOT, sym_index);
- goti = tcc_realloc(goti, (mo->n_got + 1) * sizeof(*goti));
- if (ELFW(ST_BIND)(sym->st_info) == STB_LOCAL) {
- if (sym->st_shndx == SHN_UNDEF)
- tcc_error("undefined local symbo: '%s'",
- (char *) symtab_section->link->data + sym->st_name);
- goti[mo->n_got++] = INDIRECT_SYMBOL_LOCAL;
- } else {
- goti[mo->n_got++] = mo->e2msym[sym_index];
- if (sym->st_shndx == SHN_UNDEF
-#ifdef TCC_TARGET_X86_64
- && type == R_X86_64_GOTPCREL
-#elif defined TCC_TARGET_ARM64
- && type == R_AARCH64_ADR_GOT_PAGE
-#endif
- ) {
- mo->bind =
- tcc_realloc(mo->bind,
- (mo->n_bind + 1) *
- sizeof(struct bind));
- mo->bind[mo->n_bind].section = s1->got->reloc->sh_info;
- mo->bind[mo->n_bind].rel = save_rel;
- mo->bind[mo->n_bind].rel.r_offset = attr->got_offset;
- mo->n_bind++;
- s1->got->reloc->data_offset -= sizeof (ElfW_Rel);
- }
- }
- }
- if (for_code && sym->st_shndx == SHN_UNDEF) {
- if (attr->plt_offset == -1) {
- attr->plt_offset = mo->stubs->data_offset;
-#ifdef TCC_TARGET_X86_64
- if (type != R_X86_64_PLT32)
- continue;
- /* __stubs */
- jmp = section_ptr_add(mo->stubs, 6);
- jmp[0] = 0xff; /* jmpq *__la_symbol_ptr(%rip) */
- jmp[1] = 0x25;
- put_elf_reloca(s1->symtab, mo->stubs,
- mo->stubs->data_offset - 4,
- R_X86_64_PC32, mo->lasym,
- mo->la_symbol_ptr->data_offset - 4);
-
- /* __stub_helper */
- bind_offset = mo->stub_helper->data_offset + 1;
- jmp = section_ptr_add(mo->stub_helper, 10);
- jmp[0] = 0x68; /* pushq $bind_offset */
- jmp[5] = 0xe9; /* jmpq __stub_helper */
- write32le(jmp + 6, -mo->stub_helper->data_offset);
-
- /* __la_symbol_ptr */
- la_symbol_offset = mo->la_symbol_ptr->data_offset;
- put_elf_reloca(s1->symtab, mo->la_symbol_ptr,
- mo->la_symbol_ptr->data_offset,
- R_DATA_PTR, mo->helpsym,
- mo->stub_helper->data_offset - 10);
- section_ptr_add(mo->la_symbol_ptr, PTR_SIZE);
-#elif defined TCC_TARGET_ARM64
- if (type != R_AARCH64_CALL26)
- continue;
- /* __stubs */
- jmp = section_ptr_add(mo->stubs, 12);
- put_elf_reloca(s1->symtab, mo->stubs,
- mo->stubs->data_offset - 12,
- R_AARCH64_ADR_PREL_PG_HI21, mo->lasym,
- mo->la_symbol_ptr->data_offset);
- write32le(jmp, // adrp x16, __la_symbol_ptr@page
- 0x90000010);
- put_elf_reloca(s1->symtab, mo->stubs,
- mo->stubs->data_offset - 8,
- R_AARCH64_LDST64_ABS_LO12_NC, mo->lasym,
- mo->la_symbol_ptr->data_offset);
- write32le(jmp + 4, // ldr x16,[x16, __la_symbol_ptr@pageoff]
- 0xf9400210);
- write32le(jmp + 8, // br x16
- 0xd61f0200);
-
- /* __stub_helper */
- bind_offset = mo->stub_helper->data_offset + 8;
- jmp = section_ptr_add(mo->stub_helper, 12);
- write32le(jmp + 0, // ldr w16, l0
- 0x18000050);
- write32le(jmp + 4, // b stubHelperHeader
- 0x14000000 +
- ((-(mo->stub_helper->data_offset - 8) / 4) &
- 0x3ffffff));
- write32le(jmp + 8, 0); // l0: .long bind_offset
-
- /* __la_symbol_ptr */
- la_symbol_offset = mo->la_symbol_ptr->data_offset;
- put_elf_reloca(s1->symtab, mo->la_symbol_ptr,
- mo->la_symbol_ptr->data_offset,
- R_DATA_PTR, mo->helpsym,
- mo->stub_helper->data_offset - 12);
- section_ptr_add(mo->la_symbol_ptr, PTR_SIZE);
-#endif
- mo->s_lazy_bind =
- tcc_realloc(mo->s_lazy_bind, (mo->n_lazy_bind + 1) *
- sizeof(struct s_lazy_bind));
- mo->s_lazy_bind[mo->n_lazy_bind].section =
- mo->stub_helper->reloc->sh_info;
- mo->s_lazy_bind[mo->n_lazy_bind].bind_offset =
- bind_offset;
- mo->s_lazy_bind[mo->n_lazy_bind].la_symbol_offset =
- la_symbol_offset;
- mo->s_lazy_bind[mo->n_lazy_bind].rel = save_rel;
- mo->s_lazy_bind[mo->n_lazy_bind].rel.r_offset =
- attr->plt_offset;
- mo->n_lazy_bind++;
- pi = section_ptr_add(mo->indirsyms, sizeof(*pi));
- *pi = mo->e2msym[sym_index];
- mo->nr_plt++;
- }
- rel->r_info = ELFW(R_INFO)(mo->stubsym, type);
- rel->r_addend += attr->plt_offset;
- }
- }
- if (type == R_DATA_PTR || type == R_JMP_SLOT) {
- if (sym->st_shndx == SHN_UNDEF) {
- mo->bind = tcc_realloc(mo->bind,
- (mo->n_bind + 1) *
- sizeof(struct bind));
- mo->bind[mo->n_bind].section = s->sh_info;
- mo->bind[mo->n_bind].rel = save_rel;
- mo->n_bind++;
- }
- else {
- mo->s_rebase =
- tcc_realloc(mo->s_rebase, (mo->n_rebase + 1) *
- sizeof(struct s_rebase));
- mo->s_rebase[mo->n_rebase].section = s->sh_info;
- mo->s_rebase[mo->n_rebase].rel = save_rel;
- mo->n_rebase++;
- }
- }
- }
- }
- pi = section_ptr_add(mo->indirsyms, mo->n_got * sizeof(*pi));
- memcpy(pi, goti, mo->n_got * sizeof(*pi));
- pi = section_ptr_add(mo->indirsyms, mo->nr_plt * sizeof(*pi));
- memcpy(pi, mo->indirsyms->data, mo->nr_plt * sizeof(*pi));
- tcc_free(goti);
-}
-#endif
-
-static int check_symbols(TCCState *s1, struct macho *mo)
-{
- int sym_index, sym_end;
- int ret = 0;
-
- mo->ilocal = mo->iextdef = mo->iundef = -1;
- sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
- for (sym_index = 1; sym_index < sym_end; ++sym_index) {
- int elf_index = ((struct nlist_64 *)mo->symtab->data + sym_index - 1)->n_value;
- ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + elf_index;
- const char *name = (char*)symtab_section->link->data + sym->st_name;
- unsigned type = ELFW(ST_TYPE)(sym->st_info);
- unsigned bind = ELFW(ST_BIND)(sym->st_info);
- unsigned vis = ELFW(ST_VISIBILITY)(sym->st_other);
-
- dprintf("%4d (%4d): %09lx %4d %4d %4d %3d %s\n",
- sym_index, elf_index, (long)sym->st_value,
- type, bind, vis, sym->st_shndx, name);
- if (bind == STB_LOCAL) {
- if (mo->ilocal == -1)
- mo->ilocal = sym_index - 1;
- if (mo->iextdef != -1 || mo->iundef != -1)
- tcc_error("local syms after global ones");
- } else if (sym->st_shndx != SHN_UNDEF) {
- if (mo->iextdef == -1)
- mo->iextdef = sym_index - 1;
- if (mo->iundef != -1)
- tcc_error("external defined symbol after undefined");
- } else if (sym->st_shndx == SHN_UNDEF) {
- if (mo->iundef == -1)
- mo->iundef = sym_index - 1;
- if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK
- || s1->output_type != TCC_OUTPUT_EXE
- || find_elf_sym(s1->dynsymtab_section, name)) {
- /* Mark the symbol as coming from a dylib so that
- relocate_syms doesn't complain. Normally bind_exe_dynsyms
- would do this check, and place the symbol into dynsym
- which is checked by relocate_syms. But Mach-O doesn't use
- bind_exe_dynsyms. */
- sym->st_shndx = SHN_FROMDLL;
- continue;
- }
- tcc_error_noabort("undefined symbol '%s'", name);
- ret = -1;
- }
- }
- return ret;
-}
-
-static void convert_symbol(TCCState *s1, struct macho *mo, struct nlist_64 *pn)
-{
- struct nlist_64 n = *pn;
- ElfSym *sym = (ElfW(Sym) *)symtab_section->data + pn->n_value;
- const char *name = (char*)symtab_section->link->data + sym->st_name;
- switch(ELFW(ST_TYPE)(sym->st_info)) {
- case STT_NOTYPE:
- case STT_OBJECT:
- case STT_FUNC:
- case STT_SECTION:
- n.n_type = N_SECT;
- break;
- case STT_FILE:
- n.n_type = N_ABS;
- break;
- default:
- tcc_error("unhandled ELF symbol type %d %s",
- ELFW(ST_TYPE)(sym->st_info), name);
- }
- if (sym->st_shndx == SHN_UNDEF)
- tcc_error("should have been rewritten to SHN_FROMDLL: %s", name);
- else if (sym->st_shndx == SHN_FROMDLL)
- n.n_type = N_UNDF, n.n_sect = 0;
- else if (sym->st_shndx == SHN_ABS)
- n.n_type = N_ABS, n.n_sect = 0;
- else if (sym->st_shndx >= SHN_LORESERVE)
- tcc_error("unhandled ELF symbol section %d %s", sym->st_shndx, name);
- else if (!mo->elfsectomacho[sym->st_shndx]) {
- if (strncmp(s1->sections[sym->st_shndx]->name, ".debug_", 7))
- tcc_error("ELF section %d(%s) not mapped into Mach-O for symbol %s",
- sym->st_shndx, s1->sections[sym->st_shndx]->name, name);
- }
- else
- n.n_sect = mo->elfsectomacho[sym->st_shndx];
- if (ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL)
- n.n_type |= N_EXT;
- else if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
- n.n_desc |= N_WEAK_REF | (n.n_type != N_UNDF ? N_WEAK_DEF : 0);
- n.n_strx = pn->n_strx;
- n.n_value = sym->st_value;
- *pn = n;
-}
-
-static void convert_symbols(TCCState *s1, struct macho *mo)
-{
- struct nlist_64 *pn;
- for_each_elem(mo->symtab, 0, pn, struct nlist_64)
- convert_symbol(s1, mo, pn);
-}
-
-static int machosymcmp(const void *_a, const void *_b, void *arg)
-{
- TCCState *s1 = arg;
- int ea = ((struct nlist_64 *)_a)->n_value;
- int eb = ((struct nlist_64 *)_b)->n_value;
- ElfSym *sa = (ElfSym *)symtab_section->data + ea;
- ElfSym *sb = (ElfSym *)symtab_section->data + eb;
- int r;
- /* locals, then defined externals, then undefined externals, the
- last two sections also by name, otherwise stable sort */
- r = (ELFW(ST_BIND)(sb->st_info) == STB_LOCAL)
- - (ELFW(ST_BIND)(sa->st_info) == STB_LOCAL);
- if (r)
- return r;
- r = (sa->st_shndx == SHN_UNDEF) - (sb->st_shndx == SHN_UNDEF);
- if (r)
- return r;
- if (ELFW(ST_BIND)(sa->st_info) != STB_LOCAL) {
- const char * na = (char*)symtab_section->link->data + sa->st_name;
- const char * nb = (char*)symtab_section->link->data + sb->st_name;
- r = strcmp(na, nb);
- if (r)
- return r;
- }
- return ea - eb;
-}
-
-/* cannot use qsort because code has to be reentrant */
-static void tcc_qsort (void *base, size_t nel, size_t width,
- int (*comp)(const void *, const void *, void *), void *arg)
-{
- size_t wnel, gap, wgap, i, j, k;
- char *a, *b, tmp;
-
- wnel = width * nel;
- for (gap = 0; ++gap < nel;)
- gap *= 3;
- while ( gap /= 3 ) {
- wgap = width * gap;
- for (i = wgap; i < wnel; i += width) {
- for (j = i - wgap; ;j -= wgap) {
- a = j + (char *)base;
- b = a + wgap;
- if ( (*comp)(a, b, arg) <= 0 )
- break;
- k = width;
- do {
- tmp = *a;
- *a++ = *b;
- *b++ = tmp;
- } while ( --k );
- if (j < wgap)
- break;
- }
- }
- }
-}
-
-static void create_symtab(TCCState *s1, struct macho *mo)
-{
- int sym_index, sym_end;
- struct nlist_64 *pn;
-
- /* Stub creation belongs to check_relocs, but we need to create
- the symbol now, so its included in the sorting. */
- mo->stubs = new_section(s1, "__stubs", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
- s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
- mo->stubsym = put_elf_sym(s1->symtab, 0, 0,
- ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
- mo->stubs->sh_num, ".__stubs");
-#ifdef CONFIG_NEW_MACHO
- mo->chained_fixups = new_section(s1, "CHAINED_FIXUPS",
- SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
-#else
- mo->stub_helper = new_section(s1, "__stub_helper", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
- mo->la_symbol_ptr = new_section(s1, "__la_symbol_ptr", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
- mo->helpsym = put_elf_sym(s1->symtab, 0, 0,
- ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
- mo->stub_helper->sh_num, ".__stub_helper");
- mo->lasym = put_elf_sym(s1->symtab, 0, 0,
- ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
- mo->la_symbol_ptr->sh_num, ".__la_symbol_ptr");
- section_ptr_add(data_section, -data_section->data_offset & (PTR_SIZE - 1));
- mo->dyld_private = put_elf_sym(s1->symtab, data_section->data_offset, PTR_SIZE,
- ELFW(ST_INFO)(STB_LOCAL, STT_OBJECT), 0,
- data_section->sh_num, ".__dyld_private");
- section_ptr_add(data_section, PTR_SIZE);
- mo->dyld_stub_binder = put_elf_sym(s1->symtab, 0, 0,
- ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT), 0,
- SHN_UNDEF, "dyld_stub_binder");
- mo->rebase = new_section(s1, "REBASE", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
- mo->binding = new_section(s1, "BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
- mo->weak_binding = new_section(s1, "WEAK_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
- mo->lazy_binding = new_section(s1, "LAZY_BINDING", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
-#endif
- mo->exports = new_section(s1, "EXPORT", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
- mo->indirsyms = new_section(s1, "LEINDIR", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
-
- mo->symtab = new_section(s1, "LESYMTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
- mo->strtab = new_section(s1, "LESTRTAB", SHT_LINKEDIT, SHF_ALLOC | SHF_WRITE);
- put_elf_str(mo->strtab, " "); /* Mach-O starts strtab with a space */
- sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
- pn = section_ptr_add(mo->symtab, sizeof(*pn) * (sym_end - 1));
- for (sym_index = 1; sym_index < sym_end; ++sym_index) {
- ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
- const char *name = (char*)symtab_section->link->data + sym->st_name;
- pn[sym_index - 1].n_strx = put_elf_str(mo->strtab, name);
- pn[sym_index - 1].n_value = sym_index;
- }
- section_ptr_add(mo->strtab, -mo->strtab->data_offset & (PTR_SIZE - 1));
- tcc_qsort(pn, sym_end - 1, sizeof(*pn), machosymcmp, s1);
- mo->e2msym = tcc_malloc(sym_end * sizeof(*mo->e2msym));
- mo->e2msym[0] = -1;
- for (sym_index = 1; sym_index < sym_end; ++sym_index) {
- mo->e2msym[pn[sym_index - 1].n_value] = sym_index - 1;
- }
-}
-
-const struct {
- int seg_initial;
- uint32_t flags;
- const char *name;
-} skinfo[sk_last] = {
- /*[sk_unknown] =*/ { 0 },
- /*[sk_discard] =*/ { 0 },
- /*[sk_text] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS, "__text" },
- /*[sk_stubs] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS | S_SYMBOL_STUBS
- | S_ATTR_SOME_INSTRUCTIONS , "__stubs" },
- /*[sk_stub_helper] =*/ { 1, S_REGULAR | S_ATTR_PURE_INSTRUCTIONS
- | S_ATTR_SOME_INSTRUCTIONS , "__stub_helper" },
- /*[sk_ro_data] =*/ { 2, S_REGULAR, "__rodata" },
- /*[sk_uw_info] =*/ { 0 },
- /*[sk_nl_ptr] =*/ { 2, S_NON_LAZY_SYMBOL_POINTERS, "__got" },
- /*[sk_debug_info] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_info" },
- /*[sk_debug_abbrev] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_abbrev" },
- /*[sk_debug_line] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_line" },
- /*[sk_debug_aranges] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_aranges" },
- /*[sk_debug_str] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_str" },
- /*[sk_debug_line_str] =*/ { 3, S_REGULAR | S_ATTR_DEBUG, "__debug_line_str" },
- /*[sk_stab] =*/ { 4, S_REGULAR, "__stab" },
- /*[sk_stab_str] =*/ { 4, S_REGULAR, "__stab_str" },
- /*[sk_la_ptr] =*/ { 4, S_LAZY_SYMBOL_POINTERS, "__la_symbol_ptr" },
- /*[sk_init] =*/ { 4, S_MOD_INIT_FUNC_POINTERS, "__mod_init_func" },
- /*[sk_fini] =*/ { 4, S_MOD_TERM_FUNC_POINTERS, "__mod_term_func" },
- /*[sk_rw_data] =*/ { 4, S_REGULAR, "__data" },
- /*[sk_bss] =*/ { 4, S_ZEROFILL, "__bss" },
- /*[sk_linkedit] =*/ { 5, S_REGULAR, NULL },
-};
-
-#define START ((uint64_t)1 << 32)
-
-const struct {
- int used;
- const char *name;
- uint64_t vmaddr;
- uint64_t vmsize;
- vm_prot_t maxprot;
- vm_prot_t initprot;
- uint32_t flags;
-} all_segment[] = {
- { 1, "__PAGEZERO", 0, START, 0, 0, 0 },
- { 0, "__TEXT", START, 0, 5, 5, 0 },
- { 0, "__DATA_CONST", -1, 0, 3, 3, SG_READ_ONLY },
- { 0, "__DWARF", -1, 0, 7, 3, 0 },
- { 0, "__DATA", -1, 0, 3, 3, 0 },
- { 1, "__LINKEDIT", -1, 0, 1, 1, 0 },
-};
-
-#define N_SEGMENT (sizeof(all_segment)/sizeof(all_segment[0]))
-
-#ifdef CONFIG_NEW_MACHO
-static void calc_fixup_size(TCCState *s1, struct macho *mo)
-{
- int i, size;
-
- size = (sizeof(struct dyld_chained_fixups_header) + 7) & -8;
- size += (sizeof(struct dyld_chained_starts_in_image) + (mo->nseg - 1) * sizeof(uint32_t) + 7) & -8;
- for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) {
- int page_count = (get_segment(mo, i)->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE;
- size += (sizeof(struct dyld_chained_starts_in_segment) + (page_count - 1) * sizeof(uint16_t) + 7) & -8;
- }
- size += mo->n_bind * sizeof (struct dyld_chained_import) + 1;
- for (i = 0; i < mo->n_bind_rebase; i++) {
- if (mo->bind_rebase[i].bind) {
- int sym_index = ELFW(R_SYM)(mo->bind_rebase[i].rel.r_info);
- ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- const char *name = (char *) symtab_section->link->data + sym->st_name;
- size += strlen(name) + 1;
- }
- }
- size = (size + 7) & -8;
- section_ptr_add(mo->chained_fixups, size);
-}
-
-#else
-
-static void set_segment_and_offset(TCCState *s1, struct macho *mo, addr_t addr,
- uint8_t *ptr, int opcode,
- Section *sec, addr_t offset)
-{
- int i;
- struct segment_command_64 *seg = NULL;
-
- for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) {
- seg = get_segment(mo, i);
- if (addr >= seg->vmaddr && addr < (seg->vmaddr + seg->vmsize))
- break;
- }
- *ptr = opcode | i;
- write_uleb128(sec, offset - seg->vmaddr);
-}
-
-static void bind_rebase(TCCState *s1, struct macho *mo)
-{
- int i;
- uint8_t *ptr;
- ElfW(Sym) *sym;
- const char *name;
-
- for (i = 0; i < mo->n_lazy_bind; i++) {
- int sym_index = ELFW(R_SYM)(mo->s_lazy_bind[i].rel.r_info);
-
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- name = (char *) symtab_section->link->data + sym->st_name;
- write32le(mo->stub_helper->data +
- mo->s_lazy_bind[i].bind_offset,
- mo->lazy_binding->data_offset);
- ptr = section_ptr_add(mo->lazy_binding, 1);
- set_segment_and_offset(s1, mo, mo->la_symbol_ptr->sh_addr, ptr,
- BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
- mo->lazy_binding,
- mo->s_lazy_bind[i].la_symbol_offset +
- mo->la_symbol_ptr->sh_addr);
- ptr = section_ptr_add(mo->lazy_binding, 5 + strlen(name));
- *ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
- (BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf);
- *ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | 0;
- strcpy((char *)ptr, name);
- ptr += strlen(name) + 1;
- *ptr++ = BIND_OPCODE_DO_BIND;
- *ptr = BIND_OPCODE_DONE;
- }
- for (i = 0; i < mo->n_rebase; i++) {
- Section *s = s1->sections[mo->s_rebase[i].section];
-
- ptr = section_ptr_add(mo->rebase, 2);
- *ptr++ = REBASE_OPCODE_SET_TYPE_IMM | REBASE_TYPE_POINTER;
- set_segment_and_offset(s1, mo, s->sh_addr, ptr,
- REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
- mo->rebase,
- mo->s_rebase[i].rel.r_offset +
- s->sh_addr);
- ptr = section_ptr_add(mo->rebase, 1);
- *ptr = REBASE_OPCODE_DO_REBASE_IMM_TIMES | 1;
- }
- for (i = 0; i < mo->n_bind; i++) {
- int sym_index = ELFW(R_SYM)(mo->bind[i].rel.r_info);
- Section *s = s1->sections[mo->bind[i].section];
- Section *binding;
-
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- name = (char *) symtab_section->link->data + sym->st_name;
- binding = ELFW(ST_BIND)(sym->st_info) == STB_WEAK
- ? mo->weak_binding : mo->binding;
- ptr = section_ptr_add(binding, 4 + (binding == mo->binding) +
- strlen(name));
- if (binding == mo->binding)
- *ptr++ = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
- (BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xf);
- *ptr++ = BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM |
- (binding == mo->weak_binding
- ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0);
- strcpy((char *)ptr, name);
- ptr += strlen(name) + 1;
- *ptr++ = BIND_OPCODE_SET_TYPE_IMM | BIND_TYPE_POINTER;
- set_segment_and_offset(s1, mo, s->sh_addr, ptr,
- BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
- binding,
- mo->bind[i].rel.r_offset + s->sh_addr);
- ptr = section_ptr_add(binding, 1);
- *ptr++ = BIND_OPCODE_DO_BIND;
- }
- if (mo->rebase->data_offset) {
- ptr = section_ptr_add(mo->rebase, 1);
- *ptr = REBASE_OPCODE_DONE;
- }
- if (mo->binding->data_offset) {
- ptr = section_ptr_add(mo->binding, 1);
- *ptr = BIND_OPCODE_DONE;
- }
- if (mo->weak_binding->data_offset) {
- ptr = section_ptr_add(mo->weak_binding, 1);
- *ptr = BIND_OPCODE_DONE;
- }
- tcc_free(mo->s_lazy_bind);
- tcc_free(mo->s_rebase);
- tcc_free(mo->bind);
-}
-#endif
-
-struct trie_info {
- const char *name;
- int flag;
- addr_t addr;
- int str_size;
- int term_size;
-};
-
-struct trie_node {
- int start;
- int end;
- int index_start;
- int index_end;
- int n_child;
- struct trie_node *child;
-};
-
-struct trie_seq {
- int n_child;
- struct trie_node *node;
- int offset;
- int nest_offset;
-};
-
-static void create_trie(struct trie_node *node,
- int from, int to, int index_start,
- int n_trie, struct trie_info *trie)
-{
- int i;
- int start, end, index_end;
- char cur;
- struct trie_node *child;
-
- for (i = from; i < to; i = end) {
- cur = trie[i].name[index_start];
- start = i++;
- for (; i < to; i++)
- if (cur != trie[i].name[index_start])
- break;
- end = i;
- if (start == end - 1 ||
- (trie[start].name[index_start] &&
- trie[start].name[index_start + 1] == 0))
- index_end = trie[start].str_size - 1;
- else {
- index_end = index_start + 1;
- for (;;) {
- cur = trie[start].name[index_end];
- for (i = start + 1; i < end; i++)
- if (cur != trie[i].name[index_end])
- break;
- if (trie[start].name[index_end] &&
- trie[start].name[index_end + 1] == 0) {
- end = start + 1;
- index_end = trie[start].str_size - 1;
- break;
- }
- if (i != end)
- break;
- index_end++;
- }
- }
- node->child = tcc_realloc(node->child,
- (node->n_child + 1) *
- sizeof(struct trie_node));
- child = &node->child[node->n_child];
- child->start = start;
- child->end = end;
- child->index_start = index_start;
- child->index_end = index_end;
- child->n_child = 0;
- child->child = NULL;
- node->n_child++;
- if (start != end - 1)
- create_trie(child, start, end, index_end, n_trie, trie);
- }
-}
-
-static int create_seq(int *offset, int *n_seq, struct trie_seq **seq,
- struct trie_node *node,
- int n_trie, struct trie_info *trie)
-{
- int i, nest_offset, last_seq = *n_seq, retval = *offset;
- struct trie_seq *p_seq;
- struct trie_node *p_nest;
-
- for (i = 0; i < node->n_child; i++) {
- p_nest = &node->child[i];
- *seq = tcc_realloc(*seq, (*n_seq + 1) * sizeof(struct trie_seq));
- p_seq = &(*seq)[(*n_seq)++];
- p_seq->n_child = i == 0 ? node->n_child : -1;
- p_seq->node = p_nest;
- p_seq->offset = *offset;
- p_seq->nest_offset = 0;
- *offset += (i == 0 ? 1 + 1 : 0) +
- p_nest->index_end - p_nest->index_start + 1 + 3;
- }
- for (i = 0; i < node->n_child; i++) {
- nest_offset =
- create_seq(offset, n_seq, seq, &node->child[i], n_trie, trie);
- p_seq = &(*seq)[last_seq + i];
- p_seq->nest_offset = nest_offset;
- }
- return retval;
-}
-
-static void node_free(struct trie_node *node)
-{
- int i;
-
- for (i = 0; i < node->n_child; i++)
- node_free(&node->child[i]);
- tcc_free(node->child);
-}
-
-static int triecmp(const void *_a, const void *_b, void *arg)
-{
- struct trie_info *a = (struct trie_info *) _a;
- struct trie_info *b = (struct trie_info *) _b;
- int len_a = strlen(a->name);
- int len_b = strlen(b->name);
-
- /* strange sorting needed. Name 'xx' should be after 'xx1' */
- if (!strncmp(a->name, b->name, len_a < len_b ? len_a : len_b))
- return len_a < len_b ? 1 : (len_a > len_b ? -1 : 0);
- return strcmp(a->name, b->name);
-}
-
-static void export_trie(TCCState *s1, struct macho *mo)
-{
- int i, size, offset = 0, save_offset;
- uint8_t *ptr;
- int sym_index;
- int sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
- int n_trie = 0, n_seq = 0;
- struct trie_info *trie = NULL, *p_trie;
- struct trie_node node, *p_node;
- struct trie_seq *seq = NULL;
- addr_t vm_addr = get_segment(mo, s1->output_type == TCC_OUTPUT_EXE)->vmaddr;
-
- for (sym_index = 1; sym_index < sym_end; ++sym_index) {
- ElfW(Sym) *sym = (ElfW(Sym) *)symtab_section->data + sym_index;
- const char *name = (char*)symtab_section->link->data + sym->st_name;
-
- if (sym->st_shndx != SHN_UNDEF && sym->st_shndx < SHN_LORESERVE &&
- (ELFW(ST_BIND)(sym->st_info) == STB_GLOBAL ||
- ELFW(ST_BIND)(sym->st_info) == STB_WEAK)) {
- int flag = EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
- addr_t addr =
- sym->st_value + s1->sections[sym->st_shndx]->sh_addr - vm_addr;
-
- if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
- flag |= EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
- dprintf ("%s %d %llx\n", name, flag, (long long)addr + vm_addr);
- trie = tcc_realloc(trie, (n_trie + 1) * sizeof(struct trie_info));
- trie[n_trie].name = name;
- trie[n_trie].flag = flag;
- trie[n_trie].addr = addr;
- trie[n_trie].str_size = strlen(name) + 1;
- trie[n_trie].term_size = uleb128_size(flag) + uleb128_size(addr);
- n_trie++;
- }
- }
- if (n_trie) {
- tcc_qsort(trie, n_trie, sizeof(struct trie_info), triecmp, NULL);
- memset(&node, 0, sizeof(node));
- create_trie(&node, 0, n_trie, 0, n_trie, trie);
- create_seq(&offset, &n_seq, &seq, &node, n_trie, trie);
- save_offset = offset;
- for (i = 0; i < n_seq; i++) {
- p_node = seq[i].node;
- if (p_node->n_child == 0) {
- p_trie = &trie[p_node->start];
- seq[i].nest_offset = offset;
- offset += 1 + p_trie->term_size + 1;
- }
- }
- for (i = 0; i < n_seq; i++) {
- p_node = seq[i].node;
- p_trie = &trie[p_node->start];
- if (seq[i].n_child >= 0) {
- section_ptr_add(mo->exports,
- seq[i].offset - mo->exports->data_offset);
- ptr = section_ptr_add(mo->exports, 2);
- *ptr++ = 0;
- *ptr = seq[i].n_child;
- }
- size = p_node->index_end - p_node->index_start;
- ptr = section_ptr_add(mo->exports, size + 1);
- memcpy(ptr, &p_trie->name[p_node->index_start], size);
- ptr[size] = 0;
- write_uleb128(mo->exports, seq[i].nest_offset);
- }
- section_ptr_add(mo->exports, save_offset - mo->exports->data_offset);
- for (i = 0; i < n_seq; i++) {
- p_node = seq[i].node;
- if (p_node->n_child == 0) {
- p_trie = &trie[p_node->start];
- write_uleb128(mo->exports, p_trie->term_size);
- write_uleb128(mo->exports, p_trie->flag);
- write_uleb128(mo->exports, p_trie->addr);
- ptr = section_ptr_add(mo->exports, 1);
- *ptr = 0;
- }
- }
- section_ptr_add(mo->exports, -mo->exports->data_offset & 7);
- node_free(&node);
- tcc_free(seq);
- }
- tcc_free(trie);
-}
-
-static void collect_sections(TCCState *s1, struct macho *mo, const char *filename)
-{
- int i, sk, numsec;
- int used_segment[N_SEGMENT];
- uint64_t curaddr, fileofs;
- Section *s;
- struct segment_command_64 *seg;
- struct dylib_command *dylib;
-#ifdef CONFIG_NEW_MACHO
- struct linkedit_data_command *chained_fixups_lc;
- struct linkedit_data_command *export_trie_lc;
-#endif
- struct build_version_command *dyldbv;
- struct source_version_command *dyldsv;
- struct rpath_command *rpath;
- struct dylinker_command *dyldlc;
- struct symtab_command *symlc;
- struct dysymtab_command *dysymlc;
- char *str;
-
- for (i = 0; i < N_SEGMENT; i++)
- used_segment[i] = all_segment[i].used;
-
- memset (mo->sk_to_sect, 0, sizeof(mo->sk_to_sect));
- for (i = s1->nb_sections; i-- > 1;) {
- int type, flags;
- s = s1->sections[i];
- type = s->sh_type;
- flags = s->sh_flags;
- sk = sk_unknown;
- /* debug sections have sometimes no SHF_ALLOC */
- if ((flags & SHF_ALLOC) || !strncmp(s->name, ".debug_", 7)) {
- switch (type) {
- default: sk = sk_unknown; break;
- case SHT_INIT_ARRAY: sk = sk_init; break;
- case SHT_FINI_ARRAY: sk = sk_fini; break;
- case SHT_NOBITS: sk = sk_bss; break;
- case SHT_SYMTAB: sk = sk_discard; break;
- case SHT_STRTAB:
- if (s == stabstr_section)
- sk = sk_stab_str;
- else
- sk = sk_discard;
- break;
- case SHT_RELX: sk = sk_discard; break;
- case SHT_LINKEDIT: sk = sk_linkedit; break;
- case SHT_PROGBITS:
- if (s == mo->stubs)
- sk = sk_stubs;
-#ifndef CONFIG_NEW_MACHO
- else if (s == mo->stub_helper)
- sk = sk_stub_helper;
- else if (s == mo->la_symbol_ptr)
- sk = sk_la_ptr;
-#endif
- else if (s == rodata_section)
- sk = sk_ro_data;
- else if (s == s1->got)
- sk = sk_nl_ptr;
- else if (s == stab_section)
- sk = sk_stab;
- else if (s == dwarf_info_section)
- sk = sk_debug_info;
- else if (s == dwarf_abbrev_section)
- sk = sk_debug_abbrev;
- else if (s == dwarf_line_section)
- sk = sk_debug_line;
- else if (s == dwarf_aranges_section)
- sk = sk_debug_aranges;
- else if (s == dwarf_str_section)
- sk = sk_debug_str;
- else if (s == dwarf_line_str_section)
- sk = sk_debug_line_str;
- else if (flags & SHF_EXECINSTR)
- sk = sk_text;
- else if (flags & SHF_WRITE)
- sk = sk_rw_data;
- else
- sk = sk_ro_data;
- break;
- }
- } else
- sk = sk_discard;
- s->prev = mo->sk_to_sect[sk].s;
- mo->sk_to_sect[sk].s = s;
- used_segment[skinfo[sk].seg_initial] = 1;
- }
-
- if (s1->output_type != TCC_OUTPUT_EXE)
- used_segment[0] = 0;
-
- for (i = 0; i < N_SEGMENT; i++)
- if (used_segment[i]) {
- seg = add_segment(mo, all_segment[i].name);
- if (i == 1 && s1->output_type != TCC_OUTPUT_EXE)
- seg->vmaddr = 0;
- else
- seg->vmaddr = all_segment[i].vmaddr;
- seg->vmsize = all_segment[i].vmsize;
- seg->maxprot = all_segment[i].maxprot;
- seg->initprot = all_segment[i].initprot;
- seg->flags = all_segment[i].flags;
- for (sk = sk_unknown; sk < sk_last; sk++)
- if (skinfo[sk].seg_initial == i)
- mo->segment[sk] = mo->nseg - 1;
- }
-
- if (s1->output_type != TCC_OUTPUT_EXE) {
- const char *name = s1->install_name ? s1->install_name : filename;
- i = (sizeof(*dylib) + strlen(name) + 1 + 7) &-8;
- dylib = add_lc(mo, LC_ID_DYLIB, i);
- dylib->name = sizeof(*dylib);
- dylib->timestamp = 1;
- dylib->current_version =
- s1->current_version ? s1->current_version : 1 << 16;
- dylib->compatibility_version =
- s1->compatibility_version ? s1->compatibility_version : 1 << 16;
- str = (char*)dylib + dylib->name;
- strcpy(str, name);
- }
-
-#ifdef CONFIG_NEW_MACHO
- chained_fixups_lc = add_lc(mo, LC_DYLD_CHAINED_FIXUPS,
- sizeof(struct linkedit_data_command));
- export_trie_lc = add_lc(mo, LC_DYLD_EXPORTS_TRIE,
- sizeof(struct linkedit_data_command));
-#else
- mo->dyldinfo = add_lc(mo, LC_DYLD_INFO_ONLY, sizeof(*mo->dyldinfo));
-#endif
-
- symlc = add_lc(mo, LC_SYMTAB, sizeof(*symlc));
- dysymlc = add_lc(mo, LC_DYSYMTAB, sizeof(*dysymlc));
-
- if (s1->output_type == TCC_OUTPUT_EXE) {
- i = (sizeof(*dyldlc) + strlen("/usr/lib/dyld") + 1 + 7) &-8;
- dyldlc = add_lc(mo, LC_LOAD_DYLINKER, i);
- dyldlc->name = sizeof(*dyldlc);
- str = (char*)dyldlc + dyldlc->name;
- strcpy(str, "/usr/lib/dyld");
- }
-
- dyldbv = add_lc(mo, LC_BUILD_VERSION, sizeof(*dyldbv));
- dyldbv->platform = PLATFORM_MACOS;
- dyldbv->minos = (10 << 16) + (6 << 8);
- dyldbv->sdk = (10 << 16) + (6 << 8);
- dyldbv->ntools = 0;
-
- dyldsv = add_lc(mo, LC_SOURCE_VERSION, sizeof(*dyldsv));
- dyldsv->version = 0;
-
- if (s1->output_type == TCC_OUTPUT_EXE) {
- mo->ep = add_lc(mo, LC_MAIN, sizeof(*mo->ep));
- mo->ep->entryoff = 4096;
- }
-
- for(i = 0; i < s1->nb_loaded_dlls; i++) {
- DLLReference *dllref = s1->loaded_dlls[i];
- if (dllref->level == 0)
- add_dylib(mo, dllref->name);
- }
-
- if (s1->rpath) {
- char *path = s1->rpath, *end;
- do {
- end = strchr(path, ':');
- if (!end)
- end = strchr(path, 0);
- i = (sizeof(*rpath) + (end - path) + 1 + 7) &-8;
- rpath = add_lc(mo, LC_RPATH, i);
- rpath->path = sizeof(*rpath);
- str = (char*)rpath + rpath->path;
- memcpy(str, path, end - path);
- str[end - path] = 0;
- path = end + 1;
- } while (*end);
- }
-
- fileofs = 4096; /* leave space for mach-o headers */
- curaddr = get_segment(mo, s1->output_type == TCC_OUTPUT_EXE)->vmaddr;
- curaddr += 4096;
- seg = NULL;
- numsec = 0;
- mo->elfsectomacho = tcc_mallocz(sizeof(*mo->elfsectomacho) * s1->nb_sections);
- for (sk = sk_unknown; sk < sk_last; sk++) {
- struct section_64 *sec = NULL;
- if (seg) {
- seg->vmsize = curaddr - seg->vmaddr;
- seg->filesize = fileofs - seg->fileoff;
- }
-#ifdef CONFIG_NEW_MACHO
- if (sk == sk_linkedit) {
- calc_fixup_size(s1, mo);
- export_trie(s1, mo);
- }
-#else
- if (sk == sk_linkedit) {
- bind_rebase(s1, mo);
- export_trie(s1, mo);
- }
-#endif
- if (skinfo[sk].seg_initial &&
- (s1->output_type != TCC_OUTPUT_EXE || mo->segment[sk]) &&
- mo->sk_to_sect[sk].s) {
- uint64_t al = 0;
- int si;
- seg = get_segment(mo, mo->segment[sk]);
- if (skinfo[sk].name) {
- si = add_section(mo, &seg, skinfo[sk].name);
- numsec++;
- mo->lc[mo->seg2lc[mo->segment[sk]]] = (struct load_command*)seg;
- mo->sk_to_sect[sk].machosect = si;
- sec = get_section(seg, si);
- sec->flags = skinfo[sk].flags;
- if (sk == sk_stubs)
-#ifdef TCC_TARGET_X86_64
- sec->reserved2 = 6;
-#elif defined TCC_TARGET_ARM64
- sec->reserved2 = 12;
-#endif
- if (sk == sk_nl_ptr)
- sec->reserved1 = mo->nr_plt;
-#ifndef CONFIG_NEW_MACHO
- if (sk == sk_la_ptr)
- sec->reserved1 = mo->nr_plt + mo->n_got;
-#endif
- }
- if (seg->vmaddr == -1) {
- curaddr = (curaddr + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;
- seg->vmaddr = curaddr;
- fileofs = (fileofs + SEG_PAGE_SIZE - 1) & -SEG_PAGE_SIZE;
- seg->fileoff = fileofs;
- }
-
- for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
- int a = exact_log2p1(s->sh_addralign);
- if (a && al < (a - 1))
- al = a - 1;
- s->sh_size = s->data_offset;
- }
- if (sec)
- sec->align = al;
- al = 1ULL << al;
- if (al > 4096)
- tcc_warning("alignment > 4096"), sec->align = 12, al = 4096;
- curaddr = (curaddr + al - 1) & -al;
- fileofs = (fileofs + al - 1) & -al;
- if (sec) {
- sec->addr = curaddr;
- sec->offset = fileofs;
- }
- for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
- al = s->sh_addralign;
- curaddr = (curaddr + al - 1) & -al;
- dprintf("%s: curaddr now 0x%lx\n", s->name, (long)curaddr);
- s->sh_addr = curaddr;
- curaddr += s->sh_size;
- if (s->sh_type != SHT_NOBITS) {
- fileofs = (fileofs + al - 1) & -al;
- s->sh_offset = fileofs;
- fileofs += s->sh_size;
- dprintf("%s: fileofs now %ld\n", s->name, (long)fileofs);
- }
- if (sec)
- mo->elfsectomacho[s->sh_num] = numsec;
- }
- if (sec)
- sec->size = curaddr - sec->addr;
- }
- if (DEBUG_MACHO)
- for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
- int type = s->sh_type;
- int flags = s->sh_flags;
- printf("%d section %-16s %-10s %09lx %04x %02d %s,%s,%s\n",
- sk,
- s->name,
- type == SHT_PROGBITS ? "progbits" :
- type == SHT_NOBITS ? "nobits" :
- type == SHT_SYMTAB ? "symtab" :
- type == SHT_STRTAB ? "strtab" :
- type == SHT_INIT_ARRAY ? "init" :
- type == SHT_FINI_ARRAY ? "fini" :
- type == SHT_RELX ? "rel" : "???",
- (long)s->sh_addr,
- (unsigned)s->data_offset,
- s->sh_addralign,
- flags & SHF_ALLOC ? "alloc" : "",
- flags & SHF_WRITE ? "write" : "",
- flags & SHF_EXECINSTR ? "exec" : ""
- );
- }
- }
- if (seg) {
- seg->vmsize = curaddr - seg->vmaddr;
- seg->filesize = fileofs - seg->fileoff;
- }
-
- /* Fill symtab info */
- symlc->symoff = mo->symtab->sh_offset;
- symlc->nsyms = mo->symtab->data_offset / sizeof(struct nlist_64);
- symlc->stroff = mo->strtab->sh_offset;
- symlc->strsize = mo->strtab->data_offset;
-
- dysymlc->iundefsym = mo->iundef == -1 ? symlc->nsyms : mo->iundef;
- dysymlc->iextdefsym = mo->iextdef == -1 ? dysymlc->iundefsym : mo->iextdef;
- dysymlc->ilocalsym = mo->ilocal == -1 ? dysymlc->iextdefsym : mo->ilocal;
- dysymlc->nlocalsym = dysymlc->iextdefsym - dysymlc->ilocalsym;
- dysymlc->nextdefsym = dysymlc->iundefsym - dysymlc->iextdefsym;
- dysymlc->nundefsym = symlc->nsyms - dysymlc->iundefsym;
- dysymlc->indirectsymoff = mo->indirsyms->sh_offset;
- dysymlc->nindirectsyms = mo->indirsyms->data_offset / sizeof(uint32_t);
-
-#ifdef CONFIG_NEW_MACHO
- if (mo->chained_fixups->data_offset) {
- chained_fixups_lc->dataoff = mo->chained_fixups->sh_offset;
- chained_fixups_lc->datasize = mo->chained_fixups->data_offset;
- }
- if (mo->exports->data_offset) {
- export_trie_lc->dataoff = mo->exports->sh_offset;
- export_trie_lc->datasize = mo->exports->data_offset;
- }
-#else
- if (mo->rebase->data_offset) {
- mo->dyldinfo->rebase_off = mo->rebase->sh_offset;
- mo->dyldinfo->rebase_size = mo->rebase->data_offset;
- }
- if (mo->binding->data_offset) {
- mo->dyldinfo->bind_off = mo->binding->sh_offset;
- mo->dyldinfo->bind_size = mo->binding->data_offset;
- }
- if (mo->weak_binding->data_offset) {
- mo->dyldinfo->weak_bind_off = mo->weak_binding->sh_offset;
- mo->dyldinfo->weak_bind_size = mo->weak_binding->data_offset;
- }
- if (mo->lazy_binding->data_offset) {
- mo->dyldinfo->lazy_bind_off = mo->lazy_binding->sh_offset;
- mo->dyldinfo->lazy_bind_size = mo->lazy_binding->data_offset;
- }
- if (mo->exports->data_offset) {
- mo->dyldinfo->export_off = mo->exports->sh_offset;
- mo->dyldinfo->export_size = mo->exports->data_offset;
- }
-#endif
-}
-
-static void macho_write(TCCState *s1, struct macho *mo, FILE *fp)
-{
- int i, sk;
- uint64_t fileofs = 0;
- Section *s;
- mo->mh.mh.magic = MH_MAGIC_64;
-#ifdef TCC_TARGET_X86_64
- mo->mh.mh.cputype = CPU_TYPE_X86_64;
- mo->mh.mh.cpusubtype = CPU_SUBTYPE_LIB64 | CPU_SUBTYPE_X86_ALL;
-#elif defined TCC_TARGET_ARM64
- mo->mh.mh.cputype = CPU_TYPE_ARM64;
- mo->mh.mh.cpusubtype = CPU_SUBTYPE_ARM64_ALL;
-#endif
- if (s1->output_type == TCC_OUTPUT_EXE) {
- mo->mh.mh.filetype = MH_EXECUTE;
- mo->mh.mh.flags = MH_DYLDLINK | MH_PIE;
- }
- else {
- mo->mh.mh.filetype = MH_DYLIB;
- mo->mh.mh.flags = MH_DYLDLINK;
- }
- mo->mh.mh.ncmds = mo->nlc;
- mo->mh.mh.sizeofcmds = 0;
- for (i = 0; i < mo->nlc; i++)
- mo->mh.mh.sizeofcmds += mo->lc[i]->cmdsize;
-
- fwrite(&mo->mh, 1, sizeof(mo->mh), fp);
- fileofs += sizeof(mo->mh);
- for (i = 0; i < mo->nlc; i++) {
- fwrite(mo->lc[i], 1, mo->lc[i]->cmdsize, fp);
- fileofs += mo->lc[i]->cmdsize;
- }
-
- for (sk = sk_unknown; sk < sk_last; sk++) {
- //struct segment_command_64 *seg;
- if (skinfo[sk].seg_initial == 0 ||
- (s1->output_type == TCC_OUTPUT_EXE && !mo->segment[sk]) ||
- !mo->sk_to_sect[sk].s)
- continue;
- /*seg =*/ get_segment(mo, mo->segment[sk]);
- for (s = mo->sk_to_sect[sk].s; s; s = s->prev) {
- if (s->sh_type != SHT_NOBITS) {
- while (fileofs < s->sh_offset)
- fputc(0, fp), fileofs++;
- if (s->sh_size) {
- fwrite(s->data, 1, s->sh_size, fp);
- fileofs += s->sh_size;
- }
- }
- }
- }
-}
-
-#ifdef CONFIG_NEW_MACHO
-static int bind_rebase_cmp(const void *_a, const void *_b, void *arg)
-{
- TCCState *s1 = arg;
- struct bind_rebase *a = (struct bind_rebase *) _a;
- struct bind_rebase *b = (struct bind_rebase *) _b;
- addr_t aa = s1->sections[a->section]->sh_addr + a->rel.r_offset;
- addr_t ab = s1->sections[b->section]->sh_addr + b->rel.r_offset;
-
- return aa > ab ? 1 : aa < ab ? -1 : 0;
-}
-
-ST_FUNC void bind_rebase_import(TCCState *s1, struct macho *mo)
-{
- int i, j, k, bind_index, size, page_count, sym_index;
- const char *name;
- ElfW(Sym) *sym;
- unsigned char *data = mo->chained_fixups->data;
- struct segment_command_64 *seg;
- struct dyld_chained_fixups_header *header;
- struct dyld_chained_starts_in_image *image;
- struct dyld_chained_starts_in_segment *segment;
- struct dyld_chained_import *import;
-
- tcc_qsort(mo->bind_rebase, mo->n_bind_rebase, sizeof(struct bind_rebase),
- bind_rebase_cmp, s1);
- for (i = 0; i < mo->n_bind_rebase - 1; i++)
- if (mo->bind_rebase[i].section == mo->bind_rebase[i + 1].section &&
- mo->bind_rebase[i].rel.r_offset == mo->bind_rebase[i + 1].rel.r_offset) {
- sym_index = ELFW(R_SYM)(mo->bind_rebase[i].rel.r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- name = (char *) symtab_section->link->data + sym->st_name;
- tcc_error("Overlap %s/%s %s:%s",
- mo->bind_rebase[i].bind ? "bind" : "rebase",
- mo->bind_rebase[i + 1].bind ? "bind" : "rebase",
- s1->sections[mo->bind_rebase[i].section]->name, name);
- }
- header = (struct dyld_chained_fixups_header *) data;
- data += (sizeof(struct dyld_chained_fixups_header) + 7) & -8;
- header->starts_offset = data - mo->chained_fixups->data;
- header->imports_count = mo->n_bind;
- header->imports_format = DYLD_CHAINED_IMPORT;
- header->symbols_format = 0;
- size = sizeof(struct dyld_chained_starts_in_image) +
- (mo->nseg - 1) * sizeof(uint32_t);
- image = (struct dyld_chained_starts_in_image *) data;
- data += (size + 7) & -8;
- image->seg_count = mo->nseg;
- for (i = (s1->output_type == TCC_OUTPUT_EXE); i < mo->nseg - 1; i++) {
- image->seg_info_offset[i] = (data - mo->chained_fixups->data) -
- header->starts_offset;
- seg = get_segment(mo, i);
- page_count = (seg->vmsize + SEG_PAGE_SIZE - 1) / SEG_PAGE_SIZE;
- size = sizeof(struct dyld_chained_starts_in_segment) +
- (page_count - 1) * sizeof(uint16_t);
- segment = (struct dyld_chained_starts_in_segment *) data;
- data += (size + 7) & -8;
- segment->size = size;
- segment->page_size = SEG_PAGE_SIZE;
-#if 1
-#define PTR_64_OFFSET 0
-#define PTR_64_MASK 0x7FFFFFFFFFFULL
- segment->pointer_format = DYLD_CHAINED_PTR_64;
-#else
-#define PTR_64_OFFSET 0x100000000ULL
-#define PTR_64_MASK 0xFFFFFFFFFFFFFFULL
- segment->pointer_format = DYLD_CHAINED_PTR_64_OFFSET;
-#endif
- segment->segment_offset = seg->fileoff;
- segment->max_valid_pointer = 0;
- segment->page_count = page_count;
- // add bind/rebase
- bind_index = 0;
- k = 0;
- for (j = 0; j < page_count; j++) {
- addr_t start = seg->vmaddr + j * SEG_PAGE_SIZE;
- addr_t end = start + SEG_PAGE_SIZE;
- void *last = NULL;
- addr_t last_o = 0;
- addr_t cur_o, cur;
- struct dyld_chained_ptr_64_rebase *rebase;
- struct dyld_chained_ptr_64_bind *bind;
-
- segment->page_start[j] = DYLD_CHAINED_PTR_START_NONE;
- for (; k < mo->n_bind_rebase; k++) {
- Section *s = s1->sections[mo->bind_rebase[k].section];
- addr_t r_offset = mo->bind_rebase[k].rel.r_offset;
- addr_t addr = s->sh_addr + r_offset;
-
- if ((addr & 3) ||
- (addr & (SEG_PAGE_SIZE - 1)) > SEG_PAGE_SIZE - PTR_SIZE)
- tcc_error("Illegal rel_offset %s %lld",
- s->name, (long long)r_offset);
- if (addr >= end)
- break;
- if (addr >= start) {
- cur_o = addr - start;
- if (mo->bind_rebase[k].bind) {
- if (segment->page_start[j] == DYLD_CHAINED_PTR_START_NONE)
- segment->page_start[j] = cur_o;
- else {
- bind = (struct dyld_chained_ptr_64_bind *) last;
- bind->next = (cur_o - last_o) / 4;
- }
- bind = (struct dyld_chained_ptr_64_bind *)
- (s->data + r_offset);
- last = bind;
- last_o = cur_o;
- bind->ordinal = bind_index;
- bind->addend = 0;
- bind->reserved = 0;
- bind->next = 0;
- bind->bind = 1;
- }
- else {
- if (segment->page_start[j] == DYLD_CHAINED_PTR_START_NONE)
- segment->page_start[j] = cur_o;
- else {
- rebase = (struct dyld_chained_ptr_64_rebase *) last;
- rebase->next = (cur_o - last_o) / 4;
- }
- rebase = (struct dyld_chained_ptr_64_rebase *)
- (s->data + r_offset);
- last = rebase;
- last_o = cur_o;
- cur = (*(uint64_t *) (s->data + r_offset)) -
- PTR_64_OFFSET;
- rebase->target = cur & PTR_64_MASK;
- rebase->high8 = cur >> (64 - 8);
- if (cur != ((uint64_t)rebase->high8 << (64 - 8)) + rebase->target)
- tcc_error("rebase error");
- rebase->reserved = 0;
- rebase->next = 0;
- rebase->bind = 0;
- }
- }
- bind_index += mo->bind_rebase[k].bind;
- }
- }
- }
- // add imports
- header->imports_offset = data - mo->chained_fixups->data;
- import = (struct dyld_chained_import *) data;
- data += mo->n_bind * sizeof (struct dyld_chained_import);
- header->symbols_offset = data - mo->chained_fixups->data;
- data++;
- for (i = 0, bind_index = 0; i < mo->n_bind_rebase; i++) {
- if (mo->bind_rebase[i].bind) {
- import[bind_index].lib_ordinal =
- BIND_SPECIAL_DYLIB_FLAT_LOOKUP & 0xffu;
- import[bind_index].name_offset =
- (data - mo->chained_fixups->data) - header->symbols_offset;
- sym_index = ELFW(R_SYM)(mo->bind_rebase[i].rel.r_info);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- import[bind_index].weak_import =
- ELFW(ST_BIND)(sym->st_info) == STB_WEAK;
- name = (char *) symtab_section->link->data + sym->st_name;
- strcpy((char *) data, name);
- data += strlen(name) + 1;
- bind_index++;
- }
- }
- tcc_free(mo->bind_rebase);
-}
-#endif
-
-ST_FUNC int macho_output_file(TCCState *s1, const char *filename)
-{
- int fd, mode, file_type;
- FILE *fp;
- int i, ret = -1;
- struct macho mo;
-
- (void)memset(&mo, 0, sizeof(mo));
-
- file_type = s1->output_type;
- if (file_type == TCC_OUTPUT_OBJ)
- mode = 0666;
- else
- mode = 0777;
- unlink(filename);
- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
- if (fd < 0 || (fp = fdopen(fd, "wb")) == NULL) {
- tcc_error_noabort("could not write '%s: %s'", filename, strerror(errno));
- return -1;
- }
- if (s1->verbose)
- printf("<- %s\n", filename);
-
- tcc_add_runtime(s1);
- tcc_macho_add_destructor(s1);
- resolve_common_syms(s1);
- create_symtab(s1, &mo);
- check_relocs(s1, &mo);
- ret = check_symbols(s1, &mo);
- if (!ret) {
- int save_output = s1->output_type;
-
- collect_sections(s1, &mo, filename);
- relocate_syms(s1, s1->symtab, 0);
- if (s1->output_type == TCC_OUTPUT_EXE)
- mo.ep->entryoff = get_sym_addr(s1, "main", 1, 1)
- - get_segment(&mo, 1)->vmaddr;
- if (s1->nb_errors)
- goto do_ret;
- // Macho uses bind/rebase instead of dynsym
- s1->output_type = TCC_OUTPUT_EXE;
- relocate_sections(s1);
- s1->output_type = save_output;
-#ifdef CONFIG_NEW_MACHO
- bind_rebase_import(s1, &mo);
-#endif
- convert_symbols(s1, &mo);
- macho_write(s1, &mo, fp);
- }
-
- do_ret:
- for (i = 0; i < mo.nlc; i++)
- tcc_free(mo.lc[i]);
- tcc_free(mo.seg2lc);
- tcc_free(mo.lc);
- tcc_free(mo.elfsectomacho);
- tcc_free(mo.e2msym);
-
- fclose(fp);
-#ifdef CONFIG_CODESIGN
- {
- char command[1024];
- int retval;
-
- snprintf(command, sizeof(command), "codesign -f -s - %s", filename);
- retval = system (command);
- if (retval == -1 || !(WIFEXITED(retval) && WEXITSTATUS(retval) == 0))
- tcc_error ("command failed '%s'", command);
- }
-#endif
- return ret;
-}
-
-static uint32_t macho_swap32(uint32_t x)
-{
- return (x >> 24) | (x << 24) | ((x >> 8) & 0xff00) | ((x & 0xff00) << 8);
-}
-#define SWAP(x) (swap ? macho_swap32(x) : (x))
-#define tbd_parse_movepast(s) \
- (pos = (pos = strstr(pos, s)) ? pos + strlen(s) : NULL)
-#define tbd_parse_movetoany(cs) (pos = strpbrk(pos, cs))
-#define tbd_parse_skipws while (*pos && (*pos==' '||*pos=='\n')) ++pos
-#define tbd_parse_tramplequote if(*pos=='\''||*pos=='"') tbd_parse_trample
-#define tbd_parse_tramplespace if(*pos==' ') tbd_parse_trample
-#define tbd_parse_trample *pos++=0
-
-#ifdef TCC_IS_NATIVE
-/* Looks for the active developer SDK set by xcode-select (or the default
- one set during installation.) */
-ST_FUNC void tcc_add_macos_sdkpath(TCCState* s)
-{
- char *sdkroot = NULL, *pos = NULL;
- void* xcs = dlopen("libxcselect.dylib", RTLD_GLOBAL | RTLD_LAZY);
- CString path;
- int (*f)(unsigned int, char**) = dlsym(xcs, "xcselect_host_sdk_path");
- cstr_new(&path);
- if (f) f(1, &sdkroot);
- if (sdkroot)
- pos = strstr(sdkroot,"SDKs/MacOSX");
- if (pos)
- cstr_printf(&path, "%.*s.sdk/usr/lib", (int)(pos - sdkroot + 11), sdkroot);
- /* must use free from libc directly */
-#pragma push_macro("free")
-#undef free
- free(sdkroot);
-#pragma pop_macro("free")
- if (path.size)
- tcc_add_library_path(s, (char*)path.data);
- else
- tcc_add_library_path(s,
- "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib"
- ":" "/Applications/Xcode.app/Developer/SDKs/MacOSX.sdk/usr/lib"
- );
- cstr_free(&path);
-}
-
-ST_FUNC const char* macho_tbd_soname(const char* filename) {
- char *soname, *data, *pos;
- const char *ret = filename;
-
- int fd = open(filename,O_RDONLY);
- if (fd<0) return ret;
- pos = data = tcc_load_text(fd);
- if (!tbd_parse_movepast("install-name: ")) goto the_end;
- tbd_parse_skipws;
- tbd_parse_tramplequote;
- soname = pos;
- if (!tbd_parse_movetoany("\n \"'")) goto the_end;
- tbd_parse_trample;
- ret = tcc_strdup(soname);
-the_end:
- tcc_free(data);
- return ret;
-}
-#endif /* TCC_IS_NATIVE */
-
-ST_FUNC int macho_load_tbd(TCCState* s1, int fd, const char* filename, int lev)
-{
- char *soname, *data, *pos;
- int ret = -1;
-
- pos = data = tcc_load_text(fd);
- if (!tbd_parse_movepast("install-name: ")) goto the_end;
- tbd_parse_skipws;
- tbd_parse_tramplequote;
- soname = pos;
- if (!tbd_parse_movetoany("\n \"'")) goto the_end;
- tbd_parse_trample;
- ret = 0;
- if (tcc_add_dllref(s1, soname, lev)->found)
- goto the_end;
- while(pos) {
- char* sym = NULL;
- int cont = 1;
- if (!tbd_parse_movepast("symbols: ")) break;
- if (!tbd_parse_movepast("[")) break;
- while (cont) {
- tbd_parse_skipws;
- tbd_parse_tramplequote;
- sym = pos;
- if (!tbd_parse_movetoany(",] \"'")) break;
- tbd_parse_tramplequote;
- tbd_parse_tramplespace;
- tbd_parse_skipws;
- if (*pos==0||*pos==']') cont=0;
- tbd_parse_trample;
- set_elf_sym(s1->dynsymtab_section, 0, 0,
- ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, SHN_UNDEF, sym);
- }
- }
-
-the_end:
- tcc_free(data);
- return ret;
-}
-
-ST_FUNC int macho_load_dll(TCCState * s1, int fd, const char* filename, int lev)
-{
- unsigned char buf[sizeof(struct mach_header_64)];
- void *buf2;
- uint32_t machofs = 0;
- struct fat_header fh;
- struct mach_header mh;
- struct load_command *lc;
- int i, swap = 0;
- const char *soname = filename;
- struct nlist_64 *symtab = 0;
- uint32_t nsyms = 0;
- char *strtab = 0;
- uint32_t strsize = 0;
- uint32_t iextdef = 0;
- uint32_t nextdef = 0;
-
- again:
- if (full_read(fd, buf, sizeof(buf)) != sizeof(buf))
- return -1;
- memcpy(&fh, buf, sizeof(fh));
- if (fh.magic == FAT_MAGIC || fh.magic == FAT_CIGAM) {
- struct fat_arch *fa = load_data(fd, sizeof(fh),
- fh.nfat_arch * sizeof(*fa));
- swap = fh.magic == FAT_CIGAM;
- for (i = 0; i < SWAP(fh.nfat_arch); i++)
-#ifdef TCC_TARGET_X86_64
- if (SWAP(fa[i].cputype) == CPU_TYPE_X86_64
- && SWAP(fa[i].cpusubtype) == CPU_SUBTYPE_X86_ALL)
-#elif defined TCC_TARGET_ARM64
- if (SWAP(fa[i].cputype) == CPU_TYPE_ARM64
- && SWAP(fa[i].cpusubtype) == CPU_SUBTYPE_ARM64_ALL)
-#endif
- break;
- if (i == SWAP(fh.nfat_arch)) {
- tcc_free(fa);
- return -1;
- }
- machofs = SWAP(fa[i].offset);
- tcc_free(fa);
- lseek(fd, machofs, SEEK_SET);
- goto again;
- } else if (fh.magic == FAT_MAGIC_64 || fh.magic == FAT_CIGAM_64) {
- tcc_warning("%s: Mach-O fat 64bit files of type 0x%x not handled",
- filename, fh.magic);
- return -1;
- }
-
- memcpy(&mh, buf, sizeof(mh));
- if (mh.magic != MH_MAGIC_64)
- return -1;
- dprintf("found Mach-O at %d\n", machofs);
- buf2 = load_data(fd, machofs + sizeof(struct mach_header_64), mh.sizeofcmds);
- for (i = 0, lc = buf2; i < mh.ncmds; i++) {
- dprintf("lc %2d: 0x%08x\n", i, lc->cmd);
- switch (lc->cmd) {
- case LC_SYMTAB:
- {
- struct symtab_command *sc = (struct symtab_command*)lc;
- nsyms = sc->nsyms;
- symtab = load_data(fd, machofs + sc->symoff, nsyms * sizeof(*symtab));
- strsize = sc->strsize;
- strtab = load_data(fd, machofs + sc->stroff, strsize);
- break;
- }
- case LC_ID_DYLIB:
- {
- struct dylib_command *dc = (struct dylib_command*)lc;
- soname = (char*)lc + dc->name;
- dprintf(" ID_DYLIB %d 0x%x 0x%x %s\n",
- dc->timestamp, dc->current_version,
- dc->compatibility_version, soname);
- break;
- }
- case LC_REEXPORT_DYLIB:
- {
- struct dylib_command *dc = (struct dylib_command*)lc;
- char *name = (char*)lc + dc->name;
- int subfd = open(name, O_RDONLY | O_BINARY);
- dprintf(" REEXPORT %s\n", name);
- if (subfd < 0)
- tcc_warning("can't open %s (reexported from %s)", name, filename);
- else {
- /* Hopefully the REEXPORTs never form a cycle, we don't check
- for that! */
- macho_load_dll(s1, subfd, name, lev + 1);
- close(subfd);
- }
- break;
- }
- case LC_DYSYMTAB:
- {
- struct dysymtab_command *dc = (struct dysymtab_command*)lc;
- iextdef = dc->iextdefsym;
- nextdef = dc->nextdefsym;
- break;
- }
- }
- lc = (struct load_command*) ((char*)lc + lc->cmdsize);
- }
-
- if (tcc_add_dllref(s1, soname, lev)->found)
- goto the_end;
-
- if (!nsyms || !nextdef)
- tcc_warning("%s doesn't export any symbols?", filename);
-
- //dprintf("symbols (all):\n");
- dprintf("symbols (exported):\n");
- dprintf(" n: typ sec desc value name\n");
- //for (i = 0; i < nsyms; i++) {
- for (i = iextdef; i < iextdef + nextdef; i++) {
- struct nlist_64 *sym = symtab + i;
- dprintf("%5d: %3d %3d 0x%04x 0x%016lx %s\n",
- i, sym->n_type, sym->n_sect, sym->n_desc, (long)sym->n_value,
- strtab + sym->n_strx);
- set_elf_sym(s1->dynsymtab_section, 0, 0,
- ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
- 0, SHN_UNDEF, strtab + sym->n_strx);
- }
-
- the_end:
- tcc_free(strtab);
- tcc_free(symtab);
- tcc_free(buf2);
- return 0;
-}
diff --git a/tinycc/tccpe.c b/tinycc/tccpe.c
deleted file mode 100644
index ab610af..0000000
--- a/tinycc/tccpe.c
+++ /dev/null
@@ -1,2036 +0,0 @@
-/*
- * TCCPE.C - PE file output for the Tiny C Compiler
- *
- * Copyright (c) 2005-2007 grischka
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "tcc.h"
-
-#define PE_MERGE_DATA 1
-#define PE_PRINT_SECTIONS 0
-
-#ifndef _WIN32
-#define stricmp strcasecmp
-#define strnicmp strncasecmp
-#include <sys/stat.h> /* chmod() */
-#endif
-
-#ifdef TCC_TARGET_X86_64
-# define ADDR3264 ULONGLONG
-# define PE_IMAGE_REL IMAGE_REL_BASED_DIR64
-# define REL_TYPE_DIRECT R_X86_64_64
-# define R_XXX_THUNKFIX R_X86_64_PC32
-# define R_XXX_RELATIVE R_X86_64_RELATIVE
-# define R_XXX_FUNCCALL R_X86_64_PC32
-# define IMAGE_FILE_MACHINE 0x8664
-# define RSRC_RELTYPE 3
-
-#elif defined TCC_TARGET_ARM
-# define ADDR3264 DWORD
-# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW
-# define REL_TYPE_DIRECT R_ARM_ABS32
-# define R_XXX_THUNKFIX R_ARM_ABS32
-# define R_XXX_RELATIVE R_ARM_RELATIVE
-# define R_XXX_FUNCCALL R_ARM_PC24
-# define R_XXX_FUNCCALL2 R_ARM_ABS32
-# define IMAGE_FILE_MACHINE 0x01C0
-# define RSRC_RELTYPE 7 /* ??? (not tested) */
-
-#elif defined TCC_TARGET_I386
-# define ADDR3264 DWORD
-# define PE_IMAGE_REL IMAGE_REL_BASED_HIGHLOW
-# define REL_TYPE_DIRECT R_386_32
-# define R_XXX_THUNKFIX R_386_32
-# define R_XXX_RELATIVE R_386_RELATIVE
-# define R_XXX_FUNCCALL R_386_PC32
-# define IMAGE_FILE_MACHINE 0x014C
-# define RSRC_RELTYPE 7 /* DIR32NB */
-
-#endif
-
-#ifndef IMAGE_NT_SIGNATURE
-/* ----------------------------------------------------------- */
-/* definitions below are from winnt.h */
-
-typedef unsigned char BYTE;
-typedef unsigned short WORD;
-typedef unsigned int DWORD;
-typedef unsigned long long ULONGLONG;
-#pragma pack(push, 1)
-
-typedef struct _IMAGE_DOS_HEADER { /* DOS .EXE header */
- WORD e_magic; /* Magic number */
- WORD e_cblp; /* Bytes on last page of file */
- WORD e_cp; /* Pages in file */
- WORD e_crlc; /* Relocations */
- WORD e_cparhdr; /* Size of header in paragraphs */
- WORD e_minalloc; /* Minimum extra paragraphs needed */
- WORD e_maxalloc; /* Maximum extra paragraphs needed */
- WORD e_ss; /* Initial (relative) SS value */
- WORD e_sp; /* Initial SP value */
- WORD e_csum; /* Checksum */
- WORD e_ip; /* Initial IP value */
- WORD e_cs; /* Initial (relative) CS value */
- WORD e_lfarlc; /* File address of relocation table */
- WORD e_ovno; /* Overlay number */
- WORD e_res[4]; /* Reserved words */
- WORD e_oemid; /* OEM identifier (for e_oeminfo) */
- WORD e_oeminfo; /* OEM information; e_oemid specific */
- WORD e_res2[10]; /* Reserved words */
- DWORD e_lfanew; /* File address of new exe header */
-} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
-
-#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
-#define SIZE_OF_NT_SIGNATURE 4
-
-typedef struct _IMAGE_FILE_HEADER {
- WORD Machine;
- WORD NumberOfSections;
- DWORD TimeDateStamp;
- DWORD PointerToSymbolTable;
- DWORD NumberOfSymbols;
- WORD SizeOfOptionalHeader;
- WORD Characteristics;
-} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
-
-
-#define IMAGE_SIZEOF_FILE_HEADER 20
-
-typedef struct _IMAGE_DATA_DIRECTORY {
- DWORD VirtualAddress;
- DWORD Size;
-} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
-
-
-typedef struct _IMAGE_OPTIONAL_HEADER {
- /* Standard fields. */
- WORD Magic;
- BYTE MajorLinkerVersion;
- BYTE MinorLinkerVersion;
- DWORD SizeOfCode;
- DWORD SizeOfInitializedData;
- DWORD SizeOfUninitializedData;
- DWORD AddressOfEntryPoint;
- DWORD BaseOfCode;
-#ifndef TCC_TARGET_X86_64
- DWORD BaseOfData;
-#endif
- /* NT additional fields. */
- ADDR3264 ImageBase;
- DWORD SectionAlignment;
- DWORD FileAlignment;
- WORD MajorOperatingSystemVersion;
- WORD MinorOperatingSystemVersion;
- WORD MajorImageVersion;
- WORD MinorImageVersion;
- WORD MajorSubsystemVersion;
- WORD MinorSubsystemVersion;
- DWORD Win32VersionValue;
- DWORD SizeOfImage;
- DWORD SizeOfHeaders;
- DWORD CheckSum;
- WORD Subsystem;
- WORD DllCharacteristics;
- ADDR3264 SizeOfStackReserve;
- ADDR3264 SizeOfStackCommit;
- ADDR3264 SizeOfHeapReserve;
- ADDR3264 SizeOfHeapCommit;
- DWORD LoaderFlags;
- DWORD NumberOfRvaAndSizes;
- IMAGE_DATA_DIRECTORY DataDirectory[16];
-} IMAGE_OPTIONAL_HEADER32, IMAGE_OPTIONAL_HEADER64, IMAGE_OPTIONAL_HEADER;
-
-#define IMAGE_DIRECTORY_ENTRY_EXPORT 0 /* Export Directory */
-#define IMAGE_DIRECTORY_ENTRY_IMPORT 1 /* Import Directory */
-#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 /* Resource Directory */
-#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 /* Exception Directory */
-#define IMAGE_DIRECTORY_ENTRY_SECURITY 4 /* Security Directory */
-#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 /* Base Relocation Table */
-#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 /* Debug Directory */
-/* IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 (X86 usage) */
-#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE 7 /* Architecture Specific Data */
-#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* RVA of GP */
-#define IMAGE_DIRECTORY_ENTRY_TLS 9 /* TLS Directory */
-#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 /* Load Configuration Directory */
-#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11 /* Bound Import Directory in headers */
-#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */
-#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13 /* Delay Load Import Descriptors */
-#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14 /* COM Runtime descriptor */
-
-/* Section header format. */
-#define IMAGE_SIZEOF_SHORT_NAME 8
-
-typedef struct _IMAGE_SECTION_HEADER {
- BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
- union {
- DWORD PhysicalAddress;
- DWORD VirtualSize;
- } Misc;
- DWORD VirtualAddress;
- DWORD SizeOfRawData;
- DWORD PointerToRawData;
- DWORD PointerToRelocations;
- DWORD PointerToLinenumbers;
- WORD NumberOfRelocations;
- WORD NumberOfLinenumbers;
- DWORD Characteristics;
-} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
-
-#define IMAGE_SIZEOF_SECTION_HEADER 40
-
-typedef struct _IMAGE_EXPORT_DIRECTORY {
- DWORD Characteristics;
- DWORD TimeDateStamp;
- WORD MajorVersion;
- WORD MinorVersion;
- DWORD Name;
- DWORD Base;
- DWORD NumberOfFunctions;
- DWORD NumberOfNames;
- DWORD AddressOfFunctions;
- DWORD AddressOfNames;
- DWORD AddressOfNameOrdinals;
-} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
-
-typedef struct _IMAGE_IMPORT_DESCRIPTOR {
- union {
- DWORD Characteristics;
- DWORD OriginalFirstThunk;
- };
- DWORD TimeDateStamp;
- DWORD ForwarderChain;
- DWORD Name;
- DWORD FirstThunk;
-} IMAGE_IMPORT_DESCRIPTOR;
-
-typedef struct _IMAGE_BASE_RELOCATION {
- DWORD VirtualAddress;
- DWORD SizeOfBlock;
-// WORD TypeOffset[1];
-} IMAGE_BASE_RELOCATION;
-
-#define IMAGE_SIZEOF_BASE_RELOCATION 8
-
-#define IMAGE_REL_BASED_ABSOLUTE 0
-#define IMAGE_REL_BASED_HIGH 1
-#define IMAGE_REL_BASED_LOW 2
-#define IMAGE_REL_BASED_HIGHLOW 3
-#define IMAGE_REL_BASED_HIGHADJ 4
-#define IMAGE_REL_BASED_MIPS_JMPADDR 5
-#define IMAGE_REL_BASED_SECTION 6
-#define IMAGE_REL_BASED_REL32 7
-#define IMAGE_REL_BASED_DIR64 10
-
-#define IMAGE_SCN_CNT_CODE 0x00000020
-#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
-#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
-#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
-#define IMAGE_SCN_MEM_SHARED 0x10000000
-#define IMAGE_SCN_MEM_EXECUTE 0x20000000
-#define IMAGE_SCN_MEM_READ 0x40000000
-#define IMAGE_SCN_MEM_WRITE 0x80000000
-
-#pragma pack(pop)
-
-/* ----------------------------------------------------------- */
-#endif /* ndef IMAGE_NT_SIGNATURE */
-/* ----------------------------------------------------------- */
-
-#ifndef IMAGE_REL_BASED_DIR64
-# define IMAGE_REL_BASED_DIR64 10
-#endif
-
-#pragma pack(push, 1)
-struct pe_header
-{
- IMAGE_DOS_HEADER doshdr;
- BYTE dosstub[0x40];
- DWORD nt_sig;
- IMAGE_FILE_HEADER filehdr;
-#ifdef TCC_TARGET_X86_64
- IMAGE_OPTIONAL_HEADER64 opthdr;
-#else
-#ifdef _WIN64
- IMAGE_OPTIONAL_HEADER32 opthdr;
-#else
- IMAGE_OPTIONAL_HEADER opthdr;
-#endif
-#endif
-};
-
-struct pe_reloc_header {
- DWORD offset;
- DWORD size;
-};
-
-struct pe_rsrc_header {
- struct _IMAGE_FILE_HEADER filehdr;
- struct _IMAGE_SECTION_HEADER sectionhdr;
-};
-
-struct pe_rsrc_reloc {
- DWORD offset;
- DWORD size;
- WORD type;
-};
-#pragma pack(pop)
-
-/* ------------------------------------------------------------- */
-/* internal temporary structures */
-
-enum {
- sec_text = 0,
- sec_rdata ,
- sec_data ,
- sec_bss ,
- sec_idata ,
- sec_pdata ,
- sec_other ,
- sec_rsrc ,
- sec_stab ,
- sec_stabstr ,
- sec_reloc ,
- sec_last
-};
-
-#if 0
-static const DWORD pe_sec_flags[] = {
- 0x60000020, /* ".text" , */
- 0xC0000040, /* ".data" , */
- 0xC0000080, /* ".bss" , */
- 0x40000040, /* ".idata" , */
- 0x40000040, /* ".pdata" , */
- 0xE0000060, /* < other > , */
- 0x40000040, /* ".rsrc" , */
- 0x42000802, /* ".stab" , */
- 0x42000040, /* ".reloc" , */
-};
-#endif
-
-struct section_info {
- int cls;
- char name[32];
- ADDR3264 sh_addr;
- DWORD sh_size;
- DWORD pe_flags;
- Section *sec;
- DWORD data_size;
- IMAGE_SECTION_HEADER ish;
-};
-
-struct import_symbol {
- int sym_index;
- int iat_index;
- int thk_offset;
-};
-
-struct pe_import_info {
- int dll_index;
- int sym_count;
- struct import_symbol **symbols;
-};
-
-struct pe_info {
- TCCState *s1;
- Section *reloc;
- Section *thunk;
- const char *filename;
- int type;
- DWORD sizeofheaders;
- ADDR3264 imagebase;
- const char *start_symbol;
- DWORD start_addr;
- DWORD imp_offs;
- DWORD imp_size;
- DWORD iat_offs;
- DWORD iat_size;
- DWORD exp_offs;
- DWORD exp_size;
- int subsystem;
- DWORD section_align;
- DWORD file_align;
- struct section_info **sec_info;
- int sec_count;
- struct pe_import_info **imp_info;
- int imp_count;
-};
-
-#define PE_NUL 0
-#define PE_DLL 1
-#define PE_GUI 2
-#define PE_EXE 3
-#define PE_RUN 4
-
-/* --------------------------------------------*/
-
-static const char *pe_export_name(TCCState *s1, ElfW(Sym) *sym)
-{
- const char *name = (char*)symtab_section->link->data + sym->st_name;
- if (s1->leading_underscore && name[0] == '_' && !(sym->st_other & ST_PE_STDCALL))
- return name + 1;
- return name;
-}
-
-static int pe_find_import(TCCState * s1, ElfW(Sym) *sym)
-{
- char buffer[200];
- const char *s, *p;
- int sym_index = 0, n = 0;
- int a, err = 0;
-
- do {
- s = pe_export_name(s1, sym);
- a = 0;
- if (n) {
- /* second try: */
- if (sym->st_other & ST_PE_STDCALL) {
- /* try w/0 stdcall deco (windows API convention) */
- p = strrchr(s, '@');
- if (!p || s[0] != '_')
- break;
- strcpy(buffer, s+1)[p-s-1] = 0;
- } else if (s[0] != '_') { /* try non-ansi function */
- buffer[0] = '_', strcpy(buffer + 1, s);
- } else if (0 == memcmp(s, "__imp_", 6)) { /* mingw 2.0 */
- strcpy(buffer, s + 6), a = 1;
- } else if (0 == memcmp(s, "_imp__", 6)) { /* mingw 3.7 */
- strcpy(buffer, s + 6), a = 1;
- } else {
- continue;
- }
- s = buffer;
- }
- sym_index = find_elf_sym(s1->dynsymtab_section, s);
- // printf("find (%d) %d %s\n", n, sym_index, s);
- if (sym_index
- && ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT
- && 0 == (sym->st_other & ST_PE_IMPORT)
- && 0 == a
- ) err = -1, sym_index = 0;
- } while (0 == sym_index && ++n < 2);
- return n == 2 ? err : sym_index;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int dynarray_assoc(void **pp, int n, int key)
-{
- int i;
- for (i = 0; i < n; ++i, ++pp)
- if (key == **(int **) pp)
- return i;
- return -1;
-}
-
-static DWORD umin(DWORD a, DWORD b)
-{
- return a < b ? a : b;
-}
-
-static DWORD umax(DWORD a, DWORD b)
-{
- return a < b ? b : a;
-}
-
-static DWORD pe_file_align(struct pe_info *pe, DWORD n)
-{
- return (n + (pe->file_align - 1)) & ~(pe->file_align - 1);
-}
-
-static ADDR3264 pe_virtual_align(struct pe_info *pe, ADDR3264 n)
-{
- return (n + (pe->section_align - 1)) & ~(ADDR3264)(pe->section_align - 1);
-}
-
-static void pe_align_section(Section *s, int a)
-{
- int i = s->data_offset & (a-1);
- if (i)
- section_ptr_add(s, a - i);
-}
-
-static void pe_set_datadir(struct pe_header *hdr, int dir, DWORD addr, DWORD size)
-{
- hdr->opthdr.DataDirectory[dir].VirtualAddress = addr;
- hdr->opthdr.DataDirectory[dir].Size = size;
-}
-
-struct pe_file {
- FILE *op;
- DWORD sum;
- unsigned pos;
-};
-
-static int pe_fwrite(void *data, int len, struct pe_file *pf)
-{
- WORD *p = data;
- DWORD sum;
- int ret, i;
- pf->pos += (ret = fwrite(data, 1, len, pf->op));
- sum = pf->sum;
- for (i = len; i > 0; i -= 2) {
- sum += (i >= 2) ? *p++ : *(BYTE*)p;
- sum = (sum + (sum >> 16)) & 0xFFFF;
- }
- pf->sum = sum;
- return len == ret ? 0 : -1;
-}
-
-static void pe_fpad(struct pe_file *pf, DWORD new_pos)
-{
- char buf[256];
- int n, diff = new_pos - pf->pos;
- memset(buf, 0, sizeof buf);
- while (diff > 0) {
- diff -= n = umin(diff, sizeof buf);
- fwrite(buf, n, 1, pf->op);
- }
- pf->pos = new_pos;
-}
-
-/*----------------------------------------------------------------------------*/
-static int pe_write(struct pe_info *pe)
-{
- static const struct pe_header pe_template = {
- {
- /* IMAGE_DOS_HEADER doshdr */
- 0x5A4D, /*WORD e_magic; Magic number */
- 0x0090, /*WORD e_cblp; Bytes on last page of file */
- 0x0003, /*WORD e_cp; Pages in file */
- 0x0000, /*WORD e_crlc; Relocations */
-
- 0x0004, /*WORD e_cparhdr; Size of header in paragraphs */
- 0x0000, /*WORD e_minalloc; Minimum extra paragraphs needed */
- 0xFFFF, /*WORD e_maxalloc; Maximum extra paragraphs needed */
- 0x0000, /*WORD e_ss; Initial (relative) SS value */
-
- 0x00B8, /*WORD e_sp; Initial SP value */
- 0x0000, /*WORD e_csum; Checksum */
- 0x0000, /*WORD e_ip; Initial IP value */
- 0x0000, /*WORD e_cs; Initial (relative) CS value */
- 0x0040, /*WORD e_lfarlc; File address of relocation table */
- 0x0000, /*WORD e_ovno; Overlay number */
- {0,0,0,0}, /*WORD e_res[4]; Reserved words */
- 0x0000, /*WORD e_oemid; OEM identifier (for e_oeminfo) */
- 0x0000, /*WORD e_oeminfo; OEM information; e_oemid specific */
- {0,0,0,0,0,0,0,0,0,0}, /*WORD e_res2[10]; Reserved words */
- 0x00000080 /*DWORD e_lfanew; File address of new exe header */
- },{
- /* BYTE dosstub[0x40] */
- /* 14 code bytes + "This program cannot be run in DOS mode.\r\r\n$" + 6 * 0x00 */
- 0x0e,0x1f,0xba,0x0e,0x00,0xb4,0x09,0xcd,0x21,0xb8,0x01,0x4c,0xcd,0x21,0x54,0x68,
- 0x69,0x73,0x20,0x70,0x72,0x6f,0x67,0x72,0x61,0x6d,0x20,0x63,0x61,0x6e,0x6e,0x6f,
- 0x74,0x20,0x62,0x65,0x20,0x72,0x75,0x6e,0x20,0x69,0x6e,0x20,0x44,0x4f,0x53,0x20,
- 0x6d,0x6f,0x64,0x65,0x2e,0x0d,0x0d,0x0a,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- },
- 0x00004550, /* DWORD nt_sig = IMAGE_NT_SIGNATURE */
- {
- /* IMAGE_FILE_HEADER filehdr */
- IMAGE_FILE_MACHINE, /*WORD Machine; */
- 0x0003, /*WORD NumberOfSections; */
- 0x00000000, /*DWORD TimeDateStamp; */
- 0x00000000, /*DWORD PointerToSymbolTable; */
- 0x00000000, /*DWORD NumberOfSymbols; */
-#if defined(TCC_TARGET_X86_64)
- 0x00F0, /*WORD SizeOfOptionalHeader; */
- 0x022F /*WORD Characteristics; */
-#define CHARACTERISTICS_DLL 0x222E
-#elif defined(TCC_TARGET_I386)
- 0x00E0, /*WORD SizeOfOptionalHeader; */
- 0x030F /*WORD Characteristics; */
-#define CHARACTERISTICS_DLL 0x230E
-#elif defined(TCC_TARGET_ARM)
- 0x00E0, /*WORD SizeOfOptionalHeader; */
- 0x010F, /*WORD Characteristics; */
-#define CHARACTERISTICS_DLL 0x230F
-#endif
-},{
- /* IMAGE_OPTIONAL_HEADER opthdr */
- /* Standard fields. */
-#ifdef TCC_TARGET_X86_64
- 0x020B, /*WORD Magic; */
-#else
- 0x010B, /*WORD Magic; */
-#endif
- 0x06, /*BYTE MajorLinkerVersion; */
- 0x00, /*BYTE MinorLinkerVersion; */
- 0x00000000, /*DWORD SizeOfCode; */
- 0x00000000, /*DWORD SizeOfInitializedData; */
- 0x00000000, /*DWORD SizeOfUninitializedData; */
- 0x00000000, /*DWORD AddressOfEntryPoint; */
- 0x00000000, /*DWORD BaseOfCode; */
-#ifndef TCC_TARGET_X86_64
- 0x00000000, /*DWORD BaseOfData; */
-#endif
- /* NT additional fields. */
-#if defined(TCC_TARGET_ARM)
- 0x00100000, /*DWORD ImageBase; */
-#else
- 0x00400000, /*DWORD ImageBase; */
-#endif
- 0x00001000, /*DWORD SectionAlignment; */
- 0x00000200, /*DWORD FileAlignment; */
- 0x0004, /*WORD MajorOperatingSystemVersion; */
- 0x0000, /*WORD MinorOperatingSystemVersion; */
- 0x0000, /*WORD MajorImageVersion; */
- 0x0000, /*WORD MinorImageVersion; */
- 0x0004, /*WORD MajorSubsystemVersion; */
- 0x0000, /*WORD MinorSubsystemVersion; */
- 0x00000000, /*DWORD Win32VersionValue; */
- 0x00000000, /*DWORD SizeOfImage; */
- 0x00000200, /*DWORD SizeOfHeaders; */
- 0x00000000, /*DWORD CheckSum; */
- 0x0002, /*WORD Subsystem; */
- 0x0000, /*WORD DllCharacteristics; */
- 0x00100000, /*DWORD SizeOfStackReserve; */
- 0x00001000, /*DWORD SizeOfStackCommit; */
- 0x00100000, /*DWORD SizeOfHeapReserve; */
- 0x00001000, /*DWORD SizeOfHeapCommit; */
- 0x00000000, /*DWORD LoaderFlags; */
- 0x00000010, /*DWORD NumberOfRvaAndSizes; */
-
- /* IMAGE_DATA_DIRECTORY DataDirectory[16]; */
- {{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
- {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}}
- }};
-
- struct pe_header pe_header = pe_template;
-
- int i;
- struct pe_file pf = {0};
- DWORD file_offset;
- struct section_info *si;
- IMAGE_SECTION_HEADER *psh;
- TCCState *s1 = pe->s1;
-
- pf.op = fopen(pe->filename, "wb");
- if (NULL == pf.op)
- return tcc_error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
-
- pe->sizeofheaders = pe_file_align(pe,
- sizeof (struct pe_header)
- + pe->sec_count * sizeof (IMAGE_SECTION_HEADER)
- );
-
- file_offset = pe->sizeofheaders;
-
- if (2 == pe->s1->verbose)
- printf("-------------------------------"
- "\n virt file size section" "\n");
- for (i = 0; i < pe->sec_count; ++i) {
- DWORD addr, size;
- const char *sh_name;
-
- si = pe->sec_info[i];
- sh_name = si->name;
- addr = si->sh_addr - pe->imagebase;
- size = si->sh_size;
- psh = &si->ish;
-
- if (2 == pe->s1->verbose)
- printf("%6x %6x %6x %s\n",
- (unsigned)addr, (unsigned)file_offset, (unsigned)size, sh_name);
-
- switch (si->cls) {
- case sec_text:
- if (!pe_header.opthdr.BaseOfCode)
- pe_header.opthdr.BaseOfCode = addr;
- break;
-
- case sec_data:
-#ifndef TCC_TARGET_X86_64
- if (!pe_header.opthdr.BaseOfData)
- pe_header.opthdr.BaseOfData = addr;
-#endif
- break;
-
- case sec_bss:
- break;
-
- case sec_reloc:
- pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size);
- break;
-
- case sec_rsrc:
- pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
- break;
-
- case sec_pdata:
- pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXCEPTION, addr, size);
- break;
- }
-
- if (pe->imp_size) {
- pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IMPORT,
- pe->imp_offs, pe->imp_size);
- pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_IAT,
- pe->iat_offs, pe->iat_size);
- }
- if (pe->exp_size) {
- pe_set_datadir(&pe_header, IMAGE_DIRECTORY_ENTRY_EXPORT,
- pe->exp_offs, pe->exp_size);
- }
-
- memcpy(psh->Name, sh_name, umin(strlen(sh_name), sizeof psh->Name));
-
- psh->Characteristics = si->pe_flags;
- psh->VirtualAddress = addr;
- psh->Misc.VirtualSize = size;
- pe_header.opthdr.SizeOfImage =
- umax(pe_virtual_align(pe, size + addr), pe_header.opthdr.SizeOfImage);
-
- if (si->data_size) {
- psh->PointerToRawData = file_offset;
- file_offset = pe_file_align(pe, file_offset + si->data_size);
- psh->SizeOfRawData = file_offset - psh->PointerToRawData;
- if (si->cls == sec_text)
- pe_header.opthdr.SizeOfCode += psh->SizeOfRawData;
- else
- pe_header.opthdr.SizeOfInitializedData += psh->SizeOfRawData;
- }
- }
-
- //pe_header.filehdr.TimeDateStamp = time(NULL);
- pe_header.filehdr.NumberOfSections = pe->sec_count;
- pe_header.opthdr.AddressOfEntryPoint = pe->start_addr;
- pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
- pe_header.opthdr.ImageBase = pe->imagebase;
- pe_header.opthdr.Subsystem = pe->subsystem;
- if (pe->s1->pe_stack_size)
- pe_header.opthdr.SizeOfStackReserve = pe->s1->pe_stack_size;
- if (PE_DLL == pe->type)
- pe_header.filehdr.Characteristics = CHARACTERISTICS_DLL;
- pe_header.filehdr.Characteristics |= pe->s1->pe_characteristics;
-
- pe_fwrite(&pe_header, sizeof pe_header, &pf);
- for (i = 0; i < pe->sec_count; ++i)
- pe_fwrite(&pe->sec_info[i]->ish, sizeof(IMAGE_SECTION_HEADER), &pf);
-
- file_offset = pe->sizeofheaders;
- for (i = 0; i < pe->sec_count; ++i) {
- Section *s;
- si = pe->sec_info[i];
- if (!si->data_size)
- continue;
- for (s = si->sec; s; s = s->prev) {
- pe_fpad(&pf, file_offset);
- pe_fwrite(s->data, s->data_offset, &pf);
- if (s->prev)
- file_offset += s->prev->sh_addr - s->sh_addr;
- }
- file_offset = si->ish.PointerToRawData + si->ish.SizeOfRawData;
- pe_fpad(&pf, file_offset);
- }
-
- pf.sum += file_offset;
- fseek(pf.op, offsetof(struct pe_header, opthdr.CheckSum), SEEK_SET);
- pe_fwrite(&pf.sum, sizeof (DWORD), &pf);
-
- fclose (pf.op);
-#ifndef _WIN32
- chmod(pe->filename, 0777);
-#endif
-
- if (2 == pe->s1->verbose)
- printf("-------------------------------\n");
- if (pe->s1->verbose)
- printf("<- %s (%u bytes)\n", pe->filename, (unsigned)file_offset);
-
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static struct import_symbol *pe_add_import(struct pe_info *pe, int sym_index)
-{
- int i;
- int dll_index;
- struct pe_import_info *p;
- struct import_symbol *s;
- ElfW(Sym) *isym;
-
- isym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
- dll_index = isym->st_size;
-
- i = dynarray_assoc ((void**)pe->imp_info, pe->imp_count, dll_index);
- if (-1 != i) {
- p = pe->imp_info[i];
- goto found_dll;
- }
- p = tcc_mallocz(sizeof *p);
- p->dll_index = dll_index;
- dynarray_add(&pe->imp_info, &pe->imp_count, p);
-
-found_dll:
- i = dynarray_assoc ((void**)p->symbols, p->sym_count, sym_index);
- if (-1 != i)
- return p->symbols[i];
-
- s = tcc_mallocz(sizeof *s);
- dynarray_add(&p->symbols, &p->sym_count, s);
- s->sym_index = sym_index;
- return s;
-}
-
-void pe_free_imports(struct pe_info *pe)
-{
- int i;
- for (i = 0; i < pe->imp_count; ++i) {
- struct pe_import_info *p = pe->imp_info[i];
- dynarray_reset(&p->symbols, &p->sym_count);
- }
- dynarray_reset(&pe->imp_info, &pe->imp_count);
-}
-
-/*----------------------------------------------------------------------------*/
-static void pe_build_imports(struct pe_info *pe)
-{
- int thk_ptr, ent_ptr, dll_ptr, sym_cnt, i;
- DWORD rva_base = pe->thunk->sh_addr - pe->imagebase;
- int ndlls = pe->imp_count;
- TCCState *s1 = pe->s1;
-
- for (sym_cnt = i = 0; i < ndlls; ++i)
- sym_cnt += pe->imp_info[i]->sym_count;
-
- if (0 == sym_cnt)
- return;
-
- pe_align_section(pe->thunk, 16);
- pe->imp_size = (ndlls + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
- pe->iat_size = (sym_cnt + ndlls) * sizeof(ADDR3264);
- dll_ptr = pe->thunk->data_offset;
- thk_ptr = dll_ptr + pe->imp_size;
- ent_ptr = thk_ptr + pe->iat_size;
- pe->imp_offs = dll_ptr + rva_base;
- pe->iat_offs = thk_ptr + rva_base;
- section_ptr_add(pe->thunk, pe->imp_size + 2*pe->iat_size);
-
- for (i = 0; i < pe->imp_count; ++i) {
- IMAGE_IMPORT_DESCRIPTOR *hdr;
- int k, n, dllindex;
- ADDR3264 v;
- struct pe_import_info *p = pe->imp_info[i];
- const char *name;
- DLLReference *dllref;
-
- dllindex = p->dll_index;
- if (dllindex)
- name = tcc_basename((dllref = pe->s1->loaded_dlls[dllindex-1])->name);
- else
- name = "", dllref = NULL;
-
- /* put the dll name into the import header */
- v = put_elf_str(pe->thunk, name);
- hdr = (IMAGE_IMPORT_DESCRIPTOR*)(pe->thunk->data + dll_ptr);
- hdr->FirstThunk = thk_ptr + rva_base;
- hdr->OriginalFirstThunk = ent_ptr + rva_base;
- hdr->Name = v + rva_base;
-
- for (k = 0, n = p->sym_count; k <= n; ++k) {
- if (k < n) {
- int iat_index = p->symbols[k]->iat_index;
- int sym_index = p->symbols[k]->sym_index;
- ElfW(Sym) *imp_sym = (ElfW(Sym) *)pe->s1->dynsymtab_section->data + sym_index;
- ElfW(Sym) *org_sym = (ElfW(Sym) *)symtab_section->data + iat_index;
- const char *name = (char*)pe->s1->dynsymtab_section->link->data + imp_sym->st_name;
- int ordinal;
-
- org_sym->st_value = thk_ptr;
- org_sym->st_shndx = pe->thunk->sh_num;
-
- if (dllref)
- v = 0, ordinal = imp_sym->st_value; /* ordinal from pe_load_def */
- else
- ordinal = 0, v = imp_sym->st_value; /* address from tcc_add_symbol() */
-
-#ifdef TCC_IS_NATIVE
- if (pe->type == PE_RUN) {
- if (dllref) {
- if ( !dllref->handle )
- dllref->handle = LoadLibrary(dllref->name);
- v = (ADDR3264)GetProcAddress(dllref->handle, ordinal?(char*)0+ordinal:name);
- }
- if (!v)
- tcc_error_noabort("could not resolve symbol '%s'", name);
- } else
-#endif
- if (ordinal) {
- v = ordinal | (ADDR3264)1 << (sizeof(ADDR3264)*8 - 1);
- } else {
- v = pe->thunk->data_offset + rva_base;
- section_ptr_add(pe->thunk, sizeof(WORD)); /* hint, not used */
- put_elf_str(pe->thunk, name);
- }
-
- } else {
- v = 0; /* last entry is zero */
- }
-
- *(ADDR3264*)(pe->thunk->data+thk_ptr) =
- *(ADDR3264*)(pe->thunk->data+ent_ptr) = v;
- thk_ptr += sizeof (ADDR3264);
- ent_ptr += sizeof (ADDR3264);
- }
- dll_ptr += sizeof(IMAGE_IMPORT_DESCRIPTOR);
- }
-}
-
-/* ------------------------------------------------------------- */
-
-struct pe_sort_sym
-{
- int index;
- const char *name;
-};
-
-static int sym_cmp(const void *va, const void *vb)
-{
- const char *ca = (*(struct pe_sort_sym**)va)->name;
- const char *cb = (*(struct pe_sort_sym**)vb)->name;
- return strcmp(ca, cb);
-}
-
-static void pe_build_exports(struct pe_info *pe)
-{
- ElfW(Sym) *sym;
- int sym_index, sym_end;
- DWORD rva_base, base_o, func_o, name_o, ord_o, str_o;
- IMAGE_EXPORT_DIRECTORY *hdr;
- int sym_count, ord;
- struct pe_sort_sym **sorted, *p;
- TCCState *s1 = pe->s1;
-
- FILE *op;
- char buf[260];
- const char *dllname;
- const char *name;
-
- rva_base = pe->thunk->sh_addr - pe->imagebase;
- sym_count = 0, sorted = NULL, op = NULL;
-
- sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
- for (sym_index = 1; sym_index < sym_end; ++sym_index) {
- sym = (ElfW(Sym)*)symtab_section->data + sym_index;
- name = pe_export_name(pe->s1, sym);
- if (sym->st_other & ST_PE_EXPORT) {
- p = tcc_malloc(sizeof *p);
- p->index = sym_index;
- p->name = name;
- dynarray_add(&sorted, &sym_count, p);
- }
-#if 0
- if (sym->st_other & ST_PE_EXPORT)
- printf("export: %s\n", name);
- if (sym->st_other & ST_PE_STDCALL)
- printf("stdcall: %s\n", name);
-#endif
- }
-
- if (0 == sym_count)
- return;
-
- qsort (sorted, sym_count, sizeof *sorted, sym_cmp);
-
- pe_align_section(pe->thunk, 16);
- dllname = tcc_basename(pe->filename);
-
- base_o = pe->thunk->data_offset;
- func_o = base_o + sizeof(IMAGE_EXPORT_DIRECTORY);
- name_o = func_o + sym_count * sizeof (DWORD);
- ord_o = name_o + sym_count * sizeof (DWORD);
- str_o = ord_o + sym_count * sizeof(WORD);
-
- hdr = section_ptr_add(pe->thunk, str_o - base_o);
- hdr->Characteristics = 0;
- hdr->Base = 1;
- hdr->NumberOfFunctions = sym_count;
- hdr->NumberOfNames = sym_count;
- hdr->AddressOfFunctions = func_o + rva_base;
- hdr->AddressOfNames = name_o + rva_base;
- hdr->AddressOfNameOrdinals = ord_o + rva_base;
- hdr->Name = str_o + rva_base;
- put_elf_str(pe->thunk, dllname);
-
-#if 1
- /* automatically write exports to <output-filename>.def */
- pstrcpy(buf, sizeof buf, pe->filename);
- strcpy(tcc_fileextension(buf), ".def");
- op = fopen(buf, "wb");
- if (NULL == op) {
- tcc_error_noabort("could not create '%s': %s", buf, strerror(errno));
- } else {
- fprintf(op, "LIBRARY %s\n\nEXPORTS\n", dllname);
- if (pe->s1->verbose)
- printf("<- %s (%d symbol%s)\n", buf, sym_count, &"s"[sym_count < 2]);
- }
-#endif
-
- for (ord = 0; ord < sym_count; ++ord)
- {
- p = sorted[ord], sym_index = p->index, name = p->name;
- /* insert actual address later in relocate_sections() */
- put_elf_reloc(symtab_section, pe->thunk,
- func_o, R_XXX_RELATIVE, sym_index);
- *(DWORD*)(pe->thunk->data + name_o)
- = pe->thunk->data_offset + rva_base;
- *(WORD*)(pe->thunk->data + ord_o)
- = ord;
- put_elf_str(pe->thunk, name);
- func_o += sizeof (DWORD);
- name_o += sizeof (DWORD);
- ord_o += sizeof (WORD);
- if (op)
- fprintf(op, "%s\n", name);
- }
-
- pe->exp_offs = base_o + rva_base;
- pe->exp_size = pe->thunk->data_offset - base_o;
- dynarray_reset(&sorted, &sym_count);
- if (op)
- fclose(op);
-}
-
-/* ------------------------------------------------------------- */
-static void pe_build_reloc (struct pe_info *pe)
-{
- DWORD offset, block_ptr, sh_addr, addr;
- int count, i;
- ElfW_Rel *rel, *rel_end;
- Section *s = NULL, *sr;
- struct pe_reloc_header *hdr;
-
- sh_addr = offset = block_ptr = count = i = 0;
- rel = rel_end = NULL;
-
- for(;;) {
- if (rel < rel_end) {
- int type = ELFW(R_TYPE)(rel->r_info);
- addr = rel->r_offset + sh_addr;
- ++ rel;
- if (type != REL_TYPE_DIRECT)
- continue;
- if (count == 0) { /* new block */
- block_ptr = pe->reloc->data_offset;
- section_ptr_add(pe->reloc, sizeof(struct pe_reloc_header));
- offset = addr & 0xFFFFFFFF<<12;
- }
- if ((addr -= offset) < (1<<12)) { /* one block spans 4k addresses */
- WORD *wp = section_ptr_add(pe->reloc, sizeof (WORD));
- *wp = addr | PE_IMAGE_REL<<12;
- ++count;
- continue;
- }
- -- rel;
-
- } else if (s) {
- sr = s->reloc;
- if (sr) {
- rel = (ElfW_Rel *)sr->data;
- rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
- sh_addr = s->sh_addr;
- }
- s = s->prev;
- continue;
-
- } else if (i < pe->sec_count) {
- s = pe->sec_info[i]->sec, ++i;
- continue;
-
- } else if (!count)
- break;
-
- /* fill the last block and ready for a new one */
- if (count & 1) /* align for DWORDS */
- section_ptr_add(pe->reloc, sizeof(WORD)), ++count;
- hdr = (struct pe_reloc_header *)(pe->reloc->data + block_ptr);
- hdr -> offset = offset - pe->imagebase;
- hdr -> size = count * sizeof(WORD) + sizeof(struct pe_reloc_header);
- count = 0;
- }
-}
-
-/* ------------------------------------------------------------- */
-static int pe_section_class(Section *s)
-{
- int type, flags;
- const char *name;
- type = s->sh_type;
- flags = s->sh_flags;
- name = s->name;
- if (0 == memcmp(name, ".stab", 5)) {
- if (0 == s->s1->do_debug)
- return sec_last;
- return name[5] ? sec_stabstr : sec_stab;
- }
- if (flags & SHF_ALLOC) {
- if (type == SHT_PROGBITS
- || type == SHT_INIT_ARRAY
- || type == SHT_FINI_ARRAY) {
- if (flags & SHF_EXECINSTR)
- return sec_text;
- if (flags & SHF_WRITE)
- return sec_data;
- if (0 == strcmp(name, ".rsrc"))
- return sec_rsrc;
- if (0 == strcmp(name, ".iedat"))
- return sec_idata;
- if (0 == strcmp(name, ".pdata"))
- return sec_pdata;
- return sec_rdata;
- } else if (type == SHT_NOBITS) {
- return sec_bss;
- }
- return sec_other;
- } else {
- if (0 == strcmp(name, ".reloc"))
- return sec_reloc;
- }
- return sec_last;
-}
-
-static int pe_assign_addresses (struct pe_info *pe)
-{
- int i, k, n, c, nbs;
- ADDR3264 addr;
- int *sec_order, *sec_cls;
- struct section_info *si;
- Section *s;
- TCCState *s1 = pe->s1;
-
- if (PE_DLL == pe->type)
- pe->reloc = new_section(pe->s1, ".reloc", SHT_PROGBITS, 0);
- //pe->thunk = new_section(pe->s1, ".iedat", SHT_PROGBITS, SHF_ALLOC);
-
- nbs = s1->nb_sections;
- sec_order = tcc_mallocz(2 * sizeof (int) * nbs);
- sec_cls = sec_order + nbs;
- for (i = 1; i < nbs; ++i) {
- s = s1->sections[i];
- k = pe_section_class(s);
- for (n = i; n > 1 && k < (c = sec_cls[n - 1]); --n)
- sec_cls[n] = c, sec_order[n] = sec_order[n - 1];
- sec_cls[n] = k, sec_order[n] = i;
- }
- si = NULL;
- addr = pe->imagebase + 1;
-
- for (i = 1; (c = sec_cls[i]) < sec_last; ++i) {
- s = s1->sections[sec_order[i]];
-
- if (PE_MERGE_DATA && c == sec_bss)
- c = sec_data;
-
- if (si && c == si->cls) {
- /* merge with previous section */
- s->sh_addr = addr = ((addr - 1) | (16 - 1)) + 1;
- } else {
- si = NULL;
- s->sh_addr = addr = pe_virtual_align(pe, addr);
- }
-
- if (NULL == pe->thunk
- && c == (data_section == rodata_section ? sec_data : sec_rdata))
- pe->thunk = s;
-
- if (s == pe->thunk) {
- pe_build_imports(pe);
- pe_build_exports(pe);
- }
- if (s == pe->reloc)
- pe_build_reloc (pe);
-
- if (0 == s->data_offset)
- continue;
-
- if (si)
- goto add_section;
-
- si = tcc_mallocz(sizeof *si);
- dynarray_add(&pe->sec_info, &pe->sec_count, si);
-
- strcpy(si->name, s->name);
- si->cls = c;
- si->sh_addr = addr;
-
- si->pe_flags = IMAGE_SCN_MEM_READ;
- if (s->sh_flags & SHF_EXECINSTR)
- si->pe_flags |= IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE;
- else if (s->sh_type == SHT_NOBITS)
- si->pe_flags |= IMAGE_SCN_CNT_UNINITIALIZED_DATA;
- else
- si->pe_flags |= IMAGE_SCN_CNT_INITIALIZED_DATA;
- if (s->sh_flags & SHF_WRITE)
- si->pe_flags |= IMAGE_SCN_MEM_WRITE;
- if (0 == (s->sh_flags & SHF_ALLOC))
- si->pe_flags |= IMAGE_SCN_MEM_DISCARDABLE;
-
-add_section:
- addr += s->data_offset;
- si->sh_size = addr - si->sh_addr;
- if (s->sh_type != SHT_NOBITS) {
- Section **ps = &si->sec;
- while (*ps)
- ps = &(*ps)->prev;
- *ps = s, s->prev = NULL;
- si->data_size = si->sh_size;
- }
- //printf("%08x %05x %08x %s\n", si->sh_addr, si->sh_size, si->pe_flags, s->name);
- }
-#if 0
- for (i = 1; i < nbs; ++i) {
- Section *s = s1->sections[sec_order[i]];
- int type = s->sh_type;
- int flags = s->sh_flags;
- printf("section %-16s %-10s %p %04x %s,%s,%s\n",
- s->name,
- type == SHT_PROGBITS ? "progbits" :
- type == SHT_INIT_ARRAY ? "initarr" :
- type == SHT_FINI_ARRAY ? "finiarr" :
- type == SHT_NOBITS ? "nobits" :
- type == SHT_SYMTAB ? "symtab" :
- type == SHT_STRTAB ? "strtab" :
- type == SHT_RELX ? "rel" : "???",
- s->sh_addr,
- (unsigned)s->data_offset,
- flags & SHF_ALLOC ? "alloc" : "",
- flags & SHF_WRITE ? "write" : "",
- flags & SHF_EXECINSTR ? "exec" : ""
- );
- fflush(stdout);
- }
- s1->verbose = 2;
-#endif
- tcc_free(sec_order);
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-
-static int pe_isafunc(TCCState *s1, int sym_index)
-{
- Section *sr = text_section->reloc;
- ElfW_Rel *rel, *rel_end;
- ElfW(Addr)info = ELFW(R_INFO)(sym_index, R_XXX_FUNCCALL);
-#ifdef R_XXX_FUNCCALL2
- ElfW(Addr)info2 = ELFW(R_INFO)(sym_index, R_XXX_FUNCCALL2);
-#endif
- if (!sr)
- return 0;
- rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
- for (rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
- if (rel->r_info == info)
- return 1;
-#ifdef R_XXX_FUNCCALL2
- if (rel->r_info == info2)
- return 1;
-#endif
- }
- return 0;
-}
-
-/*----------------------------------------------------------------------------*/
-static int pe_check_symbols(struct pe_info *pe)
-{
- ElfW(Sym) *sym;
- int sym_index, sym_end;
- int ret = 0;
- TCCState *s1 = pe->s1;
-
- pe_align_section(text_section, 8);
-
- sym_end = symtab_section->data_offset / sizeof(ElfW(Sym));
- for (sym_index = 1; sym_index < sym_end; ++sym_index) {
-
- sym = (ElfW(Sym) *)symtab_section->data + sym_index;
- if (sym->st_shndx == SHN_UNDEF) {
-
- const char *name = (char*)symtab_section->link->data + sym->st_name;
- unsigned type = ELFW(ST_TYPE)(sym->st_info);
- int imp_sym = pe_find_import(pe->s1, sym);
- struct import_symbol *is;
-
- if (imp_sym <= 0)
- goto not_found;
-
- if (type == STT_NOTYPE) {
- /* symbols from assembler have no type, find out which */
- if (pe_isafunc(s1, sym_index))
- type = STT_FUNC;
- else
- type = STT_OBJECT;
- }
-
- is = pe_add_import(pe, imp_sym);
-
- if (type == STT_FUNC) {
- unsigned offset = is->thk_offset;
- if (offset) {
- /* got aliased symbol, like stricmp and _stricmp */
- } else {
- char buffer[100];
- unsigned char *p;
-
- /* add a helper symbol, will be patched later in
- pe_build_imports */
- sprintf(buffer, "IAT.%s", name);
- is->iat_index = put_elf_sym(
- symtab_section, 0, sizeof(DWORD),
- ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
- 0, SHN_UNDEF, buffer);
-
- offset = text_section->data_offset;
- is->thk_offset = offset;
-
- /* add the 'jmp IAT[x]' instruction */
-#ifdef TCC_TARGET_ARM
- p = section_ptr_add(text_section, 8+4); // room for code and address
- write32le(p + 0, 0xE59FC000); // arm code ldr ip, [pc] ; PC+8+0 = 0001xxxx
- write32le(p + 4, 0xE59CF000); // arm code ldr pc, [ip]
- put_elf_reloc(symtab_section, text_section,
- offset + 8, R_XXX_THUNKFIX, is->iat_index); // offset to IAT position
-#else
- p = section_ptr_add(text_section, 8);
- write16le(p, 0x25FF);
-#ifdef TCC_TARGET_X86_64
- write32le(p + 2, (DWORD)-4);
-#endif
- put_elf_reloc(symtab_section, text_section,
- offset + 2, R_XXX_THUNKFIX, is->iat_index);
-#endif
- }
- /* tcc_realloc might have altered sym's address */
- sym = (ElfW(Sym) *)symtab_section->data + sym_index;
-
- /* patch the original symbol */
- sym->st_value = offset;
- sym->st_shndx = text_section->sh_num;
- sym->st_other &= ~ST_PE_EXPORT; /* do not export */
- continue;
- }
-
- if (type == STT_OBJECT) { /* data, ptr to that should be */
- if (0 == is->iat_index) {
- /* original symbol will be patched later in pe_build_imports */
- is->iat_index = sym_index;
- continue;
- }
- }
-
- not_found:
- if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
- /* STB_WEAK undefined symbols are accepted */
- continue;
- ret = tcc_error_noabort("undefined symbol '%s'%s", name,
- imp_sym < 0 ? ", missing __declspec(dllimport)?":"");
-
- } else if (pe->s1->rdynamic
- && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
- /* if -rdynamic option, then export all non local symbols */
- sym->st_other |= ST_PE_EXPORT;
- }
- }
- return ret;
-}
-
-/*----------------------------------------------------------------------------*/
-#if PE_PRINT_SECTIONS
-static void pe_print_section(FILE * f, Section * s)
-{
- /* just if you're curious */
- BYTE *p, *e, b;
- int i, n, l, m;
- p = s->data;
- e = s->data + s->data_offset;
- l = e - p;
-
- fprintf(f, "section \"%s\"", s->name);
- if (s->link)
- fprintf(f, "\nlink \"%s\"", s->link->name);
- if (s->reloc)
- fprintf(f, "\nreloc \"%s\"", s->reloc->name);
- fprintf(f, "\nv_addr %08X", (unsigned)s->sh_addr);
- fprintf(f, "\ncontents %08X", (unsigned)l);
- fprintf(f, "\n\n");
-
- if (s->sh_type == SHT_NOBITS)
- return;
-
- if (0 == l)
- return;
-
- if (s->sh_type == SHT_SYMTAB)
- m = sizeof(ElfW(Sym));
- else if (s->sh_type == SHT_RELX)
- m = sizeof(ElfW_Rel);
- else
- m = 16;
-
- fprintf(f, "%-8s", "offset");
- for (i = 0; i < m; ++i)
- fprintf(f, " %02x", i);
- n = 56;
-
- if (s->sh_type == SHT_SYMTAB || s->sh_type == SHT_RELX) {
- const char *fields1[] = {
- "name",
- "value",
- "size",
- "bind",
- "type",
- "other",
- "shndx",
- NULL
- };
-
- const char *fields2[] = {
- "offs",
- "type",
- "symb",
- NULL
- };
-
- const char **p;
-
- if (s->sh_type == SHT_SYMTAB)
- p = fields1, n = 106;
- else
- p = fields2, n = 58;
-
- for (i = 0; p[i]; ++i)
- fprintf(f, "%6s", p[i]);
- fprintf(f, " symbol");
- }
-
- fprintf(f, "\n");
- for (i = 0; i < n; ++i)
- fprintf(f, "-");
- fprintf(f, "\n");
-
- for (i = 0; i < l;)
- {
- fprintf(f, "%08X", i);
- for (n = 0; n < m; ++n) {
- if (n + i < l)
- fprintf(f, " %02X", p[i + n]);
- else
- fprintf(f, " ");
- }
-
- if (s->sh_type == SHT_SYMTAB) {
- ElfW(Sym) *sym = (ElfW(Sym) *) (p + i);
- const char *name = s->link->data + sym->st_name;
- fprintf(f, " %04X %04X %04X %02X %02X %02X %04X \"%s\"",
- (unsigned)sym->st_name,
- (unsigned)sym->st_value,
- (unsigned)sym->st_size,
- (unsigned)ELFW(ST_BIND)(sym->st_info),
- (unsigned)ELFW(ST_TYPE)(sym->st_info),
- (unsigned)sym->st_other,
- (unsigned)sym->st_shndx,
- name);
-
- } else if (s->sh_type == SHT_RELX) {
- ElfW_Rel *rel = (ElfW_Rel *) (p + i);
- ElfW(Sym) *sym =
- (ElfW(Sym) *) s->link->data + ELFW(R_SYM)(rel->r_info);
- const char *name = s->link->link->data + sym->st_name;
- fprintf(f, " %04X %02X %04X \"%s\"",
- (unsigned)rel->r_offset,
- (unsigned)ELFW(R_TYPE)(rel->r_info),
- (unsigned)ELFW(R_SYM)(rel->r_info),
- name);
- } else {
- fprintf(f, " ");
- for (n = 0; n < m; ++n) {
- if (n + i < l) {
- b = p[i + n];
- if (b < 32 || b >= 127)
- b = '.';
- fprintf(f, "%c", b);
- }
- }
- }
- i += m;
- fprintf(f, "\n");
- }
- fprintf(f, "\n\n");
-}
-
-static void pe_print_sections(TCCState *s1, const char *fname)
-{
- Section *s;
- FILE *f;
- int i;
- f = fopen(fname, "w");
- for (i = 1; i < s1->nb_sections; ++i) {
- s = s1->sections[i];
- pe_print_section(f, s);
- }
- pe_print_section(f, s1->dynsymtab_section);
- fclose(f);
-}
-#endif
-
-/* ------------------------------------------------------------- */
-/* helper function for load/store to insert one more indirection */
-
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
-ST_FUNC SValue *pe_getimport(SValue *sv, SValue *v2)
-{
- int r2;
- if ((sv->r & (VT_VALMASK|VT_SYM)) != (VT_CONST|VT_SYM) || (sv->r2 != VT_CONST))
- return sv;
- if (!sv->sym->a.dllimport)
- return sv;
- // printf("import %04x %04x %04x %s\n", sv->type.t, sv->sym->type.t, sv->r, get_tok_str(sv->sym->v, NULL));
- memset(v2, 0, sizeof *v2);
- v2->type.t = VT_PTR;
- v2->r = VT_CONST | VT_SYM | VT_LVAL;
- v2->sym = sv->sym;
-
- r2 = get_reg(RC_INT);
- load(r2, v2);
- v2->r = r2;
- if ((uint32_t)sv->c.i) {
- vpushv(v2);
- vpushi(sv->c.i);
- gen_opi('+');
- *v2 = *vtop--;
- }
- v2->type.t = sv->type.t;
- v2->r |= sv->r & VT_LVAL;
- return v2;
-}
-#endif
-
-ST_FUNC int pe_putimport(TCCState *s1, int dllindex, const char *name, addr_t value)
-{
- return set_elf_sym(
- s1->dynsymtab_section,
- value,
- dllindex, /* st_size */
- ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE),
- 0,
- value ? SHN_ABS : SHN_UNDEF,
- name
- );
-}
-
-static int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
-{
- lseek(fd, offset, SEEK_SET);
- return len == read(fd, buffer, len);
-}
-
-/* ------------------------------------------------------------- */
-
-static int get_dllexports(int fd, char **pp)
-{
- int l, i, n, n0, ret;
- char *p;
-
- IMAGE_SECTION_HEADER ish;
- IMAGE_EXPORT_DIRECTORY ied;
- IMAGE_DOS_HEADER dh;
- IMAGE_FILE_HEADER ih;
- DWORD sig, ref, addr, ptr, namep;
-
- int pef_hdroffset, opt_hdroffset, sec_hdroffset;
-
- n = n0 = 0;
- p = NULL;
- ret = 1;
- if (!read_mem(fd, 0, &dh, sizeof dh))
- goto the_end;
- if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
- goto the_end;
- if (sig != 0x00004550)
- goto the_end;
- pef_hdroffset = dh.e_lfanew + sizeof sig;
- if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
- goto the_end;
- opt_hdroffset = pef_hdroffset + sizeof ih;
- if (ih.Machine == 0x014C) {
- IMAGE_OPTIONAL_HEADER32 oh;
- sec_hdroffset = opt_hdroffset + sizeof oh;
- if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
- goto the_end;
- if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
- goto the_end_0;
- addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- } else if (ih.Machine == 0x8664) {
- IMAGE_OPTIONAL_HEADER64 oh;
- sec_hdroffset = opt_hdroffset + sizeof oh;
- if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
- goto the_end;
- if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
- goto the_end_0;
- addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
- } else
- goto the_end;
-
- //printf("addr: %08x\n", addr);
- for (i = 0; i < ih.NumberOfSections; ++i) {
- if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
- goto the_end;
- //printf("vaddr: %08x\n", ish.VirtualAddress);
- if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
- goto found;
- }
- goto the_end_0;
-
-found:
- ref = ish.VirtualAddress - ish.PointerToRawData;
- if (!read_mem(fd, addr - ref, &ied, sizeof ied))
- goto the_end;
-
- namep = ied.AddressOfNames - ref;
- for (i = 0; i < ied.NumberOfNames; ++i) {
- if (!read_mem(fd, namep, &ptr, sizeof ptr))
- goto the_end;
- namep += sizeof ptr;
- for (l = 0;;) {
- if (n+1 >= n0)
- p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
- if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
- tcc_free(p), p = NULL;
- goto the_end;
- }
- if (p[n++] == 0)
- break;
- }
- }
- if (p)
- p[n] = 0;
-the_end_0:
- ret = 0;
-the_end:
- *pp = p;
- return ret;
-}
-
-/* -------------------------------------------------------------
- * This is for compiled windows resources in 'coff' format
- * as generated by 'windres.exe -O coff ...'.
- */
-
-static int pe_load_res(TCCState *s1, int fd)
-{
- struct pe_rsrc_header hdr;
- Section *rsrc_section;
- int i, ret = -1, sym_index;
- BYTE *ptr;
- unsigned offs;
-
- if (!read_mem(fd, 0, &hdr, sizeof hdr))
- goto quit;
-
- if (hdr.filehdr.Machine != IMAGE_FILE_MACHINE
- || hdr.filehdr.NumberOfSections != 1
- || strcmp((char*)hdr.sectionhdr.Name, ".rsrc") != 0)
- goto quit;
-
- rsrc_section = new_section(s1, ".rsrc", SHT_PROGBITS, SHF_ALLOC);
- ptr = section_ptr_add(rsrc_section, hdr.sectionhdr.SizeOfRawData);
- offs = hdr.sectionhdr.PointerToRawData;
- if (!read_mem(fd, offs, ptr, hdr.sectionhdr.SizeOfRawData))
- goto quit;
- offs = hdr.sectionhdr.PointerToRelocations;
- sym_index = put_elf_sym(symtab_section, 0, 0, 0, 0, rsrc_section->sh_num, ".rsrc");
- for (i = 0; i < hdr.sectionhdr.NumberOfRelocations; ++i) {
- struct pe_rsrc_reloc rel;
- if (!read_mem(fd, offs, &rel, sizeof rel))
- goto quit;
- // printf("rsrc_reloc: %x %x %x\n", rel.offset, rel.size, rel.type);
- if (rel.type != RSRC_RELTYPE)
- goto quit;
- put_elf_reloc(symtab_section, rsrc_section,
- rel.offset, R_XXX_RELATIVE, sym_index);
- offs += sizeof rel;
- }
- ret = 0;
-quit:
- return ret;
-}
-
-/* ------------------------------------------------------------- */
-
-static char *trimfront(char *p)
-{
- while ((unsigned char)*p <= ' ' && *p && *p != '\n')
- ++p;
- return p;
-}
-
-/*
-static char *trimback(char *a, char *e)
-{
- while (e > a && (unsigned char)e[-1] <= ' ')
- --e;
- *e = 0;;
- return a;
-}*/
-
-static char *get_token(char **s, char *f)
-{
- char *p = *s, *e;
- p = e = trimfront(p);
- while ((unsigned char)*e > ' ')
- ++e;
- *s = trimfront(e);
- *f = **s; *e = 0;
- return p;
-}
-
-static int pe_load_def(TCCState *s1, int fd)
-{
- int state = 0, ret = -1, dllindex = 0, ord;
- char dllname[80], *buf, *line, *p, *x, next;
-
- buf = tcc_load_text(fd);
- for (line = buf;; ++line) {
- p = get_token(&line, &next);
- if (!(*p && *p != ';'))
- goto skip;
- switch (state) {
- case 0:
- if (0 != stricmp(p, "LIBRARY") || next == '\n')
- goto quit;
- pstrcpy(dllname, sizeof dllname, get_token(&line, &next));
- ++state;
- break;
- case 1:
- if (0 != stricmp(p, "EXPORTS"))
- goto quit;
- ++state;
- break;
- case 2:
- dllindex = tcc_add_dllref(s1, dllname, 0)->index;
- ++state;
- /* fall through */
- default:
- /* get ordinal and will store in sym->st_value */
- ord = 0;
- if (next == '@') {
- x = get_token(&line, &next);
- ord = (int)strtol(x + 1, &x, 10);
- }
- //printf("token %s ; %s : %d\n", dllname, p, ord);
- pe_putimport(s1, dllindex, p, ord);
- break;
- }
-skip:
- while ((unsigned char)next > ' ')
- get_token(&line, &next);
- if (next != '\n')
- break;
- }
- ret = 0;
-quit:
- tcc_free(buf);
- return ret;
-}
-
-/* ------------------------------------------------------------- */
-
-static int pe_load_dll(TCCState *s1, int fd, const char *filename)
-{
- char *p, *q;
- int index, ret;
-
- ret = get_dllexports(fd, &p);
- if (ret) {
- return -1;
- } else if (p) {
- index = tcc_add_dllref(s1, filename, 0)->index;
- for (q = p; *q; q += 1 + strlen(q))
- pe_putimport(s1, index, q, 0);
- tcc_free(p);
- }
- return 0;
-}
-
-ST_FUNC int pe_load_file(struct TCCState *s1, int fd, const char *filename)
-{
- int ret = -1;
- char buf[10];
- if (0 == strcmp(tcc_fileextension(filename), ".def"))
- ret = pe_load_def(s1, fd);
- else if (pe_load_res(s1, fd) == 0)
- ret = 0;
- else if (read_mem(fd, 0, buf, 4) && 0 == memcmp(buf, "MZ", 2))
- ret = pe_load_dll(s1, fd, filename);
- return ret;
-}
-
-PUB_FUNC int tcc_get_dllexports(const char *filename, char **pp)
-{
- int ret, fd = open(filename, O_RDONLY | O_BINARY);
- if (fd < 0)
- return -1;
- ret = get_dllexports(fd, pp);
- close(fd);
- return ret;
-}
-
-/* ------------------------------------------------------------- */
-#ifdef TCC_TARGET_X86_64
-static unsigned pe_add_uwwind_info(TCCState *s1)
-{
- if (NULL == s1->uw_pdata) {
- s1->uw_pdata = find_section(s1, ".pdata");
- s1->uw_pdata->sh_addralign = 4;
- }
- if (0 == s1->uw_sym)
- s1->uw_sym = put_elf_sym(symtab_section, 0, 0, 0, 0, text_section->sh_num, ".uw_base");
- if (0 == s1->uw_offs) {
- /* As our functions all have the same stackframe, we use one entry for all */
- static const unsigned char uw_info[] = {
- 0x01, // UBYTE: 3 Version , UBYTE: 5 Flags
- 0x04, // UBYTE Size of prolog
- 0x02, // UBYTE Count of unwind codes
- 0x05, // UBYTE: 4 Frame Register (rbp), UBYTE: 4 Frame Register offset (scaled)
- // USHORT * n Unwind codes array
- // 0x0b, 0x01, 0xff, 0xff, // stack size
- 0x04, 0x03, // set frame ptr (mov rsp -> rbp)
- 0x01, 0x50 // push reg (rbp)
- };
-
- Section *s = text_section;
- unsigned char *p;
-
- section_ptr_add(s, -s->data_offset & 3); /* align */
- s1->uw_offs = s->data_offset;
- p = section_ptr_add(s, sizeof uw_info);
- memcpy(p, uw_info, sizeof uw_info);
- }
-
- return s1->uw_offs;
-}
-
-ST_FUNC void pe_add_unwind_data(unsigned start, unsigned end, unsigned stack)
-{
- TCCState *s1 = tcc_state;
- Section *pd;
- unsigned o, n, d;
- struct /* _RUNTIME_FUNCTION */ {
- DWORD BeginAddress;
- DWORD EndAddress;
- DWORD UnwindData;
- } *p;
-
- d = pe_add_uwwind_info(s1);
- pd = s1->uw_pdata;
- o = pd->data_offset;
- p = section_ptr_add(pd, sizeof *p);
-
- /* record this function */
- p->BeginAddress = start;
- p->EndAddress = end;
- p->UnwindData = d;
-
- /* put relocations on it */
- for (n = o + sizeof *p; o < n; o += sizeof p->BeginAddress)
- put_elf_reloc(symtab_section, pd, o, R_XXX_RELATIVE, s1->uw_sym);
-}
-#endif
-/* ------------------------------------------------------------- */
-#ifdef TCC_TARGET_X86_64
-#define PE_STDSYM(n,s) n
-#else
-#define PE_STDSYM(n,s) "_" n s
-#endif
-
-static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
-{
- const char *start_symbol;
- int pe_type;
-
- if (TCC_OUTPUT_DLL == s1->output_type) {
- pe_type = PE_DLL;
- start_symbol = PE_STDSYM("__dllstart","@12");
- } else {
- const char *run_symbol;
- if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16"))) {
- start_symbol = "__winstart";
- run_symbol = "__runwinmain";
- pe_type = PE_GUI;
- } else if (find_elf_sym(symtab_section, PE_STDSYM("wWinMain","@16"))) {
- start_symbol = "__wwinstart";
- run_symbol = "__runwwinmain";
- pe_type = PE_GUI;
- } else if (find_elf_sym(symtab_section, "wmain")) {
- start_symbol = "__wstart";
- run_symbol = "__runwmain";
- pe_type = PE_EXE;
- } else {
- start_symbol = "__start";
- run_symbol = "__runmain";
- pe_type = PE_EXE;
-
- }
- if (TCC_OUTPUT_MEMORY == s1->output_type)
- start_symbol = run_symbol;
- }
-
- pe->start_symbol = start_symbol + 1;
- if (!s1->leading_underscore || strchr(start_symbol, '@'))
- ++start_symbol;
-
-#ifdef CONFIG_TCC_BACKTRACE
- if (s1->do_backtrace) {
-#ifdef CONFIG_TCC_BCHECK
- if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL)
- tcc_add_support(s1, "bcheck.o");
-#endif
- if (s1->output_type == TCC_OUTPUT_EXE)
- tcc_add_support(s1, "bt-exe.o");
- if (s1->output_type == TCC_OUTPUT_DLL)
- tcc_add_support(s1, "bt-dll.o");
- if (s1->output_type != TCC_OUTPUT_DLL)
- tcc_add_support(s1, "bt-log.o");
- if (s1->output_type != TCC_OUTPUT_MEMORY)
- tcc_add_btstub(s1);
- }
-#endif
-
- /* grab the startup code from libtcc1.a */
-#ifdef TCC_IS_NATIVE
- if (TCC_OUTPUT_MEMORY != s1->output_type || s1->runtime_main)
-#endif
- set_global_sym(s1, start_symbol, NULL, 0);
-
- if (0 == s1->nostdlib) {
- static const char * const libs[] = {
- "msvcrt", "kernel32", "", "user32", "gdi32", NULL
- };
- const char * const *pp, *p;
- if (TCC_LIBTCC1[0])
- tcc_add_support(s1, TCC_LIBTCC1);
- for (pp = libs; 0 != (p = *pp); ++pp) {
- if (*p)
- tcc_add_library_err(s1, p);
- else if (PE_DLL != pe_type && PE_GUI != pe_type)
- break;
- }
- }
-
- /* need this for 'tccelf.c:relocate_sections()' */
- if (TCC_OUTPUT_DLL == s1->output_type)
- s1->output_type = TCC_OUTPUT_EXE;
- if (TCC_OUTPUT_MEMORY == s1->output_type)
- pe_type = PE_RUN;
- pe->type = pe_type;
-}
-
-static void pe_set_options(TCCState * s1, struct pe_info *pe)
-{
- if (PE_DLL == pe->type) {
- /* XXX: check if is correct for arm-pe target */
- pe->imagebase = 0x10000000;
- } else {
-#if defined(TCC_TARGET_ARM)
- pe->imagebase = 0x00010000;
-#else
- pe->imagebase = 0x00400000;
-#endif
- }
-
-#if defined(TCC_TARGET_ARM)
- /* we use "console" subsystem by default */
- pe->subsystem = 9;
-#else
- if (PE_DLL == pe->type || PE_GUI == pe->type)
- pe->subsystem = 2;
- else
- pe->subsystem = 3;
-#endif
- /* Allow override via -Wl,-subsystem=... option */
- if (s1->pe_subsystem != 0)
- pe->subsystem = s1->pe_subsystem;
-
- /* set default file/section alignment */
- if (pe->subsystem == 1) {
- pe->section_align = 0x20;
- pe->file_align = 0x20;
- } else {
- pe->section_align = 0x1000;
- pe->file_align = 0x200;
- }
-
- if (s1->section_align != 0)
- pe->section_align = s1->section_align;
- if (s1->pe_file_align != 0)
- pe->file_align = s1->pe_file_align;
-
- if ((pe->subsystem >= 10) && (pe->subsystem <= 12))
- pe->imagebase = 0;
-
- if (s1->has_text_addr)
- pe->imagebase = s1->text_addr;
-}
-
-ST_FUNC int pe_output_file(TCCState *s1, const char *filename)
-{
- struct pe_info pe;
-
- memset(&pe, 0, sizeof pe);
- pe.filename = filename;
- pe.s1 = s1;
- s1->filetype = 0;
-
-#ifdef CONFIG_TCC_BCHECK
- tcc_add_bcheck(s1);
-#endif
- tcc_add_pragma_libs(s1);
- pe_add_runtime(s1, &pe);
- resolve_common_syms(s1);
- pe_set_options(s1, &pe);
- pe_check_symbols(&pe);
-
- if (s1->nb_errors)
- ;
- else if (filename) {
- pe_assign_addresses(&pe);
- relocate_syms(s1, s1->symtab, 0);
- s1->pe_imagebase = pe.imagebase;
- relocate_sections(s1);
- pe.start_addr = (DWORD)
- (get_sym_addr(s1, pe.start_symbol, 1, 1) - pe.imagebase);
- if (0 == s1->nb_errors)
- pe_write(&pe);
- dynarray_reset(&pe.sec_info, &pe.sec_count);
- } else {
-#ifdef TCC_IS_NATIVE
- pe.thunk = data_section;
- pe_build_imports(&pe);
- s1->runtime_main = pe.start_symbol;
-#ifdef TCC_TARGET_X86_64
- s1->uw_pdata = find_section(s1, ".pdata");
-#endif
-#endif
- }
- pe_free_imports(&pe);
-#if PE_PRINT_SECTIONS
- if (s1->g_debug & 8)
- pe_print_sections(s1, "tcc.log");
-#endif
- return s1->nb_errors ? -1 : 0;
-}
-
-/* ------------------------------------------------------------- */
diff --git a/tinycc/tccpp.c b/tinycc/tccpp.c
deleted file mode 100644
index 717ab48..0000000
--- a/tinycc/tccpp.c
+++ /dev/null
@@ -1,3999 +0,0 @@
-/*
- * TCC - Tiny C Compiler
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#define USING_GLOBALS
-#include "tcc.h"
-
-/* #define to 1 to enable (see parse_pp_string()) */
-#define ACCEPT_LF_IN_STRINGS 0
-
-/********************************************************/
-/* global variables */
-
-ST_DATA int tok_flags;
-ST_DATA int parse_flags;
-
-ST_DATA struct BufferedFile *file;
-ST_DATA int tok;
-ST_DATA CValue tokc;
-ST_DATA const int *macro_ptr;
-ST_DATA CString tokcstr; /* current parsed string, if any */
-
-/* display benchmark infos */
-ST_DATA int tok_ident;
-ST_DATA TokenSym **table_ident;
-
-/* ------------------------------------------------------------------------- */
-
-static TokenSym *hash_ident[TOK_HASH_SIZE];
-static char token_buf[STRING_MAX_SIZE + 1];
-static CString cstr_buf;
-static TokenString tokstr_buf;
-static unsigned char isidnum_table[256 - CH_EOF];
-static int pp_debug_tok, pp_debug_symv;
-static int pp_once;
-static int pp_expr;
-static int pp_counter;
-static void tok_print(const char *msg, const int *str);
-
-static struct TinyAlloc *toksym_alloc;
-static struct TinyAlloc *tokstr_alloc;
-
-static TokenString *macro_stack;
-
-static const char tcc_keywords[] =
-#define DEF(id, str) str "\0"
-#include "tcctok.h"
-#undef DEF
-;
-
-/* WARNING: the content of this string encodes token numbers */
-static const unsigned char tok_two_chars[] =
-/* outdated -- gr
- "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253"
- "-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
-*/{
- '<','=', TOK_LE,
- '>','=', TOK_GE,
- '!','=', TOK_NE,
- '&','&', TOK_LAND,
- '|','|', TOK_LOR,
- '+','+', TOK_INC,
- '-','-', TOK_DEC,
- '=','=', TOK_EQ,
- '<','<', TOK_SHL,
- '>','>', TOK_SAR,
- '+','=', TOK_A_ADD,
- '-','=', TOK_A_SUB,
- '*','=', TOK_A_MUL,
- '/','=', TOK_A_DIV,
- '%','=', TOK_A_MOD,
- '&','=', TOK_A_AND,
- '^','=', TOK_A_XOR,
- '|','=', TOK_A_OR,
- '-','>', TOK_ARROW,
- '.','.', TOK_TWODOTS,
- '#','#', TOK_TWOSHARPS,
- '#','#', TOK_PPJOIN,
- 0
-};
-
-static void next_nomacro(void);
-
-ST_FUNC void skip(int c)
-{
- if (tok != c)
- tcc_error("'%c' expected (got \"%s\")", c, get_tok_str(tok, &tokc));
- next();
-}
-
-ST_FUNC void expect(const char *msg)
-{
- tcc_error("%s expected", msg);
-}
-
-/* ------------------------------------------------------------------------- */
-/* Custom allocator for tiny objects */
-
-#define USE_TAL
-
-#ifndef USE_TAL
-#define tal_free(al, p) tcc_free(p)
-#define tal_realloc(al, p, size) tcc_realloc(p, size)
-#define tal_new(a,b,c)
-#define tal_delete(a)
-#else
-#if !defined(MEM_DEBUG)
-#define tal_free(al, p) tal_free_impl(al, p)
-#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size)
-#define TAL_DEBUG_PARAMS
-#else
-#define TAL_DEBUG 1
-//#define TAL_INFO 1 /* collect and dump allocators stats */
-#define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__)
-#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__)
-#define TAL_DEBUG_PARAMS , const char *file, int line
-#define TAL_DEBUG_FILE_LEN 40
-#endif
-
-#define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */
-#define TOKSTR_TAL_SIZE (768 * 1024) /* allocator for tiny TokenString instances */
-#define CSTR_TAL_SIZE (256 * 1024) /* allocator for tiny CString instances */
-#define TOKSYM_TAL_LIMIT 256 /* prefer unique limits to distinguish allocators debug msgs */
-#define TOKSTR_TAL_LIMIT 128 /* 32 * sizeof(int) */
-#define CSTR_TAL_LIMIT 1024
-
-typedef struct TinyAlloc {
- unsigned limit;
- unsigned size;
- uint8_t *buffer;
- uint8_t *p;
- unsigned nb_allocs;
- struct TinyAlloc *next, *top;
-#ifdef TAL_INFO
- unsigned nb_peak;
- unsigned nb_total;
- unsigned nb_missed;
- uint8_t *peak_p;
-#endif
-} TinyAlloc;
-
-typedef struct tal_header_t {
- unsigned size;
-#ifdef TAL_DEBUG
- int line_num; /* negative line_num used for double free check */
- char file_name[TAL_DEBUG_FILE_LEN + 1];
-#endif
-} tal_header_t;
-
-/* ------------------------------------------------------------------------- */
-
-static TinyAlloc *tal_new(TinyAlloc **pal, unsigned limit, unsigned size)
-{
- TinyAlloc *al = tcc_mallocz(sizeof(TinyAlloc));
- al->p = al->buffer = tcc_malloc(size);
- al->limit = limit;
- al->size = size;
- if (pal) *pal = al;
- return al;
-}
-
-static void tal_delete(TinyAlloc *al)
-{
- TinyAlloc *next;
-
-tail_call:
- if (!al)
- return;
-#ifdef TAL_INFO
- fprintf(stderr, "limit=%5d, size=%5g MB, nb_peak=%6d, nb_total=%8d, nb_missed=%6d, usage=%5.1f%%\n",
- al->limit, al->size / 1024.0 / 1024.0, al->nb_peak, al->nb_total, al->nb_missed,
- (al->peak_p - al->buffer) * 100.0 / al->size);
-#endif
-#ifdef TAL_DEBUG
- if (al->nb_allocs > 0) {
- uint8_t *p;
- fprintf(stderr, "TAL_DEBUG: memory leak %d chunk(s) (limit= %d)\n",
- al->nb_allocs, al->limit);
- p = al->buffer;
- while (p < al->p) {
- tal_header_t *header = (tal_header_t *)p;
- if (header->line_num > 0) {
- fprintf(stderr, "%s:%d: chunk of %d bytes leaked\n",
- header->file_name, header->line_num, header->size);
- }
- p += header->size + sizeof(tal_header_t);
- }
-#if MEM_DEBUG-0 == 2
- exit(2);
-#endif
- }
-#endif
- next = al->next;
- tcc_free(al->buffer);
- tcc_free(al);
- al = next;
- goto tail_call;
-}
-
-static void tal_free_impl(TinyAlloc *al, void *p TAL_DEBUG_PARAMS)
-{
- if (!p)
- return;
-tail_call:
- if (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size) {
-#ifdef TAL_DEBUG
- tal_header_t *header = (((tal_header_t *)p) - 1);
- if (header->line_num < 0) {
- fprintf(stderr, "%s:%d: TAL_DEBUG: double frees chunk from\n",
- file, line);
- fprintf(stderr, "%s:%d: %d bytes\n",
- header->file_name, (int)-header->line_num, (int)header->size);
- } else
- header->line_num = -header->line_num;
-#endif
- al->nb_allocs--;
- if (!al->nb_allocs)
- al->p = al->buffer;
- } else if (al->next) {
- al = al->next;
- goto tail_call;
- }
- else
- tcc_free(p);
-}
-
-static void *tal_realloc_impl(TinyAlloc **pal, void *p, unsigned size TAL_DEBUG_PARAMS)
-{
- tal_header_t *header;
- void *ret;
- int is_own;
- unsigned adj_size = (size + 3) & -4;
- TinyAlloc *al = *pal;
-
-tail_call:
- is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size);
- if ((!p || is_own) && size <= al->limit) {
- if (al->p - al->buffer + adj_size + sizeof(tal_header_t) < al->size) {
- header = (tal_header_t *)al->p;
- header->size = adj_size;
-#ifdef TAL_DEBUG
- { int ofs = strlen(file) - TAL_DEBUG_FILE_LEN;
- strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), TAL_DEBUG_FILE_LEN);
- header->file_name[TAL_DEBUG_FILE_LEN] = 0;
- header->line_num = line; }
-#endif
- ret = al->p + sizeof(tal_header_t);
- al->p += adj_size + sizeof(tal_header_t);
- if (is_own) {
- header = (((tal_header_t *)p) - 1);
- if (p) memcpy(ret, p, header->size);
-#ifdef TAL_DEBUG
- header->line_num = -header->line_num;
-#endif
- } else {
- al->nb_allocs++;
- }
-#ifdef TAL_INFO
- if (al->nb_peak < al->nb_allocs)
- al->nb_peak = al->nb_allocs;
- if (al->peak_p < al->p)
- al->peak_p = al->p;
- al->nb_total++;
-#endif
- return ret;
- } else if (is_own) {
- al->nb_allocs--;
- ret = tal_realloc(*pal, 0, size);
- header = (((tal_header_t *)p) - 1);
- if (p) memcpy(ret, p, header->size);
-#ifdef TAL_DEBUG
- header->line_num = -header->line_num;
-#endif
- return ret;
- }
- if (al->next) {
- al = al->next;
- } else {
- TinyAlloc *bottom = al, *next = al->top ? al->top : al;
-
- al = tal_new(pal, next->limit, next->size * 2);
- al->next = next;
- bottom->top = al;
- }
- goto tail_call;
- }
- if (is_own) {
- al->nb_allocs--;
- ret = tcc_malloc(size);
- header = (((tal_header_t *)p) - 1);
- if (p) memcpy(ret, p, header->size);
-#ifdef TAL_DEBUG
- header->line_num = -header->line_num;
-#endif
- } else if (al->next) {
- al = al->next;
- goto tail_call;
- } else
- ret = tcc_realloc(p, size);
-#ifdef TAL_INFO
- al->nb_missed++;
-#endif
- return ret;
-}
-
-#endif /* USE_TAL */
-
-/* ------------------------------------------------------------------------- */
-/* CString handling */
-static void cstr_realloc(CString *cstr, int new_size)
-{
- int size;
-
- size = cstr->size_allocated;
- if (size < 8)
- size = 8; /* no need to allocate a too small first string */
- while (size < new_size)
- size = size * 2;
- cstr->data = tcc_realloc(cstr->data, size);
- cstr->size_allocated = size;
-}
-
-/* add a byte */
-ST_INLN void cstr_ccat(CString *cstr, int ch)
-{
- int size;
- size = cstr->size + 1;
- if (size > cstr->size_allocated)
- cstr_realloc(cstr, size);
- ((unsigned char *)cstr->data)[size - 1] = ch;
- cstr->size = size;
-}
-
-ST_INLN char *unicode_to_utf8 (char *b, uint32_t Uc)
-{
- if (Uc<0x80) *b++=Uc;
- else if (Uc<0x800) *b++=192+Uc/64, *b++=128+Uc%64;
- else if (Uc-0xd800u<0x800) goto error;
- else if (Uc<0x10000) *b++=224+Uc/4096, *b++=128+Uc/64%64, *b++=128+Uc%64;
- else if (Uc<0x110000) *b++=240+Uc/262144, *b++=128+Uc/4096%64, *b++=128+Uc/64%64, *b++=128+Uc%64;
- else error: tcc_error("0x%x is not a valid universal character", Uc);
- return b;
-}
-
-/* add a unicode character expanded into utf8 */
-ST_INLN void cstr_u8cat(CString *cstr, int ch)
-{
- char buf[4], *e;
- e = unicode_to_utf8(buf, (uint32_t)ch);
- cstr_cat(cstr, buf, e - buf);
-}
-
-ST_FUNC void cstr_cat(CString *cstr, const char *str, int len)
-{
- int size;
- if (len <= 0)
- len = strlen(str) + 1 + len;
- size = cstr->size + len;
- if (size > cstr->size_allocated)
- cstr_realloc(cstr, size);
- memmove(((unsigned char *)cstr->data) + cstr->size, str, len);
- cstr->size = size;
-}
-
-/* add a wide char */
-ST_FUNC void cstr_wccat(CString *cstr, int ch)
-{
- int size;
- size = cstr->size + sizeof(nwchar_t);
- if (size > cstr->size_allocated)
- cstr_realloc(cstr, size);
- *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
- cstr->size = size;
-}
-
-ST_FUNC void cstr_new(CString *cstr)
-{
- memset(cstr, 0, sizeof(CString));
-}
-
-/* free string and reset it to NULL */
-ST_FUNC void cstr_free(CString *cstr)
-{
- tcc_free(cstr->data);
-}
-
-/* reset string to empty */
-ST_FUNC void cstr_reset(CString *cstr)
-{
- cstr->size = 0;
-}
-
-ST_FUNC int cstr_vprintf(CString *cstr, const char *fmt, va_list ap)
-{
- va_list v;
- int len, size = 80;
- for (;;) {
- size += cstr->size;
- if (size > cstr->size_allocated)
- cstr_realloc(cstr, size);
- size = cstr->size_allocated - cstr->size;
- va_copy(v, ap);
- len = vsnprintf((char*)cstr->data + cstr->size, size, fmt, v);
- va_end(v);
- if (len >= 0 && len < size)
- break;
- size *= 2;
- }
- cstr->size += len;
- return len;
-}
-
-ST_FUNC int cstr_printf(CString *cstr, const char *fmt, ...)
-{
- va_list ap; int len;
- va_start(ap, fmt);
- len = cstr_vprintf(cstr, fmt, ap);
- va_end(ap);
- return len;
-}
-
-/* XXX: unicode ? */
-static void add_char(CString *cstr, int c)
-{
- if (c == '\'' || c == '\"' || c == '\\') {
- /* XXX: could be more precise if char or string */
- cstr_ccat(cstr, '\\');
- }
- if (c >= 32 && c <= 126) {
- cstr_ccat(cstr, c);
- } else {
- cstr_ccat(cstr, '\\');
- if (c == '\n') {
- cstr_ccat(cstr, 'n');
- } else {
- cstr_ccat(cstr, '0' + ((c >> 6) & 7));
- cstr_ccat(cstr, '0' + ((c >> 3) & 7));
- cstr_ccat(cstr, '0' + (c & 7));
- }
- }
-}
-
-/* ------------------------------------------------------------------------- */
-/* allocate a new token */
-static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
-{
- TokenSym *ts, **ptable;
- int i;
-
- if (tok_ident >= SYM_FIRST_ANOM)
- tcc_error("memory full (symbols)");
-
- /* expand token table if needed */
- i = tok_ident - TOK_IDENT;
- if ((i % TOK_ALLOC_INCR) == 0) {
- ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
- table_ident = ptable;
- }
-
- ts = tal_realloc(toksym_alloc, 0, sizeof(TokenSym) + len);
- table_ident[i] = ts;
- ts->tok = tok_ident++;
- ts->sym_define = NULL;
- ts->sym_label = NULL;
- ts->sym_struct = NULL;
- ts->sym_identifier = NULL;
- ts->len = len;
- ts->hash_next = NULL;
- memcpy(ts->str, str, len);
- ts->str[len] = '\0';
- *pts = ts;
- return ts;
-}
-
-#define TOK_HASH_INIT 1
-#define TOK_HASH_FUNC(h, c) ((h) + ((h) << 5) + ((h) >> 27) + (c))
-
-
-/* find a token and add it if not found */
-ST_FUNC TokenSym *tok_alloc(const char *str, int len)
-{
- TokenSym *ts, **pts;
- int i;
- unsigned int h;
-
- h = TOK_HASH_INIT;
- for(i=0;i<len;i++)
- h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
- h &= (TOK_HASH_SIZE - 1);
-
- pts = &hash_ident[h];
- for(;;) {
- ts = *pts;
- if (!ts)
- break;
- if (ts->len == len && !memcmp(ts->str, str, len))
- return ts;
- pts = &(ts->hash_next);
- }
- return tok_alloc_new(pts, str, len);
-}
-
-ST_FUNC int tok_alloc_const(const char *str)
-{
- return tok_alloc(str, strlen(str))->tok;
-}
-
-
-/* XXX: buffer overflow */
-/* XXX: float tokens */
-ST_FUNC const char *get_tok_str(int v, CValue *cv)
-{
- char *p;
- int i, len;
-
- cstr_reset(&cstr_buf);
- p = cstr_buf.data;
-
- switch(v) {
- case TOK_CINT:
- case TOK_CUINT:
- case TOK_CLONG:
- case TOK_CULONG:
- case TOK_CLLONG:
- case TOK_CULLONG:
- /* XXX: not quite exact, but only useful for testing */
-#ifdef _WIN32
- sprintf(p, "%u", (unsigned)cv->i);
-#else
- sprintf(p, "%llu", (unsigned long long)cv->i);
-#endif
- break;
- case TOK_LCHAR:
- cstr_ccat(&cstr_buf, 'L');
- case TOK_CCHAR:
- cstr_ccat(&cstr_buf, '\'');
- add_char(&cstr_buf, cv->i);
- cstr_ccat(&cstr_buf, '\'');
- cstr_ccat(&cstr_buf, '\0');
- break;
- case TOK_PPNUM:
- case TOK_PPSTR:
- return (char*)cv->str.data;
- case TOK_LSTR:
- cstr_ccat(&cstr_buf, 'L');
- case TOK_STR:
- cstr_ccat(&cstr_buf, '\"');
- if (v == TOK_STR) {
- len = cv->str.size - 1;
- for(i=0;i<len;i++)
- add_char(&cstr_buf, ((unsigned char *)cv->str.data)[i]);
- } else {
- len = (cv->str.size / sizeof(nwchar_t)) - 1;
- for(i=0;i<len;i++)
- add_char(&cstr_buf, ((nwchar_t *)cv->str.data)[i]);
- }
- cstr_ccat(&cstr_buf, '\"');
- cstr_ccat(&cstr_buf, '\0');
- break;
-
- case TOK_CFLOAT:
- return strcpy(p, "<float>");
- case TOK_CDOUBLE:
- return strcpy(p, "<double>");
- case TOK_CLDOUBLE:
- return strcpy(p, "<long double>");
- case TOK_LINENUM:
- return strcpy(p, "<linenumber");
-
- /* above tokens have value, the ones below don't */
- case TOK_LT:
- v = '<';
- goto addv;
- case TOK_GT:
- v = '>';
- goto addv;
- case TOK_DOTS:
- return strcpy(p, "...");
- case TOK_A_SHL:
- return strcpy(p, "<<=");
- case TOK_A_SAR:
- return strcpy(p, ">>=");
- case TOK_EOF:
- return strcpy(p, "<eof>");
- case 0: /* anonymous nameless symbols */
- return strcpy(p, "<no name>");
- default:
- if (v < TOK_IDENT) {
- /* search in two bytes table */
- const unsigned char *q = tok_two_chars;
- while (*q) {
- if (q[2] == v) {
- *p++ = q[0];
- *p++ = q[1];
- *p = '\0';
- return cstr_buf.data;
- }
- q += 3;
- }
- if (v >= 127 || (v < 32 && !is_space(v) && v != '\n')) {
- sprintf(p, "<\\x%02x>", v);
- break;
- }
- addv:
- *p++ = v;
- *p = '\0';
- } else if (v < tok_ident) {
- return table_ident[v - TOK_IDENT]->str;
- } else if (v >= SYM_FIRST_ANOM) {
- /* special name for anonymous symbol */
- sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
- } else {
- /* should never happen */
- return NULL;
- }
- break;
- }
- return cstr_buf.data;
-}
-
-static inline int check_space(int t, int *spc)
-{
- if (t < 256 && (isidnum_table[t - CH_EOF] & IS_SPC)) {
- if (*spc)
- return 1;
- *spc = 1;
- } else
- *spc = 0;
- return 0;
-}
-
-/* return the current character, handling end of block if necessary
- (but not stray) */
-static int handle_eob(void)
-{
- BufferedFile *bf = file;
- int len;
-
- /* only tries to read if really end of buffer */
- if (bf->buf_ptr >= bf->buf_end) {
- if (bf->fd >= 0) {
-#if defined(PARSE_DEBUG)
- len = 1;
-#else
- len = IO_BUF_SIZE;
-#endif
- len = read(bf->fd, bf->buffer, len);
- if (len < 0)
- len = 0;
- } else {
- len = 0;
- }
- total_bytes += len;
- bf->buf_ptr = bf->buffer;
- bf->buf_end = bf->buffer + len;
- *bf->buf_end = CH_EOB;
- }
- if (bf->buf_ptr < bf->buf_end) {
- return bf->buf_ptr[0];
- } else {
- bf->buf_ptr = bf->buf_end;
- return CH_EOF;
- }
-}
-
-/* read next char from current input file and handle end of input buffer */
-static int next_c(void)
-{
- int ch = *++file->buf_ptr;
- /* end of buffer/file handling */
- if (ch == CH_EOB && file->buf_ptr >= file->buf_end)
- ch = handle_eob();
- return ch;
-}
-
-/* input with '\[\r]\n' handling. */
-static int handle_stray_noerror(int err)
-{
- int ch;
- while ((ch = next_c()) == '\\') {
- ch = next_c();
- if (ch == '\n') {
- newl:
- file->line_num++;
- } else {
- if (ch == '\r') {
- ch = next_c();
- if (ch == '\n')
- goto newl;
- *--file->buf_ptr = '\r';
- }
- if (err)
- tcc_error("stray '\\' in program");
- /* may take advantage of 'BufferedFile.unget[4}' */
- return *--file->buf_ptr = '\\';
- }
- }
- return ch;
-}
-
-#define ninp() handle_stray_noerror(0)
-
-/* handle '\\' in strings, comments and skipped regions */
-static int handle_bs(uint8_t **p)
-{
- int c;
- file->buf_ptr = *p - 1;
- c = ninp();
- *p = file->buf_ptr;
- return c;
-}
-
-/* skip the stray and handle the \\n case. Output an error if
- incorrect char after the stray */
-static int handle_stray(uint8_t **p)
-{
- int c;
- file->buf_ptr = *p - 1;
- c = handle_stray_noerror(!(parse_flags & PARSE_FLAG_ACCEPT_STRAYS));
- *p = file->buf_ptr;
- return c;
-}
-
-/* handle the complicated stray case */
-#define PEEKC(c, p)\
-{\
- c = *++p;\
- if (c == '\\')\
- c = handle_stray(&p); \
-}
-
-static int skip_spaces(void)
-{
- int ch;
- --file->buf_ptr;
- do {
- ch = ninp();
- } while (isidnum_table[ch - CH_EOF] & IS_SPC);
- return ch;
-}
-
-/* single line C++ comments */
-static uint8_t *parse_line_comment(uint8_t *p)
-{
- int c;
- for(;;) {
- for (;;) {
- c = *++p;
- redo:
- if (c == '\n' || c == '\\')
- break;
- c = *++p;
- if (c == '\n' || c == '\\')
- break;
- }
- if (c == '\n')
- break;
- c = handle_bs(&p);
- if (c == CH_EOF)
- break;
- if (c != '\\')
- goto redo;
- }
- return p;
-}
-
-/* C comments */
-static uint8_t *parse_comment(uint8_t *p)
-{
- int c;
- for(;;) {
- /* fast skip loop */
- for(;;) {
- c = *++p;
- redo:
- if (c == '\n' || c == '*' || c == '\\')
- break;
- c = *++p;
- if (c == '\n' || c == '*' || c == '\\')
- break;
- }
- /* now we can handle all the cases */
- if (c == '\n') {
- file->line_num++;
- } else if (c == '*') {
- do {
- c = *++p;
- } while (c == '*');
- if (c == '\\')
- c = handle_bs(&p);
- if (c == '/')
- break;
- goto check_eof;
- } else {
- c = handle_bs(&p);
- check_eof:
- if (c == CH_EOF)
- tcc_error("unexpected end of file in comment");
- if (c != '\\')
- goto redo;
- }
- }
- return p + 1;
-}
-
-/* parse a string without interpreting escapes */
-static uint8_t *parse_pp_string(uint8_t *p, int sep, CString *str)
-{
- int c;
- for(;;) {
- c = *++p;
- redo:
- if (c == sep) {
- break;
- } else if (c == '\\') {
- c = handle_bs(&p);
- if (c == CH_EOF) {
- unterminated_string:
- /* XXX: indicate line number of start of string */
- tok_flags &= ~TOK_FLAG_BOL;
- tcc_error("missing terminating %c character", sep);
- } else if (c == '\\') {
- if (str)
- cstr_ccat(str, c);
- c = *++p;
- /* add char after '\\' unconditionally */
- if (c == '\\') {
- c = handle_bs(&p);
- if (c == CH_EOF)
- goto unterminated_string;
- }
- goto add_char;
- } else {
- goto redo;
- }
- } else if (c == '\n') {
- add_lf:
- if (ACCEPT_LF_IN_STRINGS) {
- file->line_num++;
- goto add_char;
- } else if (str) { /* not skipping */
- goto unterminated_string;
- } else {
- //tcc_warning("missing terminating %c character", sep);
- return p;
- }
- } else if (c == '\r') {
- c = *++p;
- if (c == '\\')
- c = handle_bs(&p);
- if (c == '\n')
- goto add_lf;
- if (c == CH_EOF)
- goto unterminated_string;
- if (str)
- cstr_ccat(str, '\r');
- goto redo;
- } else {
- add_char:
- if (str)
- cstr_ccat(str, c);
- }
- }
- p++;
- return p;
-}
-
-/* skip block of text until #else, #elif or #endif. skip also pairs of
- #if/#endif */
-static void preprocess_skip(void)
-{
- int a, start_of_line, c, in_warn_or_error;
- uint8_t *p;
-
- p = file->buf_ptr;
- a = 0;
-redo_start:
- start_of_line = 1;
- in_warn_or_error = 0;
- for(;;) {
- redo_no_start:
- c = *p;
- switch(c) {
- case ' ':
- case '\t':
- case '\f':
- case '\v':
- case '\r':
- p++;
- goto redo_no_start;
- case '\n':
- file->line_num++;
- p++;
- goto redo_start;
- case '\\':
- c = handle_bs(&p);
- if (c == CH_EOF)
- expect("#endif");
- if (c == '\\')
- ++p;
- goto redo_no_start;
- /* skip strings */
- case '\"':
- case '\'':
- if (in_warn_or_error)
- goto _default;
- tok_flags &= ~TOK_FLAG_BOL;
- p = parse_pp_string(p, c, NULL);
- break;
- /* skip comments */
- case '/':
- if (in_warn_or_error)
- goto _default;
- ++p;
- c = handle_bs(&p);
- if (c == '*') {
- p = parse_comment(p);
- } else if (c == '/') {
- p = parse_line_comment(p);
- }
- break;
- case '#':
- p++;
- if (start_of_line) {
- file->buf_ptr = p;
- next_nomacro();
- p = file->buf_ptr;
- if (a == 0 &&
- (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
- goto the_end;
- if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
- a++;
- else if (tok == TOK_ENDIF)
- a--;
- else if( tok == TOK_ERROR || tok == TOK_WARNING)
- in_warn_or_error = 1;
- else if (tok == TOK_LINEFEED)
- goto redo_start;
- else if (parse_flags & PARSE_FLAG_ASM_FILE)
- p = parse_line_comment(p - 1);
- }
-#if !defined(TCC_TARGET_ARM)
- else if (parse_flags & PARSE_FLAG_ASM_FILE)
- p = parse_line_comment(p - 1);
-#else
- /* ARM assembly uses '#' for constants */
-#endif
- break;
-_default:
- default:
- p++;
- break;
- }
- start_of_line = 0;
- }
- the_end: ;
- file->buf_ptr = p;
-}
-
-#if 0
-/* return the number of additional 'ints' necessary to store the
- token */
-static inline int tok_size(const int *p)
-{
- switch(*p) {
- /* 4 bytes */
- case TOK_CINT:
- case TOK_CUINT:
- case TOK_CCHAR:
- case TOK_LCHAR:
- case TOK_CFLOAT:
- case TOK_LINENUM:
- return 1 + 1;
- case TOK_STR:
- case TOK_LSTR:
- case TOK_PPNUM:
- case TOK_PPSTR:
- return 1 + ((sizeof(CString) + ((CString *)(p+1))->size + 3) >> 2);
- case TOK_CLONG:
- case TOK_CULONG:
- return 1 + LONG_SIZE / 4;
- case TOK_CDOUBLE:
- case TOK_CLLONG:
- case TOK_CULLONG:
- return 1 + 2;
- case TOK_CLDOUBLE:
-#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE
- return 1 + 8 / 4;
-#else
- return 1 + LDOUBLE_SIZE / 4;
-#endif
- default:
- return 1 + 0;
- }
-}
-#endif
-
-/* token string handling */
-ST_INLN void tok_str_new(TokenString *s)
-{
- s->str = NULL;
- s->len = s->lastlen = 0;
- s->allocated_len = 0;
- s->last_line_num = -1;
-}
-
-ST_FUNC TokenString *tok_str_alloc(void)
-{
- TokenString *str = tal_realloc(tokstr_alloc, 0, sizeof *str);
- tok_str_new(str);
- return str;
-}
-
-ST_FUNC int *tok_str_dup(TokenString *s)
-{
- int *str;
-
- str = tal_realloc(tokstr_alloc, 0, s->len * sizeof(int));
- memcpy(str, s->str, s->len * sizeof(int));
- return str;
-}
-
-ST_FUNC void tok_str_free_str(int *str)
-{
- tal_free(tokstr_alloc, str);
-}
-
-ST_FUNC void tok_str_free(TokenString *str)
-{
- tok_str_free_str(str->str);
- tal_free(tokstr_alloc, str);
-}
-
-ST_FUNC int *tok_str_realloc(TokenString *s, int new_size)
-{
- int *str, size;
-
- size = s->allocated_len;
- if (size < 16)
- size = 16;
- while (size < new_size)
- size = size * 2;
- if (size > s->allocated_len) {
- str = tal_realloc(tokstr_alloc, s->str, size * sizeof(int));
- s->allocated_len = size;
- s->str = str;
- }
- return s->str;
-}
-
-ST_FUNC void tok_str_add(TokenString *s, int t)
-{
- int len, *str;
-
- len = s->len;
- str = s->str;
- if (len >= s->allocated_len)
- str = tok_str_realloc(s, len + 1);
- str[len++] = t;
- s->len = len;
-}
-
-ST_FUNC void begin_macro(TokenString *str, int alloc)
-{
- str->alloc = alloc;
- str->prev = macro_stack;
- str->prev_ptr = macro_ptr;
- str->save_line_num = file->line_num;
- macro_ptr = str->str;
- macro_stack = str;
-}
-
-ST_FUNC void end_macro(void)
-{
- TokenString *str = macro_stack;
- macro_stack = str->prev;
- macro_ptr = str->prev_ptr;
- file->line_num = str->save_line_num;
- str->len = 0; /* matters if str not alloced, may be tokstr_buf */
- if (str->alloc != 0) {
- if (str->alloc == 2)
- str->str = NULL; /* don't free */
- tok_str_free(str);
- }
-}
-
-static void tok_str_add2(TokenString *s, int t, CValue *cv)
-{
- int len, *str;
-
- len = s->lastlen = s->len;
- str = s->str;
-
- /* allocate space for worst case */
- if (len + TOK_MAX_SIZE >= s->allocated_len)
- str = tok_str_realloc(s, len + TOK_MAX_SIZE + 1);
- str[len++] = t;
- switch(t) {
- case TOK_CINT:
- case TOK_CUINT:
- case TOK_CCHAR:
- case TOK_LCHAR:
- case TOK_CFLOAT:
- case TOK_LINENUM:
-#if LONG_SIZE == 4
- case TOK_CLONG:
- case TOK_CULONG:
-#endif
- str[len++] = cv->tab[0];
- break;
- case TOK_PPNUM:
- case TOK_PPSTR:
- case TOK_STR:
- case TOK_LSTR:
- {
- /* Insert the string into the int array. */
- size_t nb_words =
- 1 + (cv->str.size + sizeof(int) - 1) / sizeof(int);
- if (len + nb_words >= s->allocated_len)
- str = tok_str_realloc(s, len + nb_words + 1);
- str[len] = cv->str.size;
- memcpy(&str[len + 1], cv->str.data, cv->str.size);
- len += nb_words;
- }
- break;
- case TOK_CDOUBLE:
- case TOK_CLLONG:
- case TOK_CULLONG:
-#if LONG_SIZE == 8
- case TOK_CLONG:
- case TOK_CULONG:
-#endif
- str[len++] = cv->tab[0];
- str[len++] = cv->tab[1];
- break;
- case TOK_CLDOUBLE:
-#if LDOUBLE_SIZE == 8 || defined TCC_USING_DOUBLE_FOR_LDOUBLE
- str[len++] = cv->tab[0];
- str[len++] = cv->tab[1];
-#elif LDOUBLE_SIZE == 12
- str[len++] = cv->tab[0];
- str[len++] = cv->tab[1];
- str[len++] = cv->tab[2];
-#elif LDOUBLE_SIZE == 16
- str[len++] = cv->tab[0];
- str[len++] = cv->tab[1];
- str[len++] = cv->tab[2];
- str[len++] = cv->tab[3];
-#else
-#error add long double size support
-#endif
- break;
- default:
- break;
- }
- s->len = len;
-}
-
-/* add the current parse token in token string 's' */
-ST_FUNC void tok_str_add_tok(TokenString *s)
-{
- CValue cval;
-
- /* save line number info */
- if (file->line_num != s->last_line_num) {
- s->last_line_num = file->line_num;
- cval.i = s->last_line_num;
- tok_str_add2(s, TOK_LINENUM, &cval);
- }
- tok_str_add2(s, tok, &tokc);
-}
-
-/* get a token from an integer array and increment pointer. */
-static inline void tok_get(int *t, const int **pp, CValue *cv)
-{
- const int *p = *pp;
- int n, *tab;
-
- tab = cv->tab;
- switch(*t = *p++) {
-#if LONG_SIZE == 4
- case TOK_CLONG:
-#endif
- case TOK_CINT:
- case TOK_CCHAR:
- case TOK_LCHAR:
- case TOK_LINENUM:
- cv->i = *p++;
- break;
-#if LONG_SIZE == 4
- case TOK_CULONG:
-#endif
- case TOK_CUINT:
- cv->i = (unsigned)*p++;
- break;
- case TOK_CFLOAT:
- tab[0] = *p++;
- break;
- case TOK_STR:
- case TOK_LSTR:
- case TOK_PPNUM:
- case TOK_PPSTR:
- cv->str.size = *p++;
- cv->str.data = p;
- p += (cv->str.size + sizeof(int) - 1) / sizeof(int);
- break;
- case TOK_CDOUBLE:
- case TOK_CLLONG:
- case TOK_CULLONG:
-#if LONG_SIZE == 8
- case TOK_CLONG:
- case TOK_CULONG:
-#endif
- n = 2;
- goto copy;
- case TOK_CLDOUBLE:
-#if LDOUBLE_SIZE == 8 || defined TCC_USING_DOUBLE_FOR_LDOUBLE
- n = 2;
-#elif LDOUBLE_SIZE == 12
- n = 3;
-#elif LDOUBLE_SIZE == 16
- n = 4;
-#else
-# error add long double size support
-#endif
- copy:
- do
- *tab++ = *p++;
- while (--n);
- break;
- default:
- break;
- }
- *pp = p;
-}
-
-#if 0
-# define TOK_GET(t,p,c) tok_get(t,p,c)
-#else
-# define TOK_GET(t,p,c) do { \
- int _t = **(p); \
- if (TOK_HAS_VALUE(_t)) \
- tok_get(t, p, c); \
- else \
- *(t) = _t, ++*(p); \
- } while (0)
-#endif
-
-static int macro_is_equal(const int *a, const int *b)
-{
- CValue cv;
- int t;
-
- if (!a || !b)
- return 1;
-
- while (*a && *b) {
- cstr_reset(&tokcstr);
- TOK_GET(&t, &a, &cv);
- cstr_cat(&tokcstr, get_tok_str(t, &cv), 0);
- TOK_GET(&t, &b, &cv);
- if (strcmp(tokcstr.data, get_tok_str(t, &cv)))
- return 0;
- }
- return !(*a || *b);
-}
-
-/* defines handling */
-ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg)
-{
- Sym *s, *o;
-
- o = define_find(v);
- s = sym_push2(&define_stack, v, macro_type, 0);
- s->d = str;
- s->next = first_arg;
- table_ident[v - TOK_IDENT]->sym_define = s;
-
- if (o && !macro_is_equal(o->d, s->d))
- tcc_warning("%s redefined", get_tok_str(v, NULL));
-}
-
-/* undefined a define symbol. Its name is just set to zero */
-ST_FUNC void define_undef(Sym *s)
-{
- int v = s->v;
- if (v >= TOK_IDENT && v < tok_ident)
- table_ident[v - TOK_IDENT]->sym_define = NULL;
-}
-
-ST_INLN Sym *define_find(int v)
-{
- v -= TOK_IDENT;
- if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
- return NULL;
- return table_ident[v]->sym_define;
-}
-
-/* free define stack until top reaches 'b' */
-ST_FUNC void free_defines(Sym *b)
-{
- while (define_stack != b) {
- Sym *top = define_stack;
- define_stack = top->prev;
- tok_str_free_str(top->d);
- define_undef(top);
- sym_free(top);
- }
-}
-
-/* fake the nth "#if defined test_..." for tcc -dt -run */
-static void maybe_run_test(TCCState *s)
-{
- const char *p;
- if (s->include_stack_ptr != s->include_stack)
- return;
- p = get_tok_str(tok, NULL);
- if (0 != memcmp(p, "test_", 5))
- return;
- if (0 != --s->run_test)
- return;
- fprintf(s->ppfp, &"\n[%s]\n"[!(s->dflag & 32)], p), fflush(s->ppfp);
- define_push(tok, MACRO_OBJ, NULL, NULL);
-}
-
-static CachedInclude *
-search_cached_include(TCCState *s1, const char *filename, int add);
-
-static int parse_include(TCCState *s1, int do_next, int test)
-{
- int c, i;
- char name[1024], buf[1024], *p;
- CachedInclude *e;
-
- c = skip_spaces();
- if (c == '<' || c == '\"') {
- cstr_reset(&tokcstr);
- file->buf_ptr = parse_pp_string(file->buf_ptr, c == '<' ? '>' : c, &tokcstr);
- i = tokcstr.size;
- pstrncpy(name, tokcstr.data, i >= sizeof name ? sizeof name - 1 : i);
- next_nomacro();
- } else {
- /* computed #include : concatenate tokens until result is one of
- the two accepted forms. Don't convert pp-tokens to tokens here. */
- parse_flags = PARSE_FLAG_PREPROCESS
- | PARSE_FLAG_LINEFEED
- | (parse_flags & PARSE_FLAG_ASM_FILE);
- name[0] = 0;
- for (;;) {
- next();
- p = name, i = strlen(p) - 1;
- if (i > 0
- && ((p[0] == '"' && p[i] == '"')
- || (p[0] == '<' && p[i] == '>')))
- break;
- if (tok == TOK_LINEFEED)
- tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
- pstrcat(name, sizeof name, get_tok_str(tok, &tokc));
- }
- c = p[0];
- /* remove '<>|""' */
- memmove(p, p + 1, i - 1), p[i - 1] = 0;
- }
-
- i = do_next ? file->include_next_index : -1;
- for (;;) {
- ++i;
- if (i == 0) {
- /* check absolute include path */
- if (!IS_ABSPATH(name))
- continue;
- buf[0] = '\0';
- } else if (i == 1) {
- /* search in file's dir if "header.h" */
- if (c != '\"')
- continue;
- p = file->true_filename;
- pstrncpy(buf, p, tcc_basename(p) - p);
- } else {
- int j = i - 2, k = j - s1->nb_include_paths;
- if (k < 0)
- p = s1->include_paths[j];
- else if (k < s1->nb_sysinclude_paths)
- p = s1->sysinclude_paths[k];
- else if (test)
- return 0;
- else
- tcc_error("include file '%s' not found", name);
- pstrcpy(buf, sizeof buf, p);
- pstrcat(buf, sizeof buf, "/");
- }
- pstrcat(buf, sizeof buf, name);
- e = search_cached_include(s1, buf, 0);
- if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {
- /* no need to parse the include because the 'ifndef macro'
- is defined (or had #pragma once) */
-#ifdef INC_DEBUG
- printf("%s: skipping cached %s\n", file->filename, buf);
-#endif
- return 1;
- }
- if (tcc_open(s1, buf) >= 0)
- break;
- }
-
- if (test) {
- tcc_close();
- } else {
- if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
- tcc_error("#include recursion too deep");
- /* push previous file on stack */
- *s1->include_stack_ptr++ = file->prev;
- file->include_next_index = i;
-#ifdef INC_DEBUG
- printf("%s: including %s\n", file->prev->filename, file->filename);
-#endif
- /* update target deps */
- if (s1->gen_deps) {
- BufferedFile *bf = file;
- while (i == 1 && (bf = bf->prev))
- i = bf->include_next_index;
- /* skip system include files */
- if (s1->include_sys_deps || i - 2 < s1->nb_include_paths)
- dynarray_add(&s1->target_deps, &s1->nb_target_deps,
- tcc_strdup(buf));
- }
- /* add include file debug info */
- tcc_debug_bincl(s1);
- tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
- }
- return 1;
-}
-
-/* eval an expression for #if/#elif */
-static int expr_preprocess(TCCState *s1)
-{
- int c, t;
- TokenString *str;
-
- str = tok_str_alloc();
- pp_expr = 1;
- while (tok != TOK_LINEFEED && tok != TOK_EOF) {
- next(); /* do macro subst */
- redo:
- if (tok == TOK_DEFINED) {
- next_nomacro();
- t = tok;
- if (t == '(')
- next_nomacro();
- if (tok < TOK_IDENT)
- expect("identifier");
- if (s1->run_test)
- maybe_run_test(s1);
- c = 0;
- if (define_find(tok)
- || tok == TOK___HAS_INCLUDE
- || tok == TOK___HAS_INCLUDE_NEXT)
- c = 1;
- if (t == '(') {
- next_nomacro();
- if (tok != ')')
- expect("')'");
- }
- tok = TOK_CINT;
- tokc.i = c;
- } else if (tok == TOK___HAS_INCLUDE ||
- tok == TOK___HAS_INCLUDE_NEXT) {
- t = tok;
- next_nomacro();
- if (tok != '(')
- expect("(");
- c = parse_include(s1, t - TOK___HAS_INCLUDE, 1);
- if (tok != ')')
- expect("')'");
- tok = TOK_CINT;
- tokc.i = c;
- } else if (tok >= TOK_IDENT) {
- /* if undefined macro, replace with zero, check for func-like */
- t = tok;
- tok = TOK_CINT;
- tokc.i = 0;
- tok_str_add_tok(str);
- next();
- if (tok == '(')
- tcc_error("function-like macro '%s' is not defined",
- get_tok_str(t, NULL));
- goto redo;
- }
- tok_str_add_tok(str);
- }
- pp_expr = 0;
- tok_str_add(str, -1); /* simulate end of file */
- tok_str_add(str, 0);
- /* now evaluate C constant expression */
- begin_macro(str, 1);
- next();
- c = expr_const();
- end_macro();
- return c != 0;
-}
-
-
-/* parse after #define */
-ST_FUNC void parse_define(void)
-{
- Sym *s, *first, **ps;
- int v, t, varg, is_vaargs, spc;
- int saved_parse_flags = parse_flags;
-
- v = tok;
- if (v < TOK_IDENT || v == TOK_DEFINED)
- tcc_error("invalid macro name '%s'", get_tok_str(tok, &tokc));
- /* XXX: should check if same macro (ANSI) */
- first = NULL;
- t = MACRO_OBJ;
- /* We have to parse the whole define as if not in asm mode, in particular
- no line comment with '#' must be ignored. Also for function
- macros the argument list must be parsed without '.' being an ID
- character. */
- parse_flags = ((parse_flags & ~PARSE_FLAG_ASM_FILE) | PARSE_FLAG_SPACES);
- /* '(' must be just after macro definition for MACRO_FUNC */
- next_nomacro();
- parse_flags &= ~PARSE_FLAG_SPACES;
- if (tok == '(') {
- int dotid = set_idnum('.', 0);
- next_nomacro();
- ps = &first;
- if (tok != ')') for (;;) {
- varg = tok;
- next_nomacro();
- is_vaargs = 0;
- if (varg == TOK_DOTS) {
- varg = TOK___VA_ARGS__;
- is_vaargs = 1;
- } else if (tok == TOK_DOTS && gnu_ext) {
- is_vaargs = 1;
- next_nomacro();
- }
- if (varg < TOK_IDENT)
- bad_list:
- tcc_error("bad macro parameter list");
- s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
- *ps = s;
- ps = &s->next;
- if (tok == ')')
- break;
- if (tok != ',' || is_vaargs)
- goto bad_list;
- next_nomacro();
- }
- parse_flags |= PARSE_FLAG_SPACES;
- next_nomacro();
- t = MACRO_FUNC;
- set_idnum('.', dotid);
- }
-
- tokstr_buf.len = 0;
- spc = 2;
- parse_flags |= PARSE_FLAG_ACCEPT_STRAYS | PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED;
- /* The body of a macro definition should be parsed such that identifiers
- are parsed like the file mode determines (i.e. with '.' being an
- ID character in asm mode). But '#' should be retained instead of
- regarded as line comment leader, so still don't set ASM_FILE
- in parse_flags. */
- while (tok != TOK_LINEFEED && tok != TOK_EOF) {
- /* remove spaces around ## and after '#' */
- if (TOK_TWOSHARPS == tok) {
- if (2 == spc)
- goto bad_twosharp;
- if (1 == spc)
- --tokstr_buf.len;
- spc = 3;
- tok = TOK_PPJOIN;
- } else if ('#' == tok) {
- spc = 4;
- } else if (check_space(tok, &spc)) {
- goto skip;
- }
- tok_str_add2(&tokstr_buf, tok, &tokc);
- skip:
- next_nomacro();
- }
-
- parse_flags = saved_parse_flags;
- if (spc == 1)
- --tokstr_buf.len; /* remove trailing space */
- tok_str_add(&tokstr_buf, 0);
- if (3 == spc)
-bad_twosharp:
- tcc_error("'##' cannot appear at either end of macro");
- define_push(v, t, tok_str_dup(&tokstr_buf), first);
-}
-
-#ifdef _WIN32
-static unsigned long long calc_file_hash(const char *filename)
-{
- unsigned long long hash = 14695981039346656037ull; // FNV_offset_basis;
- int fd = open (filename, O_RDONLY | O_BINARY);
-
- if (fd < 0)
- return 0;
- for (;;) {
- unsigned char temp[IO_BUF_SIZE];
- int i, n = read(fd, temp, sizeof(temp));
-
- if (n <= 0)
- break;
- for (i = 0; i < n; i++)
- hash = hash * 1099511628211ull ^ temp[i]; // FNV_prime
- }
- close(fd);
- return hash ? hash : 1ull;
-}
-#endif
-
-static CachedInclude *search_cached_include(TCCState *s1, const char *filename, int add)
-{
- unsigned int h = 0;
- CachedInclude *e;
- int i;
- struct stat st;
-#ifdef _WIN32
- unsigned long long hash = 0;
-#endif
-
- /* This is needed for #pragmae once
- * We cannot use stat on windows because st_ino is not set correctly
- * so we calculate a hash of file contents.
- * This also works for hard/soft links as in gcc/clang.
- */
- memset (&st, 0, sizeof(st));
- if (stat (filename, &st))
- goto skip;
- h = st.st_size & (CACHED_INCLUDES_HASH_SIZE - 1);
-#ifdef _WIN32
- /* Only calculate file hash if file size same. */
- i = s1->cached_includes_hash[h];
- for(;;) {
- if (i == 0)
- break;
- e = s1->cached_includes[i - 1];
- if (e->st.st_size == st.st_size) {
- if (0 == PATHCMP(e->filename, filename)) {
- hash = e->hash;
- break;
- }
- if (e->hash == 0)
- e->hash = calc_file_hash(e->filename);
- if (hash == 0)
- hash = calc_file_hash(filename);
- }
- i = e->hash_next;
- }
-#endif
-
- i = s1->cached_includes_hash[h];
- for(;;) {
- if (i == 0)
- break;
- e = s1->cached_includes[i - 1];
-#ifdef _WIN32
- if (e->st.st_size == st.st_size && e->hash == hash)
-#else
- if (st.st_dev == e->st.st_dev && st.st_ino == e->st.st_ino)
-#endif
- return e;
- i = e->hash_next;
- }
-skip:
- if (!add)
- return NULL;
-
- e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
- e->st = st;
-#ifdef _WIN32
- e->hash = hash;
-#endif
- strcpy(e->filename, filename);
- e->ifndef_macro = e->once = 0;
- dynarray_add(&s1->cached_includes, &s1->nb_cached_includes, e);
- /* add in hash table */
- e->hash_next = s1->cached_includes_hash[h];
- s1->cached_includes_hash[h] = s1->nb_cached_includes;
-#ifdef INC_DEBUG
- printf("adding cached '%s'\n", filename);
-#endif
- return e;
-}
-
-static void pragma_parse(TCCState *s1)
-{
- next_nomacro();
- if (tok == TOK_push_macro || tok == TOK_pop_macro) {
- int t = tok, v;
- Sym *s;
-
- if (next(), tok != '(')
- goto pragma_err;
- if (next(), tok != TOK_STR)
- goto pragma_err;
- v = tok_alloc(tokc.str.data, tokc.str.size - 1)->tok;
- if (next(), tok != ')')
- goto pragma_err;
- if (t == TOK_push_macro) {
- while (NULL == (s = define_find(v)))
- define_push(v, 0, NULL, NULL);
- s->type.ref = s; /* set push boundary */
- } else {
- for (s = define_stack; s; s = s->prev)
- if (s->v == v && s->type.ref == s) {
- s->type.ref = NULL;
- break;
- }
- }
- if (s)
- table_ident[v - TOK_IDENT]->sym_define = s->d ? s : NULL;
- else
- tcc_warning("unbalanced #pragma pop_macro");
- pp_debug_tok = t, pp_debug_symv = v;
-
- } else if (tok == TOK_once) {
- search_cached_include(s1, file->filename, 1)->once = pp_once;
-
- } else if (s1->output_type == TCC_OUTPUT_PREPROCESS) {
- /* tcc -E: keep pragmas below unchanged */
- unget_tok(' ');
- unget_tok(TOK_PRAGMA);
- unget_tok('#');
- unget_tok(TOK_LINEFEED);
-
- } else if (tok == TOK_pack) {
- /* This may be:
- #pragma pack(1) // set
- #pragma pack() // reset to default
- #pragma pack(push) // push current
- #pragma pack(push,1) // push & set
- #pragma pack(pop) // restore previous */
- next();
- skip('(');
- if (tok == TOK_ASM_pop) {
- next();
- if (s1->pack_stack_ptr <= s1->pack_stack) {
- stk_error:
- tcc_error("out of pack stack");
- }
- s1->pack_stack_ptr--;
- } else {
- int val = 0;
- if (tok != ')') {
- if (tok == TOK_ASM_push) {
- next();
- if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
- goto stk_error;
- val = *s1->pack_stack_ptr++;
- if (tok != ',')
- goto pack_set;
- next();
- }
- if (tok != TOK_CINT)
- goto pragma_err;
- val = tokc.i;
- if (val < 1 || val > 16 || (val & (val - 1)) != 0)
- goto pragma_err;
- next();
- }
- pack_set:
- *s1->pack_stack_ptr = val;
- }
- if (tok != ')')
- goto pragma_err;
-
- } else if (tok == TOK_comment) {
- char *p; int t;
- next();
- skip('(');
- t = tok;
- next();
- skip(',');
- if (tok != TOK_STR)
- goto pragma_err;
- p = tcc_strdup((char *)tokc.str.data);
- next();
- if (tok != ')')
- goto pragma_err;
- if (t == TOK_lib) {
- dynarray_add(&s1->pragma_libs, &s1->nb_pragma_libs, p);
- } else {
- if (t == TOK_option)
- tcc_set_options(s1, p);
- tcc_free(p);
- }
-
- } else
- tcc_warning_c(warn_unsupported)("#pragma %s ignored", get_tok_str(tok, &tokc));
- return;
-
-pragma_err:
- tcc_error("malformed #pragma directive");
- return;
-}
-
-/* is_bof is true if first non space token at beginning of file */
-ST_FUNC void preprocess(int is_bof)
-{
- TCCState *s1 = tcc_state;
- int c, n, saved_parse_flags;
- char buf[1024], *q;
- Sym *s;
-
- saved_parse_flags = parse_flags;
- parse_flags = PARSE_FLAG_PREPROCESS
- | PARSE_FLAG_TOK_NUM
- | PARSE_FLAG_TOK_STR
- | PARSE_FLAG_LINEFEED
- | (parse_flags & PARSE_FLAG_ASM_FILE)
- ;
-
- next_nomacro();
- redo:
- switch(tok) {
- case TOK_DEFINE:
- pp_debug_tok = tok;
- next_nomacro();
- pp_debug_symv = tok;
- parse_define();
- break;
- case TOK_UNDEF:
- pp_debug_tok = tok;
- next_nomacro();
- pp_debug_symv = tok;
- s = define_find(tok);
- /* undefine symbol by putting an invalid name */
- if (s)
- define_undef(s);
- break;
- case TOK_INCLUDE:
- case TOK_INCLUDE_NEXT:
- parse_include(s1, tok - TOK_INCLUDE, 0);
- break;
- case TOK_IFNDEF:
- c = 1;
- goto do_ifdef;
- case TOK_IF:
- c = expr_preprocess(s1);
- goto do_if;
- case TOK_IFDEF:
- c = 0;
- do_ifdef:
- next_nomacro();
- if (tok < TOK_IDENT)
- tcc_error("invalid argument for '#if%sdef'", c ? "n" : "");
- if (is_bof) {
- if (c) {
-#ifdef INC_DEBUG
- printf("#ifndef %s\n", get_tok_str(tok, NULL));
-#endif
- file->ifndef_macro = tok;
- }
- }
- if (define_find(tok)
- || tok == TOK___HAS_INCLUDE
- || tok == TOK___HAS_INCLUDE_NEXT)
- c ^= 1;
- do_if:
- if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
- tcc_error("memory full (ifdef)");
- *s1->ifdef_stack_ptr++ = c;
- goto test_skip;
- case TOK_ELSE:
- if (s1->ifdef_stack_ptr == s1->ifdef_stack)
- tcc_error("#else without matching #if");
- if (s1->ifdef_stack_ptr[-1] & 2)
- tcc_error("#else after #else");
- c = (s1->ifdef_stack_ptr[-1] ^= 3);
- goto test_else;
- case TOK_ELIF:
- if (s1->ifdef_stack_ptr == s1->ifdef_stack)
- tcc_error("#elif without matching #if");
- c = s1->ifdef_stack_ptr[-1];
- if (c > 1)
- tcc_error("#elif after #else");
- /* last #if/#elif expression was true: we skip */
- if (c == 1) {
- c = 0;
- } else {
- c = expr_preprocess(s1);
- s1->ifdef_stack_ptr[-1] = c;
- }
- test_else:
- if (s1->ifdef_stack_ptr == file->ifdef_stack_ptr + 1)
- file->ifndef_macro = 0;
- test_skip:
- if (!(c & 1)) {
- preprocess_skip();
- is_bof = 0;
- goto redo;
- }
- break;
- case TOK_ENDIF:
- if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
- tcc_error("#endif without matching #if");
- s1->ifdef_stack_ptr--;
- /* '#ifndef macro' was at the start of file. Now we check if
- an '#endif' is exactly at the end of file */
- if (file->ifndef_macro &&
- s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
- file->ifndef_macro_saved = file->ifndef_macro;
- /* need to set to zero to avoid false matches if another
- #ifndef at middle of file */
- file->ifndef_macro = 0;
- while (tok != TOK_LINEFEED)
- next_nomacro();
- tok_flags |= TOK_FLAG_ENDIF;
- goto the_end;
- }
- break;
- case TOK_PPNUM:
- n = strtoul((char*)tokc.str.data, &q, 10);
- goto _line_num;
- case TOK_LINE:
- next();
- if (tok != TOK_CINT)
- _line_err:
- tcc_error("wrong #line format");
- n = tokc.i;
- _line_num:
- next();
- if (tok != TOK_LINEFEED) {
- if (tok == TOK_STR) {
- if (file->true_filename == file->filename)
- file->true_filename = tcc_strdup(file->filename);
- q = (char *)tokc.str.data;
- buf[0] = 0;
- if (!IS_ABSPATH(q)) {
- /* prepend directory from real file */
- pstrcpy(buf, sizeof buf, file->true_filename);
- *tcc_basename(buf) = 0;
- }
- pstrcat(buf, sizeof buf, q);
- tcc_debug_putfile(s1, buf);
- } else if (parse_flags & PARSE_FLAG_ASM_FILE)
- break;
- else
- goto _line_err;
- --n;
- }
- if (file->fd > 0)
- total_lines += file->line_num - n;
- file->line_num = n;
- break;
- case TOK_ERROR:
- case TOK_WARNING:
- q = buf;
- c = skip_spaces();
- while (c != '\n' && c != CH_EOF) {
- if ((q - buf) < sizeof(buf) - 1)
- *q++ = c;
- c = ninp();
- }
- *q = '\0';
- if (tok == TOK_ERROR)
- tcc_error("#error %s", buf);
- else
- tcc_warning("#warning %s", buf);
- break;
- case TOK_PRAGMA:
- pragma_parse(s1);
- break;
- case TOK_LINEFEED:
- goto the_end;
- default:
- /* ignore gas line comment in an 'S' file. */
- if (saved_parse_flags & PARSE_FLAG_ASM_FILE)
- goto ignore;
- if (tok == '!' && is_bof)
- /* '!' is ignored at beginning to allow C scripts. */
- goto ignore;
- tcc_warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
- ignore:
- file->buf_ptr = parse_line_comment(file->buf_ptr - 1);
- goto the_end;
- }
- /* ignore other preprocess commands or #! for C scripts */
- while (tok != TOK_LINEFEED)
- next_nomacro();
- the_end:
- parse_flags = saved_parse_flags;
-}
-
-/* evaluate escape codes in a string. */
-static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
-{
- int c, n, i;
- const uint8_t *p;
-
- p = buf;
- for(;;) {
- c = *p;
- if (c == '\0')
- break;
- if (c == '\\') {
- p++;
- /* escape */
- c = *p;
- switch(c) {
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- /* at most three octal digits */
- n = c - '0';
- p++;
- c = *p;
- if (isoct(c)) {
- n = n * 8 + c - '0';
- p++;
- c = *p;
- if (isoct(c)) {
- n = n * 8 + c - '0';
- p++;
- }
- }
- c = n;
- goto add_char_nonext;
- case 'x': i = 0; goto parse_hex_or_ucn;
- case 'u': i = 4; goto parse_hex_or_ucn;
- case 'U': i = 8; goto parse_hex_or_ucn;
- parse_hex_or_ucn:
- p++;
- n = 0;
- do {
- c = *p;
- if (c >= 'a' && c <= 'f')
- c = c - 'a' + 10;
- else if (c >= 'A' && c <= 'F')
- c = c - 'A' + 10;
- else if (isnum(c))
- c = c - '0';
- else if (i > 0)
- expect("more hex digits in universal-character-name");
- else
- goto add_hex_or_ucn;
- n = n * 16 + c;
- p++;
- } while (--i);
- if (is_long) {
- add_hex_or_ucn:
- c = n;
- goto add_char_nonext;
- }
- cstr_u8cat(outstr, n);
- continue;
- case 'a':
- c = '\a';
- break;
- case 'b':
- c = '\b';
- break;
- case 'f':
- c = '\f';
- break;
- case 'n':
- c = '\n';
- break;
- case 'r':
- c = '\r';
- break;
- case 't':
- c = '\t';
- break;
- case 'v':
- c = '\v';
- break;
- case 'e':
- if (!gnu_ext)
- goto invalid_escape;
- c = 27;
- break;
- case '\'':
- case '\"':
- case '\\':
- case '?':
- break;
- default:
- invalid_escape:
- if (c >= '!' && c <= '~')
- tcc_warning("unknown escape sequence: \'\\%c\'", c);
- else
- tcc_warning("unknown escape sequence: \'\\x%x\'", c);
- break;
- }
- } else if (is_long && c >= 0x80) {
- /* assume we are processing UTF-8 sequence */
- /* reference: The Unicode Standard, Version 10.0, ch3.9 */
-
- int cont; /* count of continuation bytes */
- int skip; /* how many bytes should skip when error occurred */
- int i;
-
- /* decode leading byte */
- if (c < 0xC2) {
- skip = 1; goto invalid_utf8_sequence;
- } else if (c <= 0xDF) {
- cont = 1; n = c & 0x1f;
- } else if (c <= 0xEF) {
- cont = 2; n = c & 0xf;
- } else if (c <= 0xF4) {
- cont = 3; n = c & 0x7;
- } else {
- skip = 1; goto invalid_utf8_sequence;
- }
-
- /* decode continuation bytes */
- for (i = 1; i <= cont; i++) {
- int l = 0x80, h = 0xBF;
-
- /* adjust limit for second byte */
- if (i == 1) {
- switch (c) {
- case 0xE0: l = 0xA0; break;
- case 0xED: h = 0x9F; break;
- case 0xF0: l = 0x90; break;
- case 0xF4: h = 0x8F; break;
- }
- }
-
- if (p[i] < l || p[i] > h) {
- skip = i; goto invalid_utf8_sequence;
- }
-
- n = (n << 6) | (p[i] & 0x3f);
- }
-
- /* advance pointer */
- p += 1 + cont;
- c = n;
- goto add_char_nonext;
-
- /* error handling */
- invalid_utf8_sequence:
- tcc_warning("ill-formed UTF-8 subsequence starting with: \'\\x%x\'", c);
- c = 0xFFFD;
- p += skip;
- goto add_char_nonext;
-
- }
- p++;
- add_char_nonext:
- if (!is_long)
- cstr_ccat(outstr, c);
- else {
-#ifdef TCC_TARGET_PE
- /* store as UTF-16 */
- if (c < 0x10000) {
- cstr_wccat(outstr, c);
- } else {
- c -= 0x10000;
- cstr_wccat(outstr, (c >> 10) + 0xD800);
- cstr_wccat(outstr, (c & 0x3FF) + 0xDC00);
- }
-#else
- cstr_wccat(outstr, c);
-#endif
- }
- }
- /* add a trailing '\0' */
- if (!is_long)
- cstr_ccat(outstr, '\0');
- else
- cstr_wccat(outstr, '\0');
-}
-
-static void parse_string(const char *s, int len)
-{
- uint8_t buf[1000], *p = buf;
- int is_long, sep;
-
- if ((is_long = *s == 'L'))
- ++s, --len;
- sep = *s++;
- len -= 2;
- if (len >= sizeof buf)
- p = tcc_malloc(len + 1);
- memcpy(p, s, len);
- p[len] = 0;
-
- cstr_reset(&tokcstr);
- parse_escape_string(&tokcstr, p, is_long);
- if (p != buf)
- tcc_free(p);
-
- if (sep == '\'') {
- int char_size, i, n, c;
- /* XXX: make it portable */
- if (!is_long)
- tok = TOK_CCHAR, char_size = 1;
- else
- tok = TOK_LCHAR, char_size = sizeof(nwchar_t);
- n = tokcstr.size / char_size - 1;
- if (n < 1)
- tcc_error("empty character constant");
- if (n > 1)
- tcc_warning_c(warn_all)("multi-character character constant");
- for (c = i = 0; i < n; ++i) {
- if (is_long)
- c = ((nwchar_t *)tokcstr.data)[i];
- else
- c = (c << 8) | ((char *)tokcstr.data)[i];
- }
- tokc.i = c;
- } else {
- tokc.str.size = tokcstr.size;
- tokc.str.data = tokcstr.data;
- if (!is_long)
- tok = TOK_STR;
- else
- tok = TOK_LSTR;
- }
-}
-
-/* we use 64 bit numbers */
-#define BN_SIZE 2
-
-/* bn = (bn << shift) | or_val */
-static void bn_lshift(unsigned int *bn, int shift, int or_val)
-{
- int i;
- unsigned int v;
- for(i=0;i<BN_SIZE;i++) {
- v = bn[i];
- bn[i] = (v << shift) | or_val;
- or_val = v >> (32 - shift);
- }
-}
-
-static void bn_zero(unsigned int *bn)
-{
- int i;
- for(i=0;i<BN_SIZE;i++) {
- bn[i] = 0;
- }
-}
-
-/* parse number in null terminated string 'p' and return it in the
- current token */
-static void parse_number(const char *p)
-{
- int b, t, shift, frac_bits, s, exp_val, ch;
- char *q;
- unsigned int bn[BN_SIZE];
- double d;
-
- /* number */
- q = token_buf;
- ch = *p++;
- t = ch;
- ch = *p++;
- *q++ = t;
- b = 10;
- if (t == '.') {
- goto float_frac_parse;
- } else if (t == '0') {
- if (ch == 'x' || ch == 'X') {
- q--;
- ch = *p++;
- b = 16;
- } else if (tcc_state->tcc_ext && (ch == 'b' || ch == 'B')) {
- q--;
- ch = *p++;
- b = 2;
- }
- }
- /* parse all digits. cannot check octal numbers at this stage
- because of floating point constants */
- while (1) {
- if (ch >= 'a' && ch <= 'f')
- t = ch - 'a' + 10;
- else if (ch >= 'A' && ch <= 'F')
- t = ch - 'A' + 10;
- else if (isnum(ch))
- t = ch - '0';
- else
- break;
- if (t >= b)
- break;
- if (q >= token_buf + STRING_MAX_SIZE) {
- num_too_long:
- tcc_error("number too long");
- }
- *q++ = ch;
- ch = *p++;
- }
- if (ch == '.' ||
- ((ch == 'e' || ch == 'E') && b == 10) ||
- ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
- if (b != 10) {
- /* NOTE: strtox should support that for hexa numbers, but
- non ISOC99 libcs do not support it, so we prefer to do
- it by hand */
- /* hexadecimal or binary floats */
- /* XXX: handle overflows */
- *q = '\0';
- if (b == 16)
- shift = 4;
- else
- shift = 1;
- bn_zero(bn);
- q = token_buf;
- while (1) {
- t = *q++;
- if (t == '\0') {
- break;
- } else if (t >= 'a') {
- t = t - 'a' + 10;
- } else if (t >= 'A') {
- t = t - 'A' + 10;
- } else {
- t = t - '0';
- }
- bn_lshift(bn, shift, t);
- }
- frac_bits = 0;
- if (ch == '.') {
- ch = *p++;
- while (1) {
- t = ch;
- if (t >= 'a' && t <= 'f') {
- t = t - 'a' + 10;
- } else if (t >= 'A' && t <= 'F') {
- t = t - 'A' + 10;
- } else if (t >= '0' && t <= '9') {
- t = t - '0';
- } else {
- break;
- }
- if (t >= b)
- tcc_error("invalid digit");
- bn_lshift(bn, shift, t);
- frac_bits += shift;
- ch = *p++;
- }
- }
- if (ch != 'p' && ch != 'P')
- expect("exponent");
- ch = *p++;
- s = 1;
- exp_val = 0;
- if (ch == '+') {
- ch = *p++;
- } else if (ch == '-') {
- s = -1;
- ch = *p++;
- }
- if (ch < '0' || ch > '9')
- expect("exponent digits");
- while (ch >= '0' && ch <= '9') {
- exp_val = exp_val * 10 + ch - '0';
- ch = *p++;
- }
- exp_val = exp_val * s;
-
- /* now we can generate the number */
- /* XXX: should patch directly float number */
- d = (double)bn[1] * 4294967296.0 + (double)bn[0];
- d = ldexp(d, exp_val - frac_bits);
- t = toup(ch);
- if (t == 'F') {
- ch = *p++;
- tok = TOK_CFLOAT;
- /* float : should handle overflow */
- tokc.f = (float)d;
- } else if (t == 'L') {
- ch = *p++;
- tok = TOK_CLDOUBLE;
-#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE
- tokc.d = d;
-#else
- /* XXX: not large enough */
- tokc.ld = (long double)d;
-#endif
- } else {
- tok = TOK_CDOUBLE;
- tokc.d = d;
- }
- } else {
- /* decimal floats */
- if (ch == '.') {
- if (q >= token_buf + STRING_MAX_SIZE)
- goto num_too_long;
- *q++ = ch;
- ch = *p++;
- float_frac_parse:
- while (ch >= '0' && ch <= '9') {
- if (q >= token_buf + STRING_MAX_SIZE)
- goto num_too_long;
- *q++ = ch;
- ch = *p++;
- }
- }
- if (ch == 'e' || ch == 'E') {
- if (q >= token_buf + STRING_MAX_SIZE)
- goto num_too_long;
- *q++ = ch;
- ch = *p++;
- if (ch == '-' || ch == '+') {
- if (q >= token_buf + STRING_MAX_SIZE)
- goto num_too_long;
- *q++ = ch;
- ch = *p++;
- }
- if (ch < '0' || ch > '9')
- expect("exponent digits");
- while (ch >= '0' && ch <= '9') {
- if (q >= token_buf + STRING_MAX_SIZE)
- goto num_too_long;
- *q++ = ch;
- ch = *p++;
- }
- }
- *q = '\0';
- t = toup(ch);
- errno = 0;
- if (t == 'F') {
- ch = *p++;
- tok = TOK_CFLOAT;
- tokc.f = strtof(token_buf, NULL);
- } else if (t == 'L') {
- ch = *p++;
- tok = TOK_CLDOUBLE;
-#ifdef TCC_USING_DOUBLE_FOR_LDOUBLE
- tokc.d = strtod(token_buf, NULL);
-#else
- tokc.ld = strtold(token_buf, NULL);
-#endif
- } else {
- tok = TOK_CDOUBLE;
- tokc.d = strtod(token_buf, NULL);
- }
- }
- } else {
- unsigned long long n, n1;
- int lcount, ucount, ov = 0;
- const char *p1;
-
- /* integer number */
- *q = '\0';
- q = token_buf;
- if (b == 10 && *q == '0') {
- b = 8;
- q++;
- }
- n = 0;
- while(1) {
- t = *q++;
- /* no need for checks except for base 10 / 8 errors */
- if (t == '\0')
- break;
- else if (t >= 'a')
- t = t - 'a' + 10;
- else if (t >= 'A')
- t = t - 'A' + 10;
- else
- t = t - '0';
- if (t >= b)
- tcc_error("invalid digit");
- n1 = n;
- n = n * b + t;
- /* detect overflow */
- if (n1 >= 0x1000000000000000ULL && n / b != n1)
- ov = 1;
- }
-
- /* Determine the characteristics (unsigned and/or 64bit) the type of
- the constant must have according to the constant suffix(es) */
- lcount = ucount = 0;
- p1 = p;
- for(;;) {
- t = toup(ch);
- if (t == 'L') {
- if (lcount >= 2)
- tcc_error("three 'l's in integer constant");
- if (lcount && *(p - 1) != ch)
- tcc_error("incorrect integer suffix: %s", p1);
- lcount++;
- ch = *p++;
- } else if (t == 'U') {
- if (ucount >= 1)
- tcc_error("two 'u's in integer constant");
- ucount++;
- ch = *p++;
- } else {
- break;
- }
- }
-
- /* Determine if it needs 64 bits and/or unsigned in order to fit */
- if (ucount == 0 && b == 10) {
- if (lcount <= (LONG_SIZE == 4)) {
- if (n >= 0x80000000U)
- lcount = (LONG_SIZE == 4) + 1;
- }
- if (n >= 0x8000000000000000ULL)
- ov = 1, ucount = 1;
- } else {
- if (lcount <= (LONG_SIZE == 4)) {
- if (n >= 0x100000000ULL)
- lcount = (LONG_SIZE == 4) + 1;
- else if (n >= 0x80000000U)
- ucount = 1;
- }
- if (n >= 0x8000000000000000ULL)
- ucount = 1;
- }
-
- if (ov)
- tcc_warning("integer constant overflow");
-
- tok = TOK_CINT;
- if (lcount) {
- tok = TOK_CLONG;
- if (lcount == 2)
- tok = TOK_CLLONG;
- }
- if (ucount)
- ++tok; /* TOK_CU... */
- tokc.i = n;
- }
- if (ch)
- tcc_error("invalid number");
-}
-
-
-#define PARSE2(c1, tok1, c2, tok2) \
- case c1: \
- PEEKC(c, p); \
- if (c == c2) { \
- p++; \
- tok = tok2; \
- } else { \
- tok = tok1; \
- } \
- break;
-
-/* return next token without macro substitution */
-static inline void next_nomacro1(void)
-{
- int t, c, is_long, len;
- TokenSym *ts;
- uint8_t *p, *p1;
- unsigned int h;
-
- p = file->buf_ptr;
- redo_no_start:
- c = *p;
- switch(c) {
- case ' ':
- case '\t':
- tok = c;
- p++;
- maybe_space:
- if (parse_flags & PARSE_FLAG_SPACES)
- goto keep_tok_flags;
- while (isidnum_table[*p - CH_EOF] & IS_SPC)
- ++p;
- goto redo_no_start;
- case '\f':
- case '\v':
- case '\r':
- p++;
- goto redo_no_start;
- case '\\':
- /* first look if it is in fact an end of buffer */
- c = handle_stray(&p);
- if (c == '\\')
- goto parse_simple;
- if (c == CH_EOF) {
- TCCState *s1 = tcc_state;
- if ((parse_flags & PARSE_FLAG_LINEFEED)
- && !(tok_flags & TOK_FLAG_EOF)) {
- tok_flags |= TOK_FLAG_EOF;
- tok = TOK_LINEFEED;
- goto keep_tok_flags;
- } else if (!(parse_flags & PARSE_FLAG_PREPROCESS)) {
- tok = TOK_EOF;
- } else if (s1->ifdef_stack_ptr != file->ifdef_stack_ptr) {
- tcc_error("missing #endif");
- } else if (s1->include_stack_ptr == s1->include_stack) {
- /* no include left : end of file. */
- tok = TOK_EOF;
- } else {
- tok_flags &= ~TOK_FLAG_EOF;
- /* pop include file */
-
- /* test if previous '#endif' was after a #ifdef at
- start of file */
- if (tok_flags & TOK_FLAG_ENDIF) {
-#ifdef INC_DEBUG
- printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
-#endif
- search_cached_include(s1, file->filename, 1)
- ->ifndef_macro = file->ifndef_macro_saved;
- tok_flags &= ~TOK_FLAG_ENDIF;
- }
-
- /* add end of include file debug info */
- tcc_debug_eincl(tcc_state);
- /* pop include stack */
- tcc_close();
- s1->include_stack_ptr--;
- p = file->buf_ptr;
- if (p == file->buffer)
- tok_flags = TOK_FLAG_BOF;
- tok_flags |= TOK_FLAG_BOL;
- goto redo_no_start;
- }
- } else {
- goto redo_no_start;
- }
- break;
-
- case '\n':
- file->line_num++;
- tok_flags |= TOK_FLAG_BOL;
- p++;
-maybe_newline:
- if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
- goto redo_no_start;
- tok = TOK_LINEFEED;
- goto keep_tok_flags;
-
- case '#':
- /* XXX: simplify */
- PEEKC(c, p);
- if ((tok_flags & TOK_FLAG_BOL) &&
- (parse_flags & PARSE_FLAG_PREPROCESS)) {
- file->buf_ptr = p;
- preprocess(tok_flags & TOK_FLAG_BOF);
- p = file->buf_ptr;
- goto maybe_newline;
- } else {
- if (c == '#') {
- p++;
- tok = TOK_TWOSHARPS;
- } else {
-#if !defined(TCC_TARGET_ARM)
- if (parse_flags & PARSE_FLAG_ASM_FILE) {
- p = parse_line_comment(p - 1);
- goto redo_no_start;
- } else
-#endif
- {
- tok = '#';
- }
- }
- }
- break;
-
- /* dollar is allowed to start identifiers when not parsing asm */
- case '$':
- if (!(isidnum_table[c - CH_EOF] & IS_ID)
- || (parse_flags & PARSE_FLAG_ASM_FILE))
- goto parse_simple;
-
- case 'a': case 'b': case 'c': case 'd':
- case 'e': case 'f': case 'g': case 'h':
- case 'i': case 'j': case 'k': case 'l':
- case 'm': case 'n': case 'o': case 'p':
- case 'q': case 'r': case 's': case 't':
- case 'u': case 'v': case 'w': case 'x':
- case 'y': case 'z':
- case 'A': case 'B': case 'C': case 'D':
- case 'E': case 'F': case 'G': case 'H':
- case 'I': case 'J': case 'K':
- case 'M': case 'N': case 'O': case 'P':
- case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X':
- case 'Y': case 'Z':
- case '_':
- parse_ident_fast:
- p1 = p;
- h = TOK_HASH_INIT;
- h = TOK_HASH_FUNC(h, c);
- while (c = *++p, isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
- h = TOK_HASH_FUNC(h, c);
- len = p - p1;
- if (c != '\\') {
- TokenSym **pts;
-
- /* fast case : no stray found, so we have the full token
- and we have already hashed it */
- h &= (TOK_HASH_SIZE - 1);
- pts = &hash_ident[h];
- for(;;) {
- ts = *pts;
- if (!ts)
- break;
- if (ts->len == len && !memcmp(ts->str, p1, len))
- goto token_found;
- pts = &(ts->hash_next);
- }
- ts = tok_alloc_new(pts, (char *) p1, len);
- token_found: ;
- } else {
- /* slower case */
- cstr_reset(&tokcstr);
- cstr_cat(&tokcstr, (char *) p1, len);
- p--;
- PEEKC(c, p);
- parse_ident_slow:
- while (isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
- {
- cstr_ccat(&tokcstr, c);
- PEEKC(c, p);
- }
- ts = tok_alloc(tokcstr.data, tokcstr.size);
- }
- tok = ts->tok;
- break;
- case 'L':
- t = p[1];
- if (t != '\\' && t != '\'' && t != '\"') {
- /* fast case */
- goto parse_ident_fast;
- } else {
- PEEKC(c, p);
- if (c == '\'' || c == '\"') {
- is_long = 1;
- goto str_const;
- } else {
- cstr_reset(&tokcstr);
- cstr_ccat(&tokcstr, 'L');
- goto parse_ident_slow;
- }
- }
- break;
-
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- case '8': case '9':
- t = c;
- PEEKC(c, p);
- /* after the first digit, accept digits, alpha, '.' or sign if
- prefixed by 'eEpP' */
- parse_num:
- cstr_reset(&tokcstr);
- for(;;) {
- cstr_ccat(&tokcstr, t);
- if (!((isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))
- || c == '.'
- || ((c == '+' || c == '-')
- && (((t == 'e' || t == 'E')
- && !(parse_flags & PARSE_FLAG_ASM_FILE
- /* 0xe+1 is 3 tokens in asm */
- && ((char*)tokcstr.data)[0] == '0'
- && toup(((char*)tokcstr.data)[1]) == 'X'))
- || t == 'p' || t == 'P'))))
- break;
- t = c;
- PEEKC(c, p);
- }
- /* We add a trailing '\0' to ease parsing */
- cstr_ccat(&tokcstr, '\0');
- tokc.str.size = tokcstr.size;
- tokc.str.data = tokcstr.data;
- tok = TOK_PPNUM;
- break;
-
- case '.':
- /* special dot handling because it can also start a number */
- PEEKC(c, p);
- if (isnum(c)) {
- t = '.';
- goto parse_num;
- } else if ((isidnum_table['.' - CH_EOF] & IS_ID)
- && (isidnum_table[c - CH_EOF] & (IS_ID|IS_NUM))) {
- *--p = c = '.';
- goto parse_ident_fast;
- } else if (c == '.') {
- PEEKC(c, p);
- if (c == '.') {
- p++;
- tok = TOK_DOTS;
- } else {
- *--p = '.'; /* may underflow into file->unget[] */
- tok = '.';
- }
- } else {
- tok = '.';
- }
- break;
- case '\'':
- case '\"':
- is_long = 0;
- str_const:
- cstr_reset(&tokcstr);
- if (is_long)
- cstr_ccat(&tokcstr, 'L');
- cstr_ccat(&tokcstr, c);
- p = parse_pp_string(p, c, &tokcstr);
- cstr_ccat(&tokcstr, c);
- cstr_ccat(&tokcstr, '\0');
- tokc.str.size = tokcstr.size;
- tokc.str.data = tokcstr.data;
- tok = TOK_PPSTR;
- break;
-
- case '<':
- PEEKC(c, p);
- if (c == '=') {
- p++;
- tok = TOK_LE;
- } else if (c == '<') {
- PEEKC(c, p);
- if (c == '=') {
- p++;
- tok = TOK_A_SHL;
- } else {
- tok = TOK_SHL;
- }
- } else {
- tok = TOK_LT;
- }
- break;
- case '>':
- PEEKC(c, p);
- if (c == '=') {
- p++;
- tok = TOK_GE;
- } else if (c == '>') {
- PEEKC(c, p);
- if (c == '=') {
- p++;
- tok = TOK_A_SAR;
- } else {
- tok = TOK_SAR;
- }
- } else {
- tok = TOK_GT;
- }
- break;
-
- case '&':
- PEEKC(c, p);
- if (c == '&') {
- p++;
- tok = TOK_LAND;
- } else if (c == '=') {
- p++;
- tok = TOK_A_AND;
- } else {
- tok = '&';
- }
- break;
-
- case '|':
- PEEKC(c, p);
- if (c == '|') {
- p++;
- tok = TOK_LOR;
- } else if (c == '=') {
- p++;
- tok = TOK_A_OR;
- } else {
- tok = '|';
- }
- break;
-
- case '+':
- PEEKC(c, p);
- if (c == '+') {
- p++;
- tok = TOK_INC;
- } else if (c == '=') {
- p++;
- tok = TOK_A_ADD;
- } else {
- tok = '+';
- }
- break;
-
- case '-':
- PEEKC(c, p);
- if (c == '-') {
- p++;
- tok = TOK_DEC;
- } else if (c == '=') {
- p++;
- tok = TOK_A_SUB;
- } else if (c == '>') {
- p++;
- tok = TOK_ARROW;
- } else {
- tok = '-';
- }
- break;
-
- PARSE2('!', '!', '=', TOK_NE)
- PARSE2('=', '=', '=', TOK_EQ)
- PARSE2('*', '*', '=', TOK_A_MUL)
- PARSE2('%', '%', '=', TOK_A_MOD)
- PARSE2('^', '^', '=', TOK_A_XOR)
-
- /* comments or operator */
- case '/':
- PEEKC(c, p);
- if (c == '*') {
- p = parse_comment(p);
- /* comments replaced by a blank */
- tok = ' ';
- goto maybe_space;
- } else if (c == '/') {
- p = parse_line_comment(p);
- tok = ' ';
- goto maybe_space;
- } else if (c == '=') {
- p++;
- tok = TOK_A_DIV;
- } else {
- tok = '/';
- }
- break;
-
- /* simple tokens */
- case '(':
- case ')':
- case '[':
- case ']':
- case '{':
- case '}':
- case ',':
- case ';':
- case ':':
- case '?':
- case '~':
- case '@': /* only used in assembler */
- parse_simple:
- tok = c;
- p++;
- break;
- default:
- if (c >= 0x80 && c <= 0xFF) /* utf8 identifiers */
- goto parse_ident_fast;
- if (parse_flags & PARSE_FLAG_ASM_FILE)
- goto parse_simple;
- tcc_error("unrecognized character \\x%02x", c);
- break;
- }
- tok_flags = 0;
-keep_tok_flags:
- file->buf_ptr = p;
-#if defined(PARSE_DEBUG)
- printf("token = %d %s\n", tok, get_tok_str(tok, &tokc));
-#endif
-}
-
-static void macro_subst(
- TokenString *tok_str,
- Sym **nested_list,
- const int *macro_str
- );
-
-/* substitute arguments in replacement lists in macro_str by the values in
- args (field d) and return allocated string */
-static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
-{
- int t, t0, t1, spc;
- const int *st;
- Sym *s;
- CValue cval;
- TokenString str;
-
- tok_str_new(&str);
- t0 = t1 = 0;
- while(1) {
- TOK_GET(&t, &macro_str, &cval);
- if (!t)
- break;
- if (t == '#') {
- /* stringize */
- TOK_GET(&t, &macro_str, &cval);
- if (!t)
- goto bad_stringy;
- s = sym_find2(args, t);
- if (s) {
- cstr_reset(&tokcstr);
- cstr_ccat(&tokcstr, '\"');
- st = s->d;
- spc = 0;
- while (*st >= 0) {
- TOK_GET(&t, &st, &cval);
- if (t != TOK_PLCHLDR
- && t != TOK_NOSUBST
- && 0 == check_space(t, &spc)) {
- const char *s = get_tok_str(t, &cval);
- while (*s) {
- if (t == TOK_PPSTR && *s != '\'')
- add_char(&tokcstr, *s);
- else
- cstr_ccat(&tokcstr, *s);
- ++s;
- }
- }
- }
- tokcstr.size -= spc;
- cstr_ccat(&tokcstr, '\"');
- cstr_ccat(&tokcstr, '\0');
-#ifdef PP_DEBUG
- printf("\nstringize: <%s>\n", (char *)tokcstr.data);
-#endif
- /* add string */
- cval.str.size = tokcstr.size;
- cval.str.data = tokcstr.data;
- tok_str_add2(&str, TOK_PPSTR, &cval);
- } else {
- bad_stringy:
- expect("macro parameter after '#'");
- }
- } else if (t >= TOK_IDENT) {
- s = sym_find2(args, t);
- if (s) {
- st = s->d;
- /* if '##' is present before or after, no arg substitution */
- if (*macro_str == TOK_PPJOIN || t1 == TOK_PPJOIN) {
- /* special case for var arg macros : ## eats the ','
- if empty VA_ARGS variable. */
- if (t1 == TOK_PPJOIN && t0 == ',' && gnu_ext && s->type.t) {
- if (*st <= 0) {
- /* suppress ',' '##' */
- str.len -= 2;
- } else {
- /* suppress '##' and add variable */
- str.len--;
- goto add_var;
- }
- }
- } else {
- add_var:
- if (!s->next) {
- /* Expand arguments tokens and store them. In most
- cases we could also re-expand each argument if
- used multiple times, but not if the argument
- contains the __COUNTER__ macro. */
- TokenString str2;
- sym_push2(&s->next, s->v, s->type.t, 0);
- tok_str_new(&str2);
- macro_subst(&str2, nested_list, st);
- tok_str_add(&str2, 0);
- s->next->d = str2.str;
- }
- st = s->next->d;
- }
- if (*st <= 0) {
- /* expanded to empty string */
- tok_str_add(&str, TOK_PLCHLDR);
- } else for (;;) {
- int t2;
- TOK_GET(&t2, &st, &cval);
- if (t2 <= 0)
- break;
- tok_str_add2(&str, t2, &cval);
- }
- } else {
- tok_str_add(&str, t);
- }
- } else {
- tok_str_add2(&str, t, &cval);
- }
- t0 = t1, t1 = t;
- }
- tok_str_add(&str, 0);
- return str.str;
-}
-
-static char const ab_month_name[12][4] =
-{
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2)
-{
- int n, ret = 1;
-
- cstr_reset(&tokcstr);
- if (t1 != TOK_PLCHLDR)
- cstr_cat(&tokcstr, get_tok_str(t1, v1), -1);
- n = tokcstr.size;
- if (t2 != TOK_PLCHLDR)
- cstr_cat(&tokcstr, get_tok_str(t2, v2), -1);
- cstr_ccat(&tokcstr, '\0');
- //printf("paste <%s>\n", (char*)tokcstr.data);
-
- tcc_open_bf(tcc_state, ":paste:", tokcstr.size);
- memcpy(file->buffer, tokcstr.data, tokcstr.size);
- tok_flags = 0;
- for (;;) {
- next_nomacro1();
- if (0 == *file->buf_ptr)
- break;
- if (is_space(tok))
- continue;
- tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid"
- " preprocessing token", n, file->buffer, file->buffer + n);
- ret = 0;
- break;
- }
- tcc_close();
- return ret;
-}
-
-/* handle the '##' operator. Return NULL if no '##' seen. Otherwise
- return the resulting string (which must be freed). */
-static inline int *macro_twosharps(const int *ptr0)
-{
- int t;
- CValue cval;
- TokenString macro_str1;
- int start_of_nosubsts = -1;
- const int *ptr;
-
- /* we search the first '##' */
- for (ptr = ptr0;;) {
- TOK_GET(&t, &ptr, &cval);
- if (t == TOK_PPJOIN)
- break;
- if (t == 0)
- return NULL;
- }
-
- tok_str_new(&macro_str1);
-
- //tok_print(" $$$", ptr0);
- for (ptr = ptr0;;) {
- TOK_GET(&t, &ptr, &cval);
- if (t == 0)
- break;
- if (t == TOK_PPJOIN)
- continue;
- while (*ptr == TOK_PPJOIN) {
- int t1; CValue cv1;
- /* given 'a##b', remove nosubsts preceding 'a' */
- if (start_of_nosubsts >= 0)
- macro_str1.len = start_of_nosubsts;
- /* given 'a##b', remove nosubsts preceding 'b' */
- while ((t1 = *++ptr) == TOK_NOSUBST)
- ;
- if (t1 && t1 != TOK_PPJOIN) {
- TOK_GET(&t1, &ptr, &cv1);
- if (t != TOK_PLCHLDR || t1 != TOK_PLCHLDR) {
- if (paste_tokens(t, &cval, t1, &cv1)) {
- t = tok, cval = tokc;
- } else {
- tok_str_add2(&macro_str1, t, &cval);
- t = t1, cval = cv1;
- }
- }
- }
- }
- if (t == TOK_NOSUBST) {
- if (start_of_nosubsts < 0)
- start_of_nosubsts = macro_str1.len;
- } else {
- start_of_nosubsts = -1;
- }
- tok_str_add2(&macro_str1, t, &cval);
- }
- tok_str_add(&macro_str1, 0);
- //tok_print(" ###", macro_str1.str);
- return macro_str1.str;
-}
-
-/* peek or read [ws_str == NULL] next token from function macro call,
- walking up macro levels up to the file if necessary */
-static int next_argstream(Sym **nested_list, TokenString *ws_str)
-{
- int t;
- const int *p;
- Sym *sa;
-
- for (;;) {
- if (macro_ptr) {
- p = macro_ptr, t = *p;
- if (ws_str) {
- while (is_space(t) || TOK_LINEFEED == t || TOK_PLCHLDR == t)
- tok_str_add(ws_str, t), t = *++p;
- }
- if (t == 0) {
- end_macro();
- /* also, end of scope for nested defined symbol */
- sa = *nested_list;
- while (sa && sa->v == 0)
- sa = sa->prev;
- if (sa)
- sa->v = 0;
- continue;
- }
- } else {
- uint8_t *p = file->buf_ptr;
- int ch = handle_bs(&p);
- if (ws_str) {
- while (is_space(ch) || ch == '\n' || ch == '/') {
- if (ch == '/') {
- int c;
- PEEKC(c, p);
- if (c == '*') {
- p = parse_comment(p) - 1;
- } else if (c == '/') {
- p = parse_line_comment(p) - 1;
- } else {
- *--p = ch;
- break;
- }
- ch = ' ';
- }
- if (ch == '\n')
- file->line_num++;
- if (!(ch == '\f' || ch == '\v' || ch == '\r'))
- tok_str_add(ws_str, ch);
- PEEKC(ch, p);
- }
- }
- file->buf_ptr = p;
- t = ch;
- }
-
- if (ws_str)
- return t;
- next_nomacro();
- return tok;
- }
-}
-
-/* do macro substitution of current token with macro 's' and add
- result to (tok_str,tok_len). 'nested_list' is the list of all
- macros we got inside to avoid recursing. Return non zero if no
- substitution needs to be done */
-static int macro_subst_tok(
- TokenString *tok_str,
- Sym **nested_list,
- Sym *s)
-{
- Sym *args, *sa, *sa1;
- int parlevel, t, t1, spc;
- TokenString str;
- char *cstrval;
- CValue cval;
- char buf[32];
-
- /* if symbol is a macro, prepare substitution */
- /* special macros */
- if (tok == TOK___LINE__ || tok == TOK___COUNTER__) {
- t = tok == TOK___LINE__ ? file->line_num : pp_counter++;
- snprintf(buf, sizeof(buf), "%d", t);
- cstrval = buf;
- t1 = TOK_PPNUM;
- goto add_cstr1;
- } else if (tok == TOK___FILE__) {
- cstrval = file->filename;
- goto add_cstr;
- } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
- time_t ti;
- struct tm *tm;
-
- time(&ti);
- tm = localtime(&ti);
- if (tok == TOK___DATE__) {
- snprintf(buf, sizeof(buf), "%s %2d %d",
- ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
- } else {
- snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
- tm->tm_hour, tm->tm_min, tm->tm_sec);
- }
- cstrval = buf;
- add_cstr:
- t1 = TOK_STR;
- add_cstr1:
- cstr_reset(&tokcstr);
- cstr_cat(&tokcstr, cstrval, 0);
- cval.str.size = tokcstr.size;
- cval.str.data = tokcstr.data;
- tok_str_add2(tok_str, t1, &cval);
- } else if (s->d) {
- int saved_parse_flags = parse_flags;
- int *joined_str = NULL;
- int *mstr = s->d;
-
- if (s->type.t == MACRO_FUNC) {
- /* whitespace between macro name and argument list */
- TokenString ws_str;
- tok_str_new(&ws_str);
-
- spc = 0;
- parse_flags |= PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED
- | PARSE_FLAG_ACCEPT_STRAYS;
-
- /* get next token from argument stream */
- t = next_argstream(nested_list, &ws_str);
- if (t != '(') {
- /* not a macro substitution after all, restore the
- * macro token plus all whitespace we've read.
- * whitespace is intentionally not merged to preserve
- * newlines. */
- parse_flags = saved_parse_flags;
- tok_str_add(tok_str, tok);
- if (parse_flags & PARSE_FLAG_SPACES) {
- int i;
- for (i = 0; i < ws_str.len; i++)
- tok_str_add(tok_str, ws_str.str[i]);
- }
- if (ws_str.len && ws_str.str[ws_str.len - 1] == '\n')
- tok_flags |= TOK_FLAG_BOL;
- tok_str_free_str(ws_str.str);
- return 0;
- } else {
- tok_str_free_str(ws_str.str);
- }
- do {
- next_nomacro(); /* eat '(' */
- } while (tok == TOK_PLCHLDR || is_space(tok));
-
- /* argument macro */
- args = NULL;
- sa = s->next;
- /* NOTE: empty args are allowed, except if no args */
- for(;;) {
- do {
- next_argstream(nested_list, NULL);
- } while (tok == TOK_PLCHLDR || is_space(tok) ||
- TOK_LINEFEED == tok);
- empty_arg:
- /* handle '()' case */
- if (!args && !sa && tok == ')')
- break;
- if (!sa)
- tcc_error("macro '%s' used with too many args",
- get_tok_str(s->v, 0));
- tok_str_new(&str);
- parlevel = spc = 0;
- /* NOTE: non zero sa->t indicates VA_ARGS */
- while ((parlevel > 0 ||
- (tok != ')' &&
- (tok != ',' || sa->type.t)))) {
- if (tok == TOK_EOF || tok == 0)
- break;
- if (tok == '(')
- parlevel++;
- else if (tok == ')')
- parlevel--;
- if (tok == TOK_LINEFEED)
- tok = ' ';
- if (!check_space(tok, &spc))
- tok_str_add2(&str, tok, &tokc);
- next_argstream(nested_list, NULL);
- }
- if (parlevel)
- expect(")");
- str.len -= spc;
- tok_str_add(&str, -1);
- tok_str_add(&str, 0);
- sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0);
- sa1->d = str.str;
- sa = sa->next;
- if (tok == ')') {
- /* special case for gcc var args: add an empty
- var arg argument if it is omitted */
- if (sa && sa->type.t && gnu_ext)
- goto empty_arg;
- break;
- }
- if (tok != ',')
- expect(",");
- }
- if (sa) {
- tcc_error("macro '%s' used with too few args",
- get_tok_str(s->v, 0));
- }
-
- /* now subst each arg */
- mstr = macro_arg_subst(nested_list, mstr, args);
- /* free memory */
- sa = args;
- while (sa) {
- sa1 = sa->prev;
- tok_str_free_str(sa->d);
- if (sa->next) {
- tok_str_free_str(sa->next->d);
- sym_free(sa->next);
- }
- sym_free(sa);
- sa = sa1;
- }
- parse_flags = saved_parse_flags;
- }
-
- sym_push2(nested_list, s->v, 0, 0);
- parse_flags = saved_parse_flags;
- joined_str = macro_twosharps(mstr);
- macro_subst(tok_str, nested_list, joined_str ? joined_str : mstr);
-
- /* pop nested defined symbol */
- sa1 = *nested_list;
- *nested_list = sa1->prev;
- sym_free(sa1);
- if (joined_str)
- tok_str_free_str(joined_str);
- if (mstr != s->d)
- tok_str_free_str(mstr);
- }
- return 0;
-}
-
-/* do macro substitution of macro_str and add result to
- (tok_str,tok_len). 'nested_list' is the list of all macros we got
- inside to avoid recursing. */
-static void macro_subst(
- TokenString *tok_str,
- Sym **nested_list,
- const int *macro_str
- )
-{
- Sym *s;
- int t, spc, nosubst;
- CValue cval;
-
- spc = nosubst = 0;
-
- while (1) {
- TOK_GET(&t, &macro_str, &cval);
- if (t <= 0)
- break;
-
- if (t >= TOK_IDENT && 0 == nosubst) {
- s = define_find(t);
- if (s == NULL)
- goto no_subst;
-
- /* if nested substitution, do nothing */
- if (sym_find2(*nested_list, t)) {
- /* and mark it as TOK_NOSUBST, so it doesn't get subst'd again */
- tok_str_add2(tok_str, TOK_NOSUBST, NULL);
- goto no_subst;
- }
-
- {
- TokenString *str = tok_str_alloc();
- str->str = (int*)macro_str;
- begin_macro(str, 2);
-
- tok = t;
- macro_subst_tok(tok_str, nested_list, s);
-
- if (macro_stack != str) {
- /* already finished by reading function macro arguments */
- break;
- }
-
- macro_str = macro_ptr;
- end_macro ();
- }
- if (tok_str->len)
- spc = is_space(t = tok_str->str[tok_str->lastlen]);
- } else {
-no_subst:
- if (!check_space(t, &spc))
- tok_str_add2(tok_str, t, &cval);
-
- if (nosubst) {
- if (nosubst > 1 && (spc || (++nosubst == 3 && t == '(')))
- continue;
- nosubst = 0;
- }
- if (t == TOK_NOSUBST)
- nosubst = 1;
- }
- /* GCC supports 'defined' as result of a macro substitution */
- if (t == TOK_DEFINED && pp_expr)
- nosubst = 2;
- }
-}
-
-/* return next token without macro substitution. Can read input from
- macro_ptr buffer */
-static void next_nomacro(void)
-{
- int t;
- if (macro_ptr) {
- redo:
- t = *macro_ptr;
- if (TOK_HAS_VALUE(t)) {
- tok_get(&tok, &macro_ptr, &tokc);
- if (t == TOK_LINENUM) {
- file->line_num = tokc.i;
- goto redo;
- }
- } else {
- macro_ptr++;
- if (t < TOK_IDENT) {
- if (!(parse_flags & PARSE_FLAG_SPACES)
- && (isidnum_table[t - CH_EOF] & IS_SPC))
- goto redo;
- }
- tok = t;
- }
- } else {
- next_nomacro1();
- }
-}
-
-/* return next token with macro substitution */
-ST_FUNC void next(void)
-{
- int t;
- redo:
- next_nomacro();
- t = tok;
- if (macro_ptr) {
- if (!TOK_HAS_VALUE(t)) {
- if (t == TOK_NOSUBST || t == TOK_PLCHLDR) {
- /* discard preprocessor markers */
- goto redo;
- } else if (t == 0) {
- /* end of macro or unget token string */
- end_macro();
- goto redo;
- } else if (t == '\\') {
- if (!(parse_flags & PARSE_FLAG_ACCEPT_STRAYS))
- tcc_error("stray '\\' in program");
- }
- return;
- }
- } else if (t >= TOK_IDENT && (parse_flags & PARSE_FLAG_PREPROCESS)) {
- /* if reading from file, try to substitute macros */
- Sym *s = define_find(t);
- if (s) {
- Sym *nested_list = NULL;
- tokstr_buf.len = 0;
- macro_subst_tok(&tokstr_buf, &nested_list, s);
- tok_str_add(&tokstr_buf, 0);
- begin_macro(&tokstr_buf, 0);
- goto redo;
- }
- return;
- }
- /* convert preprocessor tokens into C tokens */
- if (t == TOK_PPNUM) {
- if (parse_flags & PARSE_FLAG_TOK_NUM)
- parse_number((char *)tokc.str.data);
- } else if (t == TOK_PPSTR) {
- if (parse_flags & PARSE_FLAG_TOK_STR)
- parse_string((char *)tokc.str.data, tokc.str.size - 1);
- }
-}
-
-/* push back current token and set current token to 'last_tok'. Only
- identifier case handled for labels. */
-ST_INLN void unget_tok(int last_tok)
-{
-
- TokenString *str = tok_str_alloc();
- tok_str_add2(str, tok, &tokc);
- tok_str_add(str, 0);
- begin_macro(str, 1);
- tok = last_tok;
-}
-
-/* ------------------------------------------------------------------------- */
-/* init preprocessor */
-
-static const char * const target_os_defs =
-#ifdef TCC_TARGET_PE
- "_WIN32\0"
-# if PTR_SIZE == 8
- "_WIN64\0"
-# endif
-#else
-# if defined TCC_TARGET_MACHO
- "__APPLE__\0"
-# elif TARGETOS_FreeBSD
- "__FreeBSD__ 12\0"
-# elif TARGETOS_FreeBSD_kernel
- "__FreeBSD_kernel__\0"
-# elif TARGETOS_NetBSD
- "__NetBSD__\0"
-# elif TARGETOS_OpenBSD
- "__OpenBSD__\0"
-# else
- "__linux__\0"
- "__linux\0"
-# if TARGETOS_ANDROID
- "__ANDROID__\0"
-# endif
-# endif
- "__unix__\0"
- "__unix\0"
-#endif
- ;
-
-static void putdef(CString *cs, const char *p)
-{
- cstr_printf(cs, "#define %s%s\n", p, &" 1"[!!strchr(p, ' ')*2]);
-}
-
-static void putdefs(CString *cs, const char *p)
-{
- while (*p)
- putdef(cs, p), p = strchr(p, 0) + 1;
-}
-
-static void tcc_predefs(TCCState *s1, CString *cs, int is_asm)
-{
- int a, b, c;
-
- sscanf(TCC_VERSION, "%d.%d.%d", &a, &b, &c);
- cstr_printf(cs, "#define __TINYC__ %d\n", a*10000 + b*100 + c);
-
- putdefs(cs, target_machine_defs);
- putdefs(cs, target_os_defs);
-
-#ifdef TCC_TARGET_ARM
- if (s1->float_abi == ARM_HARD_FLOAT)
- putdef(cs, "__ARM_PCS_VFP");
-#endif
- if (is_asm)
- putdef(cs, "__ASSEMBLER__");
- if (s1->output_type == TCC_OUTPUT_PREPROCESS)
- putdef(cs, "__TCC_PP__");
- if (s1->output_type == TCC_OUTPUT_MEMORY)
- putdef(cs, "__TCC_RUN__");
-#ifdef CONFIG_TCC_BACKTRACE
- if (s1->do_backtrace)
- putdef(cs, "__TCC_BACKTRACE__");
-#endif
-#ifdef CONFIG_TCC_BCHECK
- if (s1->do_bounds_check)
- putdef(cs, "__TCC_BCHECK__");
-#endif
- if (s1->char_is_unsigned)
- putdef(cs, "__CHAR_UNSIGNED__");
- if (s1->optimize > 0)
- putdef(cs, "__OPTIMIZE__");
- if (s1->option_pthread)
- putdef(cs, "_REENTRANT");
- if (s1->leading_underscore)
- putdef(cs, "__leading_underscore");
- cstr_printf(cs, "#define __SIZEOF_POINTER__ %d\n", PTR_SIZE);
- cstr_printf(cs, "#define __SIZEOF_LONG__ %d\n", LONG_SIZE);
- if (!is_asm) {
- putdef(cs, "__STDC__");
- cstr_printf(cs, "#define __STDC_VERSION__ %dL\n", s1->cversion);
- }
- cstr_printf(cs, "#define __BASE_FILE__ \"%s\"\n", file->filename);
-}
-
-ST_FUNC void preprocess_start(TCCState *s1, int filetype)
-{
- int is_asm = !!(filetype & (AFF_TYPE_ASM|AFF_TYPE_ASMPP));
-
- tccpp_new(s1);
-
- s1->include_stack_ptr = s1->include_stack;
- s1->ifdef_stack_ptr = s1->ifdef_stack;
- file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
- pp_expr = 0;
- pp_counter = 0;
- pp_debug_tok = pp_debug_symv = 0;
- pp_once++;
- s1->pack_stack[0] = 0;
- s1->pack_stack_ptr = s1->pack_stack;
-
- set_idnum('$', !is_asm && s1->dollars_in_identifiers ? IS_ID : 0);
- set_idnum('.', is_asm ? IS_ID : 0);
-
- if (!(filetype & AFF_TYPE_ASM)) {
- CString cstr;
- cstr_new(&cstr);
- tcc_predefs(s1, &cstr, is_asm);
- if (s1->cmdline_defs.size)
- cstr_cat(&cstr, s1->cmdline_defs.data, s1->cmdline_defs.size);
- if (s1->cmdline_incl.size)
- cstr_cat(&cstr, s1->cmdline_incl.data, s1->cmdline_incl.size);
- //printf("%s\n", (char*)cstr.data);
- *s1->include_stack_ptr++ = file;
- tcc_open_bf(s1, "<command line>", cstr.size);
- memcpy(file->buffer, cstr.data, cstr.size);
- cstr_free(&cstr);
- }
-
- parse_flags = is_asm ? PARSE_FLAG_ASM_FILE : 0;
- tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
-}
-
-/* cleanup from error/setjmp */
-ST_FUNC void preprocess_end(TCCState *s1)
-{
- while (macro_stack)
- end_macro();
- macro_ptr = NULL;
- while (file)
- tcc_close();
- tccpp_delete(s1);
-}
-
-ST_FUNC int set_idnum(int c, int val)
-{
- int prev = isidnum_table[c - CH_EOF];
- isidnum_table[c - CH_EOF] = val;
- return prev;
-}
-
-ST_FUNC void tccpp_new(TCCState *s)
-{
- int i, c;
- const char *p, *r;
-
- /* init isid table */
- for(i = CH_EOF; i<128; i++)
- set_idnum(i,
- is_space(i) ? IS_SPC
- : isid(i) ? IS_ID
- : isnum(i) ? IS_NUM
- : 0);
-
- for(i = 128; i<256; i++)
- set_idnum(i, IS_ID);
-
- /* init allocators */
- tal_new(&toksym_alloc, TOKSYM_TAL_LIMIT, TOKSYM_TAL_SIZE);
- tal_new(&tokstr_alloc, TOKSTR_TAL_LIMIT, TOKSTR_TAL_SIZE);
-
- memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
- memset(s->cached_includes_hash, 0, sizeof s->cached_includes_hash);
-
- cstr_new(&tokcstr);
- cstr_new(&cstr_buf);
- cstr_realloc(&cstr_buf, STRING_MAX_SIZE);
- tok_str_new(&tokstr_buf);
- tok_str_realloc(&tokstr_buf, TOKSTR_MAX_SIZE);
-
- tok_ident = TOK_IDENT;
- p = tcc_keywords;
- while (*p) {
- r = p;
- for(;;) {
- c = *r++;
- if (c == '\0')
- break;
- }
- tok_alloc(p, r - p - 1);
- p = r;
- }
-
- /* we add dummy defines for some special macros to speed up tests
- and to have working defined() */
- define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
- define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
- define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
- define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
- define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL);
-}
-
-ST_FUNC void tccpp_delete(TCCState *s)
-{
- int i, n;
-
- dynarray_reset(&s->cached_includes, &s->nb_cached_includes);
-
- /* free tokens */
- n = tok_ident - TOK_IDENT;
- if (n > total_idents)
- total_idents = n;
- for(i = 0; i < n; i++)
- tal_free(toksym_alloc, table_ident[i]);
- tcc_free(table_ident);
- table_ident = NULL;
-
- /* free static buffers */
- cstr_free(&tokcstr);
- cstr_free(&cstr_buf);
- tok_str_free_str(tokstr_buf.str);
-
- /* free allocators */
- tal_delete(toksym_alloc);
- toksym_alloc = NULL;
- tal_delete(tokstr_alloc);
- tokstr_alloc = NULL;
-}
-
-/* ------------------------------------------------------------------------- */
-/* tcc -E [-P[1]] [-dD} support */
-
-static void tok_print(const char *msg, const int *str)
-{
- FILE *fp;
- int t, s = 0;
- CValue cval;
-
- fp = tcc_state->ppfp;
- fprintf(fp, "%s", msg);
- while (str) {
- TOK_GET(&t, &str, &cval);
- if (!t)
- break;
- fprintf(fp, &" %s"[s], get_tok_str(t, &cval)), s = 1;
- }
- fprintf(fp, "\n");
-}
-
-static void pp_line(TCCState *s1, BufferedFile *f, int level)
-{
- int d = f->line_num - f->line_ref;
-
- if (s1->dflag & 4)
- return;
-
- if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_NONE) {
- ;
- } else if (level == 0 && f->line_ref && d < 8) {
- while (d > 0)
- fputs("\n", s1->ppfp), --d;
- } else if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_STD) {
- fprintf(s1->ppfp, "#line %d \"%s\"\n", f->line_num, f->filename);
- } else {
- fprintf(s1->ppfp, "# %d \"%s\"%s\n", f->line_num, f->filename,
- level > 0 ? " 1" : level < 0 ? " 2" : "");
- }
- f->line_ref = f->line_num;
-}
-
-static void define_print(TCCState *s1, int v)
-{
- FILE *fp;
- Sym *s;
-
- s = define_find(v);
- if (NULL == s || NULL == s->d)
- return;
-
- fp = s1->ppfp;
- fprintf(fp, "#define %s", get_tok_str(v, NULL));
- if (s->type.t == MACRO_FUNC) {
- Sym *a = s->next;
- fprintf(fp,"(");
- if (a)
- for (;;) {
- fprintf(fp,"%s", get_tok_str(a->v & ~SYM_FIELD, NULL));
- if (!(a = a->next))
- break;
- fprintf(fp,",");
- }
- fprintf(fp,")");
- }
- tok_print("", s->d);
-}
-
-static void pp_debug_defines(TCCState *s1)
-{
- int v, t;
- const char *vs;
- FILE *fp;
-
- t = pp_debug_tok;
- if (t == 0)
- return;
-
- file->line_num--;
- pp_line(s1, file, 0);
- file->line_ref = ++file->line_num;
-
- fp = s1->ppfp;
- v = pp_debug_symv;
- vs = get_tok_str(v, NULL);
- if (t == TOK_DEFINE) {
- define_print(s1, v);
- } else if (t == TOK_UNDEF) {
- fprintf(fp, "#undef %s\n", vs);
- } else if (t == TOK_push_macro) {
- fprintf(fp, "#pragma push_macro(\"%s\")\n", vs);
- } else if (t == TOK_pop_macro) {
- fprintf(fp, "#pragma pop_macro(\"%s\")\n", vs);
- }
- pp_debug_tok = 0;
-}
-
-static void pp_debug_builtins(TCCState *s1)
-{
- int v;
- for (v = TOK_IDENT; v < tok_ident; ++v)
- define_print(s1, v);
-}
-
-/* Add a space between tokens a and b to avoid unwanted textual pasting */
-static int pp_need_space(int a, int b)
-{
- return 'E' == a ? '+' == b || '-' == b
- : '+' == a ? TOK_INC == b || '+' == b
- : '-' == a ? TOK_DEC == b || '-' == b
- : a >= TOK_IDENT ? b >= TOK_IDENT
- : a == TOK_PPNUM ? b >= TOK_IDENT
- : 0;
-}
-
-/* maybe hex like 0x1e */
-static int pp_check_he0xE(int t, const char *p)
-{
- if (t == TOK_PPNUM && toup(strchr(p, 0)[-1]) == 'E')
- return 'E';
- return t;
-}
-
-/* Preprocess the current file */
-ST_FUNC int tcc_preprocess(TCCState *s1)
-{
- BufferedFile **iptr;
- int token_seen, spcs, level;
- const char *p;
- char white[400];
-
- parse_flags = PARSE_FLAG_PREPROCESS
- | (parse_flags & PARSE_FLAG_ASM_FILE)
- | PARSE_FLAG_LINEFEED
- | PARSE_FLAG_SPACES
- | PARSE_FLAG_ACCEPT_STRAYS
- ;
- /* Credits to Fabrice Bellard's initial revision to demonstrate its
- capability to compile and run itself, provided all numbers are
- given as decimals. tcc -E -P10 will do. */
- if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_P10)
- parse_flags |= PARSE_FLAG_TOK_NUM, s1->Pflag = 1;
-
- if (s1->do_bench) {
- /* for PP benchmarks */
- do next(); while (tok != TOK_EOF);
- return 0;
- }
-
- if (s1->dflag & 1) {
- pp_debug_builtins(s1);
- s1->dflag &= ~1;
- }
-
- token_seen = TOK_LINEFEED, spcs = 0, level = 0;
- if (file->prev)
- pp_line(s1, file->prev, level++);
- pp_line(s1, file, level);
- for (;;) {
- iptr = s1->include_stack_ptr;
- next();
- if (tok == TOK_EOF)
- break;
-
- level = s1->include_stack_ptr - iptr;
- if (level) {
- if (level > 0)
- pp_line(s1, *iptr, 0);
- pp_line(s1, file, level);
- }
- if (s1->dflag & 7) {
- pp_debug_defines(s1);
- if (s1->dflag & 4)
- continue;
- }
-
- if (is_space(tok)) {
- if (spcs < sizeof white - 1)
- white[spcs++] = tok;
- continue;
- } else if (tok == TOK_LINEFEED) {
- spcs = 0;
- if (token_seen == TOK_LINEFEED)
- continue;
- ++file->line_ref;
- } else if (token_seen == TOK_LINEFEED) {
- pp_line(s1, file, 0);
- } else if (spcs == 0 && pp_need_space(token_seen, tok)) {
- white[spcs++] = ' ';
- }
-
- white[spcs] = 0, fputs(white, s1->ppfp), spcs = 0;
- fputs(p = get_tok_str(tok, &tokc), s1->ppfp);
- token_seen = pp_check_he0xE(tok, p);
- }
- return 0;
-}
-
-/* ------------------------------------------------------------------------- */
diff --git a/tinycc/tccrun.c b/tinycc/tccrun.c
deleted file mode 100644
index d373abc..0000000
--- a/tinycc/tccrun.c
+++ /dev/null
@@ -1,1461 +0,0 @@
-/*
- * TCC - Tiny C Compiler - Support for -run switch
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "tcc.h"
-
-/* only native compiler supports -run */
-#ifdef TCC_IS_NATIVE
-
-#ifdef CONFIG_TCC_BACKTRACE
-typedef struct rt_context
-{
- /* --> tccelf.c:tcc_add_btstub wants those below in that order: */
- union {
- struct {
- Stab_Sym *stab_sym, *stab_sym_end;
- char *stab_str;
- };
- struct {
- unsigned char *dwarf_line, *dwarf_line_end, *dwarf_line_str;
- };
- };
- addr_t dwarf;
- ElfW(Sym) *esym_start, *esym_end;
- char *elf_str;
- addr_t prog_base;
- void *bounds_start;
- struct rt_context *next;
- /* <-- */
- int num_callers;
- addr_t ip, fp, sp;
- void *top_func;
- jmp_buf jmp_buf;
- char do_jmp;
-} rt_context;
-
-static rt_context g_rtctxt;
-static void set_exception_handler(void);
-static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap);
-static void rt_exit(int code);
-#endif /* CONFIG_TCC_BACKTRACE */
-
-/* defined when included from lib/bt-exe.c */
-#ifndef CONFIG_TCC_BACKTRACE_ONLY
-
-#ifndef _WIN32
-# include <sys/mman.h>
-#endif
-
-static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length);
-static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff);
-
-#ifdef _WIN64
-static void *win64_add_function_table(TCCState *s1);
-static void win64_del_function_table(void *);
-#endif
-
-/* ------------------------------------------------------------- */
-/* Do all relocations (needed before using tcc_get_symbol())
- Returns -1 on error. */
-
-LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr)
-{
- int size;
- addr_t ptr_diff = 0;
-
- if (TCC_RELOCATE_AUTO != ptr)
- return tcc_relocate_ex(s1, ptr, 0);
-
- size = tcc_relocate_ex(s1, NULL, 0);
- if (size < 0)
- return -1;
-
-#ifdef HAVE_SELINUX
-{
- /* Using mmap instead of malloc */
- void *prx;
- char tmpfname[] = "/tmp/.tccrunXXXXXX";
- int fd = mkstemp(tmpfname);
- unlink(tmpfname);
- ftruncate(fd, size);
-
- size = (size + (PAGESIZE-1)) & ~(PAGESIZE-1);
- ptr = mmap(NULL, size * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- /* mmap RX memory at a fixed distance */
- prx = mmap((char*)ptr + size, size, PROT_READ|PROT_EXEC, MAP_SHARED|MAP_FIXED, fd, 0);
- close(fd);
- if (ptr == MAP_FAILED || prx == MAP_FAILED)
- return tcc_error_noabort("tccrun: could not map memory");
- ptr_diff = (char*)prx - (char*)ptr;
- //printf("map %p %p %p\n", ptr, prx, (void*)ptr_diff);
-}
-#else
- ptr = tcc_malloc(size);
-#endif
- if (tcc_relocate_ex(s1, ptr, ptr_diff))
- return -1;
- dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, (void*)(addr_t)size);
- dynarray_add(&s1->runtime_mem, &s1->nb_runtime_mem, ptr);
- return 0;
-}
-
-ST_FUNC void tcc_run_free(TCCState *s1)
-{
- int i;
-
- for (i = 0; i < s1->nb_runtime_mem; i += 2) {
- unsigned size = (unsigned)(addr_t)s1->runtime_mem[i];
- void *ptr = s1->runtime_mem[i+1];
-#ifdef HAVE_SELINUX
- munmap(ptr, size * 2);
-#else
- /* unprotect memory to make it usable for malloc again */
- set_pages_executable(s1, 2, ptr, size);
-#ifdef _WIN64
- win64_del_function_table(*(void**)ptr);
-#endif
- tcc_free(ptr);
-#endif
- }
- tcc_free(s1->runtime_mem);
-}
-
-static void run_cdtors(TCCState *s1, const char *start, const char *end,
- int argc, char **argv, char **envp)
-{
- void **a = (void **)get_sym_addr(s1, start, 0, 0);
- void **b = (void **)get_sym_addr(s1, end, 0, 0);
- while (a != b)
- ((void(*)(int, char **, char **))*a++)(argc, argv, envp);
-}
-
-#define NR_AT_EXIT 32
-
-static struct exit_context {
- int exit_called;
- int nr_exit;
- void (*exitfunc[NR_AT_EXIT])(int, void *);
- void *exitarg[NR_AT_EXIT];
-#ifndef CONFIG_TCC_BACKTRACE
- jmp_buf run_jmp_buf;
-#endif
-} g_exit_context;
-
-static void init_exit(void)
-{
- struct exit_context *e = &g_exit_context;
-
- e->exit_called = 0;
- e->nr_exit = 0;
-}
-
-static void call_exit(int ret)
-{
- struct exit_context *e = &g_exit_context;
-
- while (e->nr_exit) {
- e->nr_exit--;
- e->exitfunc[e->nr_exit](ret, e->exitarg[e->nr_exit]);
- }
-}
-
-static int rt_atexit(void (*function)(void))
-{
- struct exit_context *e = &g_exit_context;
-
- if (e->nr_exit < NR_AT_EXIT) {
- e->exitfunc[e->nr_exit] = (void (*)(int, void *))function;
- e->exitarg[e->nr_exit++] = NULL;
- return 0;
- }
- return 1;
-}
-
-static int rt_on_exit(void (*function)(int, void *), void *arg)
-{
- struct exit_context *e = &g_exit_context;
-
- if (e->nr_exit < NR_AT_EXIT) {
- e->exitfunc[e->nr_exit] = function;
- e->exitarg[e->nr_exit++] = arg;
- return 0;
- }
- return 1;
-}
-
-static void run_exit(int code)
-{
- struct exit_context *e = &g_exit_context;
-
- e->exit_called = 1;
-#ifdef CONFIG_TCC_BACKTRACE
- longjmp((&g_rtctxt)->jmp_buf, code ? code : 256);
-#else
- longjmp(e->run_jmp_buf, code ? code : 256);
-#endif
-}
-
-/* launch the compiled program with the given arguments */
-LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv)
-{
- int (*prog_main)(int, char **, char **), ret;
-#ifdef CONFIG_TCC_BACKTRACE
- rt_context *rc = &g_rtctxt;
-#endif
-
-#if defined(__APPLE__) || defined(__FreeBSD__)
- char **envp = NULL;
-#elif defined(__OpenBSD__) || defined(__NetBSD__)
- extern char **environ;
- char **envp = environ;
-#else
- char **envp = environ;
-#endif
-
- s1->runtime_main = s1->nostdlib ? "_start" : "main";
- if ((s1->dflag & 16) && (addr_t)-1 == get_sym_addr(s1, s1->runtime_main, 0, 1))
- return 0;
- tcc_add_symbol(s1, "exit", run_exit);
- tcc_add_symbol(s1, "atexit", rt_atexit);
- tcc_add_symbol(s1, "on_exit", rt_on_exit);
- if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0)
- return -1;
- prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1);
- if ((addr_t)-1 == (addr_t)prog_main)
- return -1;
-
-#ifdef CONFIG_TCC_BACKTRACE
- memset(rc, 0, sizeof *rc);
- if (s1->do_debug) {
- void *p;
- if (s1->dwarf) {
- rc->dwarf_line = dwarf_line_section->data;
- rc->dwarf_line_end = dwarf_line_section->data + dwarf_line_section->data_offset;
- if (dwarf_line_str_section)
- rc->dwarf_line_str = dwarf_line_str_section->data;
- }
- else
- {
- rc->stab_sym = (Stab_Sym *)stab_section->data;
- rc->stab_sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
- rc->stab_str = (char *)stab_section->link->data;
- }
- rc->dwarf = s1->dwarf;
- rc->esym_start = (ElfW(Sym) *)(symtab_section->data);
- rc->esym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
- rc->elf_str = (char *)symtab_section->link->data;
-#if PTR_SIZE == 8
- rc->prog_base = text_section->sh_addr & 0xffffffff00000000ULL;
-#if defined TCC_TARGET_MACHO
- if (s1->dwarf)
- rc->prog_base = (addr_t) -1;
-#else
-#endif
-#endif
- rc->top_func = tcc_get_symbol(s1, "main");
- rc->num_callers = s1->rt_num_callers;
- rc->do_jmp = 1;
- if ((p = tcc_get_symbol(s1, "__rt_error")))
- *(void**)p = _rt_error;
-#ifdef CONFIG_TCC_BCHECK
- if (s1->do_bounds_check) {
- rc->bounds_start = (void*)bounds_section->sh_addr;
- if ((p = tcc_get_symbol(s1, "__bound_init")))
- ((void(*)(void*,int))p)(rc->bounds_start, 1);
- }
-#endif
- set_exception_handler();
- }
-#endif
-
- errno = 0; /* clean errno value */
- fflush(stdout);
- fflush(stderr);
- init_exit();
- /* These aren't C symbols, so don't need leading underscore handling. */
- run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp);
-#ifdef CONFIG_TCC_BACKTRACE
- if (!(ret = setjmp(rc->jmp_buf)))
-#else
- if (!(ret = setjmp((&g_exit_context)->run_jmp_buf)))
-#endif
- {
- ret = prog_main(argc, argv, envp);
- }
- run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL);
- call_exit(ret);
- if ((s1->dflag & 16) && ret)
- fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp);
- if ((s1->dflag & 16) == 0 && (&g_exit_context)->exit_called)
- exit(ret);
- return ret;
-}
-
-#define DEBUG_RUNMEN 0
-
-/* enable rx/ro/rw permissions */
-#define CONFIG_RUNMEM_RO 1
-
-#if CONFIG_RUNMEM_RO
-# define PAGE_ALIGN PAGESIZE
-#elif defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
-/* To avoid that x86 processors would reload cached instructions
- each time when data is written in the near, we need to make
- sure that code and data do not share the same 64 byte unit */
-# define PAGE_ALIGN 64
-#else
-# define PAGE_ALIGN 1
-#endif
-
-/* relocate code. Return -1 on error, required size if ptr is NULL,
- otherwise copy code into buffer passed by the caller */
-static int tcc_relocate_ex(TCCState *s1, void *ptr, addr_t ptr_diff)
-{
- Section *s;
- unsigned offset, length, align, max_align, i, k, f;
- unsigned n, copy;
- addr_t mem, addr;
-
- if (NULL == ptr) {
- s1->nb_errors = 0;
-#ifdef TCC_TARGET_PE
- pe_output_file(s1, NULL);
-#else
- tcc_add_runtime(s1);
- resolve_common_syms(s1);
- build_got_entries(s1, 0);
-#endif
- if (s1->nb_errors)
- return -1;
- }
-
- offset = max_align = 0, mem = (addr_t)ptr;
-#ifdef _WIN64
- offset += sizeof (void*); /* space for function_table pointer */
-#endif
- copy = 0;
-redo:
- for (k = 0; k < 3; ++k) { /* 0:rx, 1:ro, 2:rw sections */
- n = 0; addr = 0;
- for(i = 1; i < s1->nb_sections; i++) {
- static const char shf[] = {
- SHF_ALLOC|SHF_EXECINSTR, SHF_ALLOC, SHF_ALLOC|SHF_WRITE
- };
- s = s1->sections[i];
- if (shf[k] != (s->sh_flags & (SHF_ALLOC|SHF_WRITE|SHF_EXECINSTR)))
- continue;
- length = s->data_offset;
- if (copy) {
- if (addr == 0)
- addr = s->sh_addr;
- n = (s->sh_addr - addr) + length;
- ptr = (void*)s->sh_addr;
- if (k == 0)
- ptr = (void*)(s->sh_addr - ptr_diff);
- if (NULL == s->data || s->sh_type == SHT_NOBITS)
- memset(ptr, 0, length);
- else
- memcpy(ptr, s->data, length);
-#ifdef _WIN64
- if (s == s1->uw_pdata)
- *(void**)mem = win64_add_function_table(s1);
-#endif
- if (s->data) {
- tcc_free(s->data);
- s->data = NULL;
- s->data_allocated = 0;
- }
- s->data_offset = 0;
- continue;
- }
- align = s->sh_addralign - 1;
- if (++n == 1 && align < (PAGE_ALIGN - 1))
- align = (PAGE_ALIGN - 1);
- if (max_align < align)
- max_align = align;
- addr = k ? mem : mem + ptr_diff;
- offset += -(addr + offset) & align;
- s->sh_addr = mem ? addr + offset : 0;
- offset += length;
-#if DEBUG_RUNMEN
- if (mem)
- printf("%d: %-16s %p len %04x align %04x\n",
- k, s->name, (void*)s->sh_addr, length, align + 1);
-#endif
- }
- if (copy) { /* set permissions */
- if (k == 0 && ptr_diff)
- continue; /* not with HAVE_SELINUX */
- f = k;
-#if !CONFIG_RUNMEM_RO
- if (f != 0)
- continue;
- f = 3; /* change only SHF_EXECINSTR to rwx */
-#endif
-#if DEBUG_RUNMEN
- printf("protect %d %p %04x\n", f, (void*)addr, n);
-#endif
- if (n) {
- if (set_pages_executable(s1, f, (void*)addr, n))
- return -1;
- }
- }
- }
-
- if (copy)
- return 0;
-
- /* relocate symbols */
- relocate_syms(s1, s1->symtab, !(s1->nostdlib));
- if (s1->nb_errors)
- return -1;
- if (0 == mem)
- return offset + max_align;
-
-#ifdef TCC_TARGET_PE
- s1->pe_imagebase = mem;
-#endif
-
- /* relocate sections */
-#ifndef TCC_TARGET_PE
- relocate_plt(s1);
-#endif
- relocate_sections(s1);
- copy = 1;
- goto redo;
-}
-
-/* ------------------------------------------------------------- */
-/* allow to run code in memory */
-
-static int set_pages_executable(TCCState *s1, int mode, void *ptr, unsigned long length)
-{
-#ifdef _WIN32
- static const unsigned char protect[] = {
- PAGE_EXECUTE_READ,
- PAGE_READONLY,
- PAGE_READWRITE,
- PAGE_EXECUTE_READWRITE
- };
- DWORD old;
- if (!VirtualProtect(ptr, length, protect[mode], &old))
- return -1;
- return 0;
-#else
- static const unsigned char protect[] = {
- PROT_READ | PROT_EXEC,
- PROT_READ,
- PROT_READ | PROT_WRITE,
- PROT_READ | PROT_WRITE | PROT_EXEC
- };
- addr_t start, end;
- start = (addr_t)ptr & ~(PAGESIZE - 1);
- end = (addr_t)ptr + length;
- end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
- if (mprotect((void *)start, end - start, protect[mode]))
- return tcc_error_noabort("mprotect failed: did you mean to configure --with-selinux?");
-/* XXX: BSD sometimes dump core with bad system call */
-# if (defined TCC_TARGET_ARM && !TARGETOS_BSD) || defined TCC_TARGET_ARM64
- if (mode == 0 || mode == 3) {
- void __clear_cache(void *beginning, void *end);
- __clear_cache(ptr, (char *)ptr + length);
- }
-# endif
- return 0;
-#endif
-}
-
-#ifdef _WIN64
-static void *win64_add_function_table(TCCState *s1)
-{
- void *p = NULL;
- if (s1->uw_pdata) {
- p = (void*)s1->uw_pdata->sh_addr;
- RtlAddFunctionTable(
- (RUNTIME_FUNCTION*)p,
- s1->uw_pdata->data_offset / sizeof (RUNTIME_FUNCTION),
- s1->pe_imagebase
- );
- s1->uw_pdata = NULL;
- }
- return p;
-}
-
-static void win64_del_function_table(void *p)
-{
- if (p) {
- RtlDeleteFunctionTable((RUNTIME_FUNCTION*)p);
- }
-}
-#endif
-#endif //ndef CONFIG_TCC_BACKTRACE_ONLY
-/* ------------------------------------------------------------- */
-#ifdef CONFIG_TCC_BACKTRACE
-
-static int rt_vprintf(const char *fmt, va_list ap)
-{
- int ret = vfprintf(stderr, fmt, ap);
- fflush(stderr);
- return ret;
-}
-
-static int rt_printf(const char *fmt, ...)
-{
- va_list ap;
- int r;
- va_start(ap, fmt);
- r = rt_vprintf(fmt, ap);
- va_end(ap);
- return r;
-}
-
-static char *rt_elfsym(rt_context *rc, addr_t wanted_pc, addr_t *func_addr)
-{
- ElfW(Sym) *esym;
- for (esym = rc->esym_start + 1; esym < rc->esym_end; ++esym) {
- int type = ELFW(ST_TYPE)(esym->st_info);
- if ((type == STT_FUNC || type == STT_GNU_IFUNC)
- && wanted_pc >= esym->st_value
- && wanted_pc < esym->st_value + esym->st_size) {
- *func_addr = esym->st_value;
- return rc->elf_str + esym->st_name;
- }
- }
- return NULL;
-}
-
-
-/* print the position in the source file of PC value 'pc' by reading
- the stabs debug information */
-static addr_t rt_printline (rt_context *rc, addr_t wanted_pc,
- const char *msg, const char *skip)
-{
- char func_name[128];
- addr_t func_addr, last_pc, pc;
- const char *incl_files[INCLUDE_STACK_SIZE];
- int incl_index, last_incl_index, len, last_line_num, i;
- const char *str, *p;
- Stab_Sym *sym;
-
-next:
- func_name[0] = '\0';
- func_addr = 0;
- incl_index = 0;
- last_pc = (addr_t)-1;
- last_line_num = 1;
- last_incl_index = 0;
-
- for (sym = rc->stab_sym + 1; sym < rc->stab_sym_end; ++sym) {
- str = rc->stab_str + sym->n_strx;
- pc = sym->n_value;
-
- switch(sym->n_type) {
- case N_SLINE:
- if (func_addr)
- goto rel_pc;
- case N_SO:
- case N_SOL:
- goto abs_pc;
- case N_FUN:
- if (sym->n_strx == 0) /* end of function */
- goto rel_pc;
- abs_pc:
-#if PTR_SIZE == 8
- /* Stab_Sym.n_value is only 32bits */
- pc += rc->prog_base;
-#endif
- goto check_pc;
- rel_pc:
- pc += func_addr;
- check_pc:
- if (pc >= wanted_pc && wanted_pc >= last_pc)
- goto found;
- break;
- }
-
- switch(sym->n_type) {
- /* function start or end */
- case N_FUN:
- if (sym->n_strx == 0)
- goto reset_func;
- p = strchr(str, ':');
- if (0 == p || (len = p - str + 1, len > sizeof func_name))
- len = sizeof func_name;
- pstrcpy(func_name, len, str);
- func_addr = pc;
- break;
- /* line number info */
- case N_SLINE:
- last_pc = pc;
- last_line_num = sym->n_desc;
- last_incl_index = incl_index;
- break;
- /* include files */
- case N_BINCL:
- if (incl_index < INCLUDE_STACK_SIZE)
- incl_files[incl_index++] = str;
- break;
- case N_EINCL:
- if (incl_index > 1)
- incl_index--;
- break;
- /* start/end of translation unit */
- case N_SO:
- incl_index = 0;
- if (sym->n_strx) {
- /* do not add path */
- len = strlen(str);
- if (len > 0 && str[len - 1] != '/')
- incl_files[incl_index++] = str;
- }
- reset_func:
- func_name[0] = '\0';
- func_addr = 0;
- last_pc = (addr_t)-1;
- break;
- /* alternative file name (from #line or #include directives) */
- case N_SOL:
- if (incl_index)
- incl_files[incl_index-1] = str;
- break;
- }
- }
-
- func_name[0] = '\0';
- func_addr = 0;
- last_incl_index = 0;
- /* we try symtab symbols (no line number info) */
- p = rt_elfsym(rc, wanted_pc, &func_addr);
- if (p) {
- pstrcpy(func_name, sizeof func_name, p);
- goto found;
- }
- if ((rc = rc->next))
- goto next;
-found:
- i = last_incl_index;
- if (i > 0) {
- str = incl_files[--i];
- if (skip[0] && strstr(str, skip))
- return (addr_t)-1;
- rt_printf("%s:%d: ", str, last_line_num);
- } else
- rt_printf("%08llx : ", (long long)wanted_pc);
- rt_printf("%s %s", msg, func_name[0] ? func_name : "???");
-#if 0
- if (--i >= 0) {
- rt_printf(" (included from ");
- for (;;) {
- rt_printf("%s", incl_files[i]);
- if (--i < 0)
- break;
- rt_printf(", ");
- }
- rt_printf(")");
- }
-#endif
- return func_addr;
-}
-
-/* ------------------------------------------------------------- */
-/* rt_printline - dwarf version */
-
-#define MAX_128 ((8 * sizeof (long long) + 6) / 7)
-
-#define DIR_TABLE_SIZE (64)
-#define FILE_TABLE_SIZE (512)
-
-#define dwarf_read_1(ln,end) \
- ((ln) < (end) ? *(ln)++ : 0)
-#define dwarf_read_2(ln,end) \
- ((ln) + 2 < (end) ? (ln) += 2, read16le((ln) - 2) : 0)
-#define dwarf_read_4(ln,end) \
- ((ln) + 4 < (end) ? (ln) += 4, read32le((ln) - 4) : 0)
-#define dwarf_read_8(ln,end) \
- ((ln) + 8 < (end) ? (ln) += 8, read64le((ln) - 8) : 0)
-#define dwarf_ignore_type(ln, end) /* timestamp/size/md5/... */ \
- switch (entry_format[j].form) { \
- case DW_FORM_data1: (ln) += 1; break; \
- case DW_FORM_data2: (ln) += 2; break; \
- case DW_FORM_data4: (ln) += 3; break; \
- case DW_FORM_data8: (ln) += 8; break; \
- case DW_FORM_data16: (ln) += 16; break; \
- case DW_FORM_udata: dwarf_read_uleb128(&(ln), (end)); break; \
- default: goto next_line; \
- }
-
-static unsigned long long
-dwarf_read_uleb128(unsigned char **ln, unsigned char *end)
-{
- unsigned char *cp = *ln;
- unsigned long long retval = 0;
- int i;
-
- for (i = 0; i < MAX_128; i++) {
- unsigned long long byte = dwarf_read_1(cp, end);
-
- retval |= (byte & 0x7f) << (i * 7);
- if ((byte & 0x80) == 0)
- break;
- }
- *ln = cp;
- return retval;
-}
-
-static long long
-dwarf_read_sleb128(unsigned char **ln, unsigned char *end)
-{
- unsigned char *cp = *ln;
- long long retval = 0;
- int i;
-
- for (i = 0; i < MAX_128; i++) {
- unsigned long long byte = dwarf_read_1(cp, end);
-
- retval |= (byte & 0x7f) << (i * 7);
- if ((byte & 0x80) == 0) {
- if ((byte & 0x40) && (i + 1) * 7 < 64)
- retval |= -1LL << ((i + 1) * 7);
- break;
- }
- }
- *ln = cp;
- return retval;
-}
-
-static addr_t rt_printline_dwarf (rt_context *rc, addr_t wanted_pc,
- const char *msg, const char *skip)
-{
- unsigned char *ln;
- unsigned char *cp;
- unsigned char *end;
- unsigned char *opcode_length;
- unsigned long long size;
- unsigned int length;
- unsigned char version;
- unsigned int min_insn_length;
- unsigned int max_ops_per_insn;
- int line_base;
- unsigned int line_range;
- unsigned int opcode_base;
- unsigned int opindex;
- unsigned int col;
- unsigned int i;
- unsigned int j;
- unsigned int len;
- unsigned long long value;
- struct {
- unsigned int type;
- unsigned int form;
- } entry_format[256];
- unsigned int dir_size;
-#if 0
- char *dirs[DIR_TABLE_SIZE];
-#endif
- unsigned int filename_size;
- struct dwarf_filename_struct {
- unsigned int dir_entry;
- char *name;
- } filename_table[FILE_TABLE_SIZE];
- addr_t last_pc;
- addr_t pc;
- addr_t func_addr;
- int line;
- char *filename;
- char *function;
-
-next:
- ln = rc->dwarf_line;
- while (ln < rc->dwarf_line_end) {
- dir_size = 0;
- filename_size = 0;
- last_pc = 0;
- pc = 0;
- func_addr = 0;
- line = 1;
- filename = NULL;
- function = NULL;
- length = 4;
- size = dwarf_read_4(ln, rc->dwarf_line_end);
- if (size == 0xffffffffu) // dwarf 64
- length = 8, size = dwarf_read_8(ln, rc->dwarf_line_end);
- end = ln + size;
- if (end < ln || end > rc->dwarf_line_end)
- break;
- version = dwarf_read_2(ln, end);
- if (version >= 5)
- ln += length + 2; // address size, segment selector, prologue Length
- else
- ln += length; // prologue Length
- min_insn_length = dwarf_read_1(ln, end);
- if (version >= 4)
- max_ops_per_insn = dwarf_read_1(ln, end);
- else
- max_ops_per_insn = 1;
- ln++; // Initial value of 'is_stmt'
- line_base = dwarf_read_1(ln, end);
- line_base |= line_base >= 0x80 ? ~0xff : 0;
- line_range = dwarf_read_1(ln, end);
- opcode_base = dwarf_read_1(ln, end);
- opcode_length = ln;
- ln += opcode_base - 1;
- opindex = 0;
- if (version >= 5) {
- col = dwarf_read_1(ln, end);
- for (i = 0; i < col; i++) {
- entry_format[i].type = dwarf_read_uleb128(&ln, end);
- entry_format[i].form = dwarf_read_uleb128(&ln, end);
- }
- dir_size = dwarf_read_uleb128(&ln, end);
- for (i = 0; i < dir_size; i++) {
- for (j = 0; j < col; j++) {
- if (entry_format[j].type == DW_LNCT_path) {
- if (entry_format[j].form != DW_FORM_line_strp)
- goto next_line;
-#if 0
- value = length == 4 ? dwarf_read_4(ln, end)
- : dwarf_read_8(ln, end);
- if (i < DIR_TABLE_SIZE)
- dirs[i] = (char *)rc->dwarf_line_str + value;
-#else
- length == 4 ? dwarf_read_4(ln, end)
- : dwarf_read_8(ln, end);
-#endif
- }
- else
- dwarf_ignore_type(ln, end);
- }
- }
- col = dwarf_read_1(ln, end);
- for (i = 0; i < col; i++) {
- entry_format[i].type = dwarf_read_uleb128(&ln, end);
- entry_format[i].form = dwarf_read_uleb128(&ln, end);
- }
- filename_size = dwarf_read_uleb128(&ln, end);
- for (i = 0; i < filename_size; i++)
- for (j = 0; j < col; j++) {
- if (entry_format[j].type == DW_LNCT_path) {
- if (entry_format[j].form != DW_FORM_line_strp)
- goto next_line;
- value = length == 4 ? dwarf_read_4(ln, end)
- : dwarf_read_8(ln, end);
- if (i < FILE_TABLE_SIZE)
- filename_table[i].name =
- (char *)rc->dwarf_line_str + value;
- }
- else if (entry_format[j].type == DW_LNCT_directory_index) {
- switch (entry_format[j].form) {
- case DW_FORM_data1: value = dwarf_read_1(ln, end); break;
- case DW_FORM_data2: value = dwarf_read_2(ln, end); break;
- case DW_FORM_data4: value = dwarf_read_4(ln, end); break;
- case DW_FORM_udata: value = dwarf_read_uleb128(&ln, end); break;
- default: goto next_line;
- }
- if (i < FILE_TABLE_SIZE)
- filename_table[i].dir_entry = value;
- }
- else
- dwarf_ignore_type(ln, end);
- }
- }
- else {
- while ((dwarf_read_1(ln, end))) {
-#if 0
- if (++dir_size < DIR_TABLE_SIZE)
- dirs[dir_size - 1] = (char *)ln - 1;
-#endif
- while (dwarf_read_1(ln, end)) {}
- }
- while ((dwarf_read_1(ln, end))) {
- if (++filename_size < FILE_TABLE_SIZE) {
- filename_table[filename_size - 1].name = (char *)ln - 1;
- while (dwarf_read_1(ln, end)) {}
- filename_table[filename_size - 1].dir_entry =
- dwarf_read_uleb128(&ln, end);
- }
- else {
- while (dwarf_read_1(ln, end)) {}
- dwarf_read_uleb128(&ln, end);
- }
- dwarf_read_uleb128(&ln, end); // time
- dwarf_read_uleb128(&ln, end); // size
- }
- }
- if (filename_size >= 1)
- filename = filename_table[0].name;
- while (ln < end) {
- last_pc = pc;
- i = dwarf_read_1(ln, end);
- if (i >= opcode_base) {
- if (max_ops_per_insn == 1)
- pc += ((i - opcode_base) / line_range) * min_insn_length;
- else {
- pc += (opindex + (i - opcode_base) / line_range) /
- max_ops_per_insn * min_insn_length;
- opindex = (opindex + (i - opcode_base) / line_range) %
- max_ops_per_insn;
- }
- i = (int)((i - opcode_base) % line_range) + line_base;
-check_pc:
- if (pc >= wanted_pc && wanted_pc >= last_pc)
- goto found;
- line += i;
- }
- else {
- switch (i) {
- case 0:
- len = dwarf_read_uleb128(&ln, end);
- cp = ln;
- ln += len;
- if (len == 0)
- goto next_line;
- switch (dwarf_read_1(cp, end)) {
- case DW_LNE_end_sequence:
- break;
- case DW_LNE_set_address:
-#if PTR_SIZE == 4
- pc = dwarf_read_4(cp, end);
-#else
- pc = dwarf_read_8(cp, end);
-#endif
-#if defined TCC_TARGET_MACHO
- if (rc->prog_base != (addr_t) -1)
- pc += rc->prog_base;
-#endif
- opindex = 0;
- break;
- case DW_LNE_define_file: /* deprecated */
- if (++filename_size < FILE_TABLE_SIZE) {
- filename_table[filename_size - 1].name = (char *)ln - 1;
- while (dwarf_read_1(ln, end)) {}
- filename_table[filename_size - 1].dir_entry =
- dwarf_read_uleb128(&ln, end);
- }
- else {
- while (dwarf_read_1(ln, end)) {}
- dwarf_read_uleb128(&ln, end);
- }
- dwarf_read_uleb128(&ln, end); // time
- dwarf_read_uleb128(&ln, end); // size
- break;
- case DW_LNE_hi_user - 1:
- function = (char *)cp;
- func_addr = pc;
- break;
- default:
- break;
- }
- break;
- case DW_LNS_advance_pc:
- if (max_ops_per_insn == 1)
- pc += dwarf_read_uleb128(&ln, end) * min_insn_length;
- else {
- unsigned long long off = dwarf_read_uleb128(&ln, end);
-
- pc += (opindex + off) / max_ops_per_insn *
- min_insn_length;
- opindex = (opindex + off) % max_ops_per_insn;
- }
- i = 0;
- goto check_pc;
- case DW_LNS_advance_line:
- line += dwarf_read_sleb128(&ln, end);
- break;
- case DW_LNS_set_file:
- i = dwarf_read_uleb128(&ln, end);
- i -= i > 0 && version < 5;
- if (i < FILE_TABLE_SIZE && i < filename_size)
- filename = filename_table[i].name;
- break;
- case DW_LNS_const_add_pc:
- if (max_ops_per_insn == 1)
- pc += ((255 - opcode_base) / line_range) * min_insn_length;
- else {
- unsigned int off = (255 - opcode_base) / line_range;
-
- pc += ((opindex + off) / max_ops_per_insn) *
- min_insn_length;
- opindex = (opindex + off) % max_ops_per_insn;
- }
- i = 0;
- goto check_pc;
- case DW_LNS_fixed_advance_pc:
- i = dwarf_read_2(ln, end);
- pc += i;
- opindex = 0;
- i = 0;
- goto check_pc;
- default:
- for (j = 0; j < opcode_length[i - 1]; j++)
- dwarf_read_uleb128 (&ln, end);
- break;
- }
- }
- }
-next_line:
- ln = end;
- }
-
- filename = NULL;
- func_addr = 0;
- /* we try symtab symbols (no line number info) */
- function = rt_elfsym(rc, wanted_pc, &func_addr);
- if (function)
- goto found;
- if ((rc = rc->next))
- goto next;
-found:
- if (filename) {
- if (skip[0] && strstr(filename, skip))
- return (addr_t)-1;
- rt_printf("%s:%d: ", filename, line);
- }
- else
- rt_printf("0x%08llx : ", (long long)wanted_pc);
- rt_printf("%s %s", msg, function ? function : "???");
- return (addr_t)func_addr;
-}
-/* ------------------------------------------------------------- */
-
-static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level);
-
-static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap)
-{
- rt_context *rc = &g_rtctxt;
- addr_t pc = 0;
- char skip[100];
- int i, level, ret, n;
- const char *a, *b, *msg;
-
- if (fp) {
- /* we're called from tcc_backtrace. */
- rc->fp = (addr_t)fp;
- rc->ip = (addr_t)ip;
- msg = "";
- } else {
- /* we're called from signal/exception handler */
- msg = "RUNTIME ERROR: ";
- }
-
- skip[0] = 0;
- /* If fmt is like "^file.c^..." then skip calls from 'file.c' */
- if (fmt[0] == '^' && (b = strchr(a = fmt + 1, fmt[0]))) {
- memcpy(skip, a, b - a), skip[b - a] = 0;
- fmt = b + 1;
- }
-
- n = rc->num_callers ? rc->num_callers : 6;
- for (i = level = 0; level < n; i++) {
- ret = rt_get_caller_pc(&pc, rc, i);
- a = "%s";
- if (ret != -1) {
- if (rc->dwarf)
- pc = rt_printline_dwarf(rc, pc, level ? "by" : "at", skip);
- else
- pc = rt_printline(rc, pc, level ? "by" : "at", skip);
- if (pc == (addr_t)-1)
- continue;
- a = ": %s";
- }
- if (level == 0) {
- rt_printf(a, msg);
- rt_vprintf(fmt, ap);
- } else if (ret == -1)
- break;
- rt_printf("\n");
- if (ret == -1 || (pc == (addr_t)rc->top_func && pc))
- break;
- ++level;
- }
-
- rc->ip = rc->fp = 0;
- return 0;
-}
-
-/* emit a run time error at position 'pc' */
-static int rt_error(const char *fmt, ...)
-{
- va_list ap;
- int ret;
- va_start(ap, fmt);
- ret = _rt_error(0, 0, fmt, ap);
- va_end(ap);
- return ret;
-}
-
-static void rt_exit(int code)
-{
- rt_context *rc = &g_rtctxt;
- if (rc->do_jmp)
- longjmp(rc->jmp_buf, code ? code : 256);
- exit(code);
-}
-
-/* ------------------------------------------------------------- */
-
-#ifndef _WIN32
-# include <signal.h>
-# ifndef __OpenBSD__
-# include <sys/ucontext.h>
-# endif
-#else
-# define ucontext_t CONTEXT
-#endif
-
-/* translate from ucontext_t* to internal rt_context * */
-static void rt_getcontext(ucontext_t *uc, rt_context *rc)
-{
-#if defined _WIN64
- rc->ip = uc->Rip;
- rc->fp = uc->Rbp;
- rc->sp = uc->Rsp;
-#elif defined _WIN32
- rc->ip = uc->Eip;
- rc->fp = uc->Ebp;
- rc->sp = uc->Esp;
-#elif defined __i386__
-# if defined(__APPLE__)
- rc->ip = uc->uc_mcontext->__ss.__eip;
- rc->fp = uc->uc_mcontext->__ss.__ebp;
-# elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
- rc->ip = uc->uc_mcontext.mc_eip;
- rc->fp = uc->uc_mcontext.mc_ebp;
-# elif defined(__dietlibc__)
- rc->ip = uc->uc_mcontext.eip;
- rc->fp = uc->uc_mcontext.ebp;
-# elif defined(__NetBSD__)
- rc->ip = uc->uc_mcontext.__gregs[_REG_EIP];
- rc->fp = uc->uc_mcontext.__gregs[_REG_EBP];
-# elif defined(__OpenBSD__)
- rc->ip = uc->sc_eip;
- rc->fp = uc->sc_ebp;
-# elif !defined REG_EIP && defined EIP /* fix for glibc 2.1 */
- rc->ip = uc->uc_mcontext.gregs[EIP];
- rc->fp = uc->uc_mcontext.gregs[EBP];
-# else
- rc->ip = uc->uc_mcontext.gregs[REG_EIP];
- rc->fp = uc->uc_mcontext.gregs[REG_EBP];
-# endif
-#elif defined(__x86_64__)
-# if defined(__APPLE__)
- rc->ip = uc->uc_mcontext->__ss.__rip;
- rc->fp = uc->uc_mcontext->__ss.__rbp;
-# elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
- rc->ip = uc->uc_mcontext.mc_rip;
- rc->fp = uc->uc_mcontext.mc_rbp;
-# elif defined(__NetBSD__)
- rc->ip = uc->uc_mcontext.__gregs[_REG_RIP];
- rc->fp = uc->uc_mcontext.__gregs[_REG_RBP];
-# elif defined(__OpenBSD__)
- rc->ip = uc->sc_rip;
- rc->fp = uc->sc_rbp;
-# else
- rc->ip = uc->uc_mcontext.gregs[REG_RIP];
- rc->fp = uc->uc_mcontext.gregs[REG_RBP];
-# endif
-#elif defined(__arm__) && defined(__NetBSD__)
- rc->ip = uc->uc_mcontext.__gregs[_REG_PC];
- rc->fp = uc->uc_mcontext.__gregs[_REG_FP];
-#elif defined(__arm__) && defined(__OpenBSD__)
- rc->ip = uc->sc_pc;
- rc->fp = uc->sc_r11;
-#elif defined(__arm__) && defined(__FreeBSD__)
- rc->ip = uc->uc_mcontext.__gregs[_REG_PC];
- rc->fp = uc->uc_mcontext.__gregs[_REG_FP];
-#elif defined(__arm__)
- rc->ip = uc->uc_mcontext.arm_pc;
- rc->fp = uc->uc_mcontext.arm_fp;
-#elif defined(__aarch64__) && defined(__APPLE__)
- // see:
- // /Library/Developer/CommandLineTools/SDKs/MacOSX11.1.sdk/usr/include/mach/arm/_structs.h
- rc->ip = uc->uc_mcontext->__ss.__pc;
- rc->fp = uc->uc_mcontext->__ss.__fp;
-#elif defined(__aarch64__) && defined(__FreeBSD__)
- rc->ip = uc->uc_mcontext.mc_gpregs.gp_elr; /* aka REG_PC */
- rc->fp = uc->uc_mcontext.mc_gpregs.gp_x[29];
-#elif defined(__aarch64__) && defined(__NetBSD__)
- rc->ip = uc->uc_mcontext.__gregs[_REG_PC];
- rc->fp = uc->uc_mcontext.__gregs[_REG_FP];
-#elif defined(__aarch64__) && defined(__OpenBSD__)
- rc->ip = uc->sc_elr;
- rc->fp = uc->sc_x[29];
-#elif defined(__aarch64__)
- rc->ip = uc->uc_mcontext.pc;
- rc->fp = uc->uc_mcontext.regs[29];
-#elif defined(__riscv) && defined(__OpenBSD__)
- rc->ip = uc->sc_sepc;
- rc->fp = uc->sc_s[0];
-#elif defined(__riscv)
- rc->ip = uc->uc_mcontext.__gregs[REG_PC];
- rc->fp = uc->uc_mcontext.__gregs[REG_S0];
-#endif
-}
-
-/* ------------------------------------------------------------- */
-#ifndef _WIN32
-/* signal handler for fatal errors */
-static void sig_error(int signum, siginfo_t *siginf, void *puc)
-{
- rt_context *rc = &g_rtctxt;
- rt_getcontext(puc, rc);
-
- switch(signum) {
- case SIGFPE:
- switch(siginf->si_code) {
- case FPE_INTDIV:
- case FPE_FLTDIV:
- rt_error("division by zero");
- break;
- default:
- rt_error("floating point exception");
- break;
- }
- break;
- case SIGBUS:
- case SIGSEGV:
- rt_error("invalid memory access");
- break;
- case SIGILL:
- rt_error("illegal instruction");
- break;
- case SIGABRT:
- rt_error("abort() called");
- break;
- default:
- rt_error("caught signal %d", signum);
- break;
- }
- rt_exit(255);
-}
-
-#ifndef SA_SIGINFO
-# define SA_SIGINFO 0x00000004u
-#endif
-
-/* Generate a stack backtrace when a CPU exception occurs. */
-static void set_exception_handler(void)
-{
- struct sigaction sigact;
- /* install TCC signal handlers to print debug info on fatal
- runtime errors */
- sigemptyset (&sigact.sa_mask);
- sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
-#if 0//def SIGSTKSZ // this causes signals not to work at all on some (older) linuxes
- sigact.sa_flags |= SA_ONSTACK;
-#endif
- sigact.sa_sigaction = sig_error;
- sigemptyset(&sigact.sa_mask);
- sigaction(SIGFPE, &sigact, NULL);
- sigaction(SIGILL, &sigact, NULL);
- sigaction(SIGSEGV, &sigact, NULL);
- sigaction(SIGBUS, &sigact, NULL);
- sigaction(SIGABRT, &sigact, NULL);
-#if 0//def SIGSTKSZ
- /* This allows stack overflow to be reported instead of a SEGV */
- {
- stack_t ss;
- static unsigned char stack[SIGSTKSZ] __attribute__((aligned(16)));
-
- ss.ss_sp = stack;
- ss.ss_size = SIGSTKSZ;
- ss.ss_flags = 0;
- sigaltstack(&ss, NULL);
- }
-#endif
-}
-
-#else /* WIN32 */
-
-/* signal handler for fatal errors */
-static long __stdcall cpu_exception_handler(EXCEPTION_POINTERS *ex_info)
-{
- rt_context *rc = &g_rtctxt;
- unsigned code;
- rt_getcontext(ex_info->ContextRecord, rc);
-
- switch (code = ex_info->ExceptionRecord->ExceptionCode) {
- case EXCEPTION_ACCESS_VIOLATION:
- rt_error("invalid memory access");
- break;
- case EXCEPTION_STACK_OVERFLOW:
- rt_error("stack overflow");
- break;
- case EXCEPTION_INT_DIVIDE_BY_ZERO:
- rt_error("division by zero");
- break;
- case EXCEPTION_BREAKPOINT:
- case EXCEPTION_SINGLE_STEP:
- rc->ip = *(addr_t*)rc->sp;
- rt_error("breakpoint/single-step exception:");
- return EXCEPTION_CONTINUE_SEARCH;
- default:
- rt_error("caught exception %08x", code);
- break;
- }
- if (rc->do_jmp)
- rt_exit(255);
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-/* Generate a stack backtrace when a CPU exception occurs. */
-static void set_exception_handler(void)
-{
- SetUnhandledExceptionFilter(cpu_exception_handler);
-}
-
-#endif
-
-/* ------------------------------------------------------------- */
-/* return the PC at frame level 'level'. Return negative if not found */
-#if defined(__i386__) || defined(__x86_64__)
-static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
-{
- addr_t ip, fp;
- if (level == 0) {
- ip = rc->ip;
- } else {
- ip = 0;
- fp = rc->fp;
- while (--level) {
- /* XXX: check address validity with program info */
- if (fp <= 0x1000)
- break;
- fp = ((addr_t *)fp)[0];
- }
- if (fp > 0x1000)
- ip = ((addr_t *)fp)[1];
- }
- if (ip <= 0x1000)
- return -1;
- *paddr = ip;
- return 0;
-}
-
-#elif defined(__arm__)
-static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
-{
- /* XXX: only supports linux/bsd */
-#if !defined(__linux__) && \
- !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
- return -1;
-#else
- if (level == 0) {
- *paddr = rc->ip;
- } else {
- addr_t fp = rc->fp;
- while (--level)
- fp = ((addr_t *)fp)[0];
- *paddr = ((addr_t *)fp)[2];
- }
- return 0;
-#endif
-}
-
-#elif defined(__aarch64__)
-static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
-{
- if (level == 0) {
- *paddr = rc->ip;
- } else {
- addr_t *fp = (addr_t*)rc->fp;
- while (--level)
- fp = (addr_t *)fp[0];
- *paddr = fp[1];
- }
- return 0;
-}
-
-#elif defined(__riscv)
-static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
-{
- if (level == 0) {
- *paddr = rc->ip;
- } else {
- addr_t *fp = (addr_t*)rc->fp;
- while (--level && fp >= (addr_t*)0x1000)
- fp = (addr_t *)fp[-2];
- if (fp < (addr_t*)0x1000)
- return -1;
- *paddr = fp[-1];
- }
- return 0;
-}
-
-#else
-#warning add arch specific rt_get_caller_pc()
-static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level)
-{
- return -1;
-}
-
-#endif
-#endif /* CONFIG_TCC_BACKTRACE */
-/* ------------------------------------------------------------- */
-#ifdef CONFIG_TCC_STATIC
-
-/* dummy function for profiling */
-ST_FUNC void *dlopen(const char *filename, int flag)
-{
- return NULL;
-}
-
-ST_FUNC void dlclose(void *p)
-{
-}
-
-ST_FUNC const char *dlerror(void)
-{
- return "error";
-}
-
-typedef struct TCCSyms {
- char *str;
- void *ptr;
-} TCCSyms;
-
-
-/* add the symbol you want here if no dynamic linking is done */
-static TCCSyms tcc_syms[] = {
-#if !defined(CONFIG_TCCBOOT)
-#define TCCSYM(a) { #a, &a, },
- TCCSYM(printf)
- TCCSYM(fprintf)
- TCCSYM(fopen)
- TCCSYM(fclose)
-#undef TCCSYM
-#endif
- { NULL, NULL },
-};
-
-ST_FUNC void *dlsym(void *handle, const char *symbol)
-{
- TCCSyms *p;
- p = tcc_syms;
- while (p->str != NULL) {
- if (!strcmp(p->str, symbol))
- return p->ptr;
- p++;
- }
- return NULL;
-}
-
-#endif /* CONFIG_TCC_STATIC */
-#endif /* TCC_IS_NATIVE */
-/* ------------------------------------------------------------- */
diff --git a/tinycc/tcctok.h b/tinycc/tcctok.h
deleted file mode 100644
index cfdc60d..0000000
--- a/tinycc/tcctok.h
+++ /dev/null
@@ -1,420 +0,0 @@
-/*********************************************************************/
-/* keywords */
- DEF(TOK_INT, "int")
- DEF(TOK_VOID, "void")
- DEF(TOK_CHAR, "char")
- DEF(TOK_IF, "if")
- DEF(TOK_ELSE, "else")
- DEF(TOK_WHILE, "while")
- DEF(TOK_BREAK, "break")
- DEF(TOK_RETURN, "return")
- DEF(TOK_FOR, "for")
- DEF(TOK_EXTERN, "extern")
- DEF(TOK_STATIC, "static")
- DEF(TOK_UNSIGNED, "unsigned")
- DEF(TOK_GOTO, "goto")
- DEF(TOK_DO, "do")
- DEF(TOK_CONTINUE, "continue")
- DEF(TOK_SWITCH, "switch")
- DEF(TOK_CASE, "case")
-
- DEF(TOK__Atomic, "_Atomic")
- DEF(TOK_CONST1, "const")
- DEF(TOK_CONST2, "__const") /* gcc keyword */
- DEF(TOK_CONST3, "__const__") /* gcc keyword */
- DEF(TOK_VOLATILE1, "volatile")
- DEF(TOK_VOLATILE2, "__volatile") /* gcc keyword */
- DEF(TOK_VOLATILE3, "__volatile__") /* gcc keyword */
- DEF(TOK_LONG, "long")
- DEF(TOK_REGISTER, "register")
- DEF(TOK_SIGNED1, "signed")
- DEF(TOK_SIGNED2, "__signed") /* gcc keyword */
- DEF(TOK_SIGNED3, "__signed__") /* gcc keyword */
- DEF(TOK_AUTO, "auto")
- DEF(TOK_INLINE1, "inline")
- DEF(TOK_INLINE2, "__inline") /* gcc keyword */
- DEF(TOK_INLINE3, "__inline__") /* gcc keyword */
- DEF(TOK_RESTRICT1, "restrict")
- DEF(TOK_RESTRICT2, "__restrict")
- DEF(TOK_RESTRICT3, "__restrict__")
- DEF(TOK_EXTENSION, "__extension__") /* gcc keyword */
- DEF(TOK_THREAD_LOCAL, "_Thread_local") /* C11 thread-local storage */
-
- DEF(TOK_GENERIC, "_Generic")
- DEF(TOK_STATIC_ASSERT, "_Static_assert")
-
- DEF(TOK_FLOAT, "float")
- DEF(TOK_DOUBLE, "double")
- DEF(TOK_BOOL, "_Bool")
- DEF(TOK_COMPLEX, "_Complex")
- DEF(TOK_SHORT, "short")
- DEF(TOK_STRUCT, "struct")
- DEF(TOK_UNION, "union")
- DEF(TOK_TYPEDEF, "typedef")
- DEF(TOK_DEFAULT, "default")
- DEF(TOK_ENUM, "enum")
- DEF(TOK_SIZEOF, "sizeof")
- DEF(TOK_ATTRIBUTE1, "__attribute")
- DEF(TOK_ATTRIBUTE2, "__attribute__")
- DEF(TOK_ALIGNOF1, "__alignof")
- DEF(TOK_ALIGNOF2, "__alignof__")
- DEF(TOK_ALIGNOF3, "_Alignof")
- DEF(TOK_ALIGNAS, "_Alignas")
- DEF(TOK_TYPEOF1, "typeof")
- DEF(TOK_TYPEOF2, "__typeof")
- DEF(TOK_TYPEOF3, "__typeof__")
- DEF(TOK_LABEL, "__label__")
- DEF(TOK_ASM1, "asm")
- DEF(TOK_ASM2, "__asm")
- DEF(TOK_ASM3, "__asm__")
-
-#ifdef TCC_TARGET_ARM64
- DEF(TOK_UINT128, "__uint128_t")
-#endif
-
-/*********************************************************************/
-/* the following are not keywords. They are included to ease parsing */
-/* preprocessor only */
- DEF(TOK_DEFINE, "define")
- DEF(TOK_INCLUDE, "include")
- DEF(TOK_INCLUDE_NEXT, "include_next")
- DEF(TOK_IFDEF, "ifdef")
- DEF(TOK_IFNDEF, "ifndef")
- DEF(TOK_ELIF, "elif")
- DEF(TOK_ENDIF, "endif")
- DEF(TOK_DEFINED, "defined")
- DEF(TOK_UNDEF, "undef")
- DEF(TOK_ERROR, "error")
- DEF(TOK_WARNING, "warning")
- DEF(TOK_LINE, "line")
- DEF(TOK_PRAGMA, "pragma")
- DEF(TOK___LINE__, "__LINE__")
- DEF(TOK___FILE__, "__FILE__")
- DEF(TOK___DATE__, "__DATE__")
- DEF(TOK___TIME__, "__TIME__")
- DEF(TOK___FUNCTION__, "__FUNCTION__")
- DEF(TOK___VA_ARGS__, "__VA_ARGS__")
- DEF(TOK___COUNTER__, "__COUNTER__")
- DEF(TOK___HAS_INCLUDE, "__has_include")
- DEF(TOK___HAS_INCLUDE_NEXT, "__has_include_next")
-
-/* special identifiers */
- DEF(TOK___FUNC__, "__func__")
-
-/* special floating point values */
- DEF(TOK___NAN__, "__nan__")
- DEF(TOK___SNAN__, "__snan__")
- DEF(TOK___INF__, "__inf__")
-#if defined TCC_TARGET_X86_64
- DEF(TOK___mzerosf, "__mzerosf") /* -0.0 */
- DEF(TOK___mzerodf, "__mzerodf") /* -0.0 */
-#endif
-
-/* attribute identifiers */
-/* XXX: handle all tokens generically since speed is not critical */
- DEF(TOK_SECTION1, "section")
- DEF(TOK_SECTION2, "__section__")
- DEF(TOK_ALIGNED1, "aligned")
- DEF(TOK_ALIGNED2, "__aligned__")
- DEF(TOK_PACKED1, "packed")
- DEF(TOK_PACKED2, "__packed__")
- DEF(TOK_WEAK1, "weak")
- DEF(TOK_WEAK2, "__weak__")
- DEF(TOK_ALIAS1, "alias")
- DEF(TOK_ALIAS2, "__alias__")
- DEF(TOK_UNUSED1, "unused")
- DEF(TOK_UNUSED2, "__unused__")
- DEF(TOK_NODEBUG1, "nodebug")
- DEF(TOK_NODEBUG2, "__nodebug__")
- DEF(TOK_CDECL1, "cdecl")
- DEF(TOK_CDECL2, "__cdecl")
- DEF(TOK_CDECL3, "__cdecl__")
- DEF(TOK_STDCALL1, "stdcall")
- DEF(TOK_STDCALL2, "__stdcall")
- DEF(TOK_STDCALL3, "__stdcall__")
- DEF(TOK_FASTCALL1, "fastcall")
- DEF(TOK_FASTCALL2, "__fastcall")
- DEF(TOK_FASTCALL3, "__fastcall__")
- DEF(TOK_REGPARM1, "regparm")
- DEF(TOK_REGPARM2, "__regparm__")
- DEF(TOK_CLEANUP1, "cleanup")
- DEF(TOK_CLEANUP2, "__cleanup__")
- DEF(TOK_CONSTRUCTOR1, "constructor")
- DEF(TOK_CONSTRUCTOR2, "__constructor__")
- DEF(TOK_DESTRUCTOR1, "destructor")
- DEF(TOK_DESTRUCTOR2, "__destructor__")
- DEF(TOK_ALWAYS_INLINE1, "always_inline")
- DEF(TOK_ALWAYS_INLINE2, "__always_inline__")
-
- DEF(TOK_MODE, "__mode__")
- DEF(TOK_MODE_QI, "__QI__")
- DEF(TOK_MODE_DI, "__DI__")
- DEF(TOK_MODE_HI, "__HI__")
- DEF(TOK_MODE_SI, "__SI__")
- DEF(TOK_MODE_word, "__word__")
-
- DEF(TOK_DLLEXPORT, "dllexport")
- DEF(TOK_DLLIMPORT, "dllimport")
- DEF(TOK_NODECORATE, "nodecorate")
- DEF(TOK_NORETURN1, "noreturn")
- DEF(TOK_NORETURN2, "__noreturn__")
- DEF(TOK_NORETURN3, "_Noreturn")
- DEF(TOK_VISIBILITY1, "visibility")
- DEF(TOK_VISIBILITY2, "__visibility__")
-
- DEF(TOK_builtin_types_compatible_p, "__builtin_types_compatible_p")
- DEF(TOK_builtin_choose_expr, "__builtin_choose_expr")
- DEF(TOK_builtin_constant_p, "__builtin_constant_p")
- DEF(TOK_builtin_frame_address, "__builtin_frame_address")
- DEF(TOK_builtin_return_address, "__builtin_return_address")
- DEF(TOK_builtin_expect, "__builtin_expect")
- /*DEF(TOK_builtin_va_list, "__builtin_va_list")*/
-#if defined TCC_TARGET_PE && defined TCC_TARGET_X86_64
- DEF(TOK_builtin_va_start, "__builtin_va_start")
-#elif defined TCC_TARGET_X86_64
- DEF(TOK_builtin_va_arg_types, "__builtin_va_arg_types")
-#elif defined TCC_TARGET_ARM64
- DEF(TOK_builtin_va_start, "__builtin_va_start")
- DEF(TOK_builtin_va_arg, "__builtin_va_arg")
-#elif defined TCC_TARGET_RISCV64
- DEF(TOK_builtin_va_start, "__builtin_va_start")
-#endif
-
-/* atomic operations */
-#define DEF_ATOMIC(ID) DEF(TOK_##__##ID, "__"#ID)
- DEF_ATOMIC(atomic_store)
- DEF_ATOMIC(atomic_load)
- DEF_ATOMIC(atomic_exchange)
- DEF_ATOMIC(atomic_compare_exchange)
- DEF_ATOMIC(atomic_fetch_add)
- DEF_ATOMIC(atomic_fetch_sub)
- DEF_ATOMIC(atomic_fetch_or)
- DEF_ATOMIC(atomic_fetch_xor)
- DEF_ATOMIC(atomic_fetch_and)
- DEF_ATOMIC(atomic_fetch_nand)
- DEF_ATOMIC(atomic_add_fetch)
- DEF_ATOMIC(atomic_sub_fetch)
- DEF_ATOMIC(atomic_or_fetch)
- DEF_ATOMIC(atomic_xor_fetch)
- DEF_ATOMIC(atomic_and_fetch)
- DEF_ATOMIC(atomic_nand_fetch)
-
-/* pragma */
- DEF(TOK_pack, "pack")
-#if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_X86_64) && \
- !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_ARM64)
- /* already defined for assembler */
- DEF(TOK_ASM_push, "push")
- DEF(TOK_ASM_pop, "pop")
-#endif
- DEF(TOK_comment, "comment")
- DEF(TOK_lib, "lib")
- DEF(TOK_push_macro, "push_macro")
- DEF(TOK_pop_macro, "pop_macro")
- DEF(TOK_once, "once")
- DEF(TOK_option, "option")
-
-/* builtin functions or variables */
-#ifndef TCC_ARM_EABI
- DEF(TOK_memcpy, "memcpy")
- DEF(TOK_memmove, "memmove")
- DEF(TOK_memset, "memset")
- DEF(TOK___divdi3, "__divdi3")
- DEF(TOK___moddi3, "__moddi3")
- DEF(TOK___udivdi3, "__udivdi3")
- DEF(TOK___umoddi3, "__umoddi3")
- DEF(TOK___ashrdi3, "__ashrdi3")
- DEF(TOK___lshrdi3, "__lshrdi3")
- DEF(TOK___ashldi3, "__ashldi3")
- DEF(TOK___floatundisf, "__floatundisf")
- DEF(TOK___floatundidf, "__floatundidf")
-# ifndef TCC_ARM_VFP
- DEF(TOK___floatundixf, "__floatundixf")
- DEF(TOK___fixunsxfdi, "__fixunsxfdi")
-# endif
- DEF(TOK___fixunssfdi, "__fixunssfdi")
- DEF(TOK___fixunsdfdi, "__fixunsdfdi")
-#endif
-
-#if defined TCC_TARGET_ARM
-# ifdef TCC_ARM_EABI
- DEF(TOK_memcpy, "__aeabi_memcpy")
- DEF(TOK_memmove, "__aeabi_memmove")
- DEF(TOK_memmove4, "__aeabi_memmove4")
- DEF(TOK_memmove8, "__aeabi_memmove8")
- DEF(TOK_memset, "__aeabi_memset")
- DEF(TOK___aeabi_ldivmod, "__aeabi_ldivmod")
- DEF(TOK___aeabi_uldivmod, "__aeabi_uldivmod")
- DEF(TOK___aeabi_idivmod, "__aeabi_idivmod")
- DEF(TOK___aeabi_uidivmod, "__aeabi_uidivmod")
- DEF(TOK___divsi3, "__aeabi_idiv")
- DEF(TOK___udivsi3, "__aeabi_uidiv")
- DEF(TOK___floatdisf, "__aeabi_l2f")
- DEF(TOK___floatdidf, "__aeabi_l2d")
- DEF(TOK___fixsfdi, "__aeabi_f2lz")
- DEF(TOK___fixdfdi, "__aeabi_d2lz")
- DEF(TOK___ashrdi3, "__aeabi_lasr")
- DEF(TOK___lshrdi3, "__aeabi_llsr")
- DEF(TOK___ashldi3, "__aeabi_llsl")
- DEF(TOK___floatundisf, "__aeabi_ul2f")
- DEF(TOK___floatundidf, "__aeabi_ul2d")
- DEF(TOK___fixunssfdi, "__aeabi_f2ulz")
- DEF(TOK___fixunsdfdi, "__aeabi_d2ulz")
-# else
- DEF(TOK___modsi3, "__modsi3")
- DEF(TOK___umodsi3, "__umodsi3")
- DEF(TOK___divsi3, "__divsi3")
- DEF(TOK___udivsi3, "__udivsi3")
- DEF(TOK___floatdisf, "__floatdisf")
- DEF(TOK___floatdidf, "__floatdidf")
-# ifndef TCC_ARM_VFP
- DEF(TOK___floatdixf, "__floatdixf")
- DEF(TOK___fixunssfsi, "__fixunssfsi")
- DEF(TOK___fixunsdfsi, "__fixunsdfsi")
- DEF(TOK___fixunsxfsi, "__fixunsxfsi")
- DEF(TOK___fixxfdi, "__fixxfdi")
-# endif
- DEF(TOK___fixsfdi, "__fixsfdi")
- DEF(TOK___fixdfdi, "__fixdfdi")
-# endif
-#endif
-
-#if defined TCC_TARGET_C67
- DEF(TOK__divi, "_divi")
- DEF(TOK__divu, "_divu")
- DEF(TOK__divf, "_divf")
- DEF(TOK__divd, "_divd")
- DEF(TOK__remi, "_remi")
- DEF(TOK__remu, "_remu")
-#endif
-
-#if defined TCC_TARGET_I386
- DEF(TOK___fixsfdi, "__fixsfdi")
- DEF(TOK___fixdfdi, "__fixdfdi")
- DEF(TOK___fixxfdi, "__fixxfdi")
-#endif
-
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
- DEF(TOK_alloca, "alloca")
-#endif
-
-#if defined TCC_TARGET_PE
- DEF(TOK___chkstk, "__chkstk")
-#endif
-#if defined TCC_TARGET_ARM64 || defined TCC_TARGET_RISCV64
- DEF(TOK___arm64_clear_cache, "__arm64_clear_cache")
- DEF(TOK___addtf3, "__addtf3")
- DEF(TOK___subtf3, "__subtf3")
- DEF(TOK___multf3, "__multf3")
- DEF(TOK___divtf3, "__divtf3")
- DEF(TOK___extendsftf2, "__extendsftf2")
- DEF(TOK___extenddftf2, "__extenddftf2")
- DEF(TOK___trunctfsf2, "__trunctfsf2")
- DEF(TOK___trunctfdf2, "__trunctfdf2")
- DEF(TOK___fixtfsi, "__fixtfsi")
- DEF(TOK___fixtfdi, "__fixtfdi")
- DEF(TOK___fixunstfsi, "__fixunstfsi")
- DEF(TOK___fixunstfdi, "__fixunstfdi")
- DEF(TOK___floatsitf, "__floatsitf")
- DEF(TOK___floatditf, "__floatditf")
- DEF(TOK___floatunsitf, "__floatunsitf")
- DEF(TOK___floatunditf, "__floatunditf")
- DEF(TOK___eqtf2, "__eqtf2")
- DEF(TOK___netf2, "__netf2")
- DEF(TOK___lttf2, "__lttf2")
- DEF(TOK___letf2, "__letf2")
- DEF(TOK___gttf2, "__gttf2")
- DEF(TOK___getf2, "__getf2")
-#endif
-
-/* bound checking symbols */
-#ifdef CONFIG_TCC_BCHECK
- DEF(TOK___bound_ptr_add, "__bound_ptr_add")
- DEF(TOK___bound_ptr_indir1, "__bound_ptr_indir1")
- DEF(TOK___bound_ptr_indir2, "__bound_ptr_indir2")
- DEF(TOK___bound_ptr_indir4, "__bound_ptr_indir4")
- DEF(TOK___bound_ptr_indir8, "__bound_ptr_indir8")
- DEF(TOK___bound_ptr_indir12, "__bound_ptr_indir12")
- DEF(TOK___bound_ptr_indir16, "__bound_ptr_indir16")
- DEF(TOK___bound_main_arg, "__bound_main_arg")
- DEF(TOK___bound_local_new, "__bound_local_new")
- DEF(TOK___bound_local_delete, "__bound_local_delete")
- DEF(TOK___bound_setjmp, "__bound_setjmp")
- DEF(TOK___bound_longjmp, "__bound_longjmp")
- DEF(TOK___bound_new_region, "__bound_new_region")
-# ifdef TCC_TARGET_PE
-# ifdef TCC_TARGET_X86_64
- DEF(TOK___bound_alloca_nr, "__bound_alloca_nr")
-# endif
-# else
- DEF(TOK_sigsetjmp, "sigsetjmp")
- DEF(TOK___sigsetjmp, "__sigsetjmp")
- DEF(TOK_siglongjmp, "siglongjmp")
-# endif
- DEF(TOK_setjmp, "setjmp")
- DEF(TOK__setjmp, "_setjmp")
- DEF(TOK_longjmp, "longjmp")
-#endif
-
-
-/*********************************************************************/
-/* Tiny Assembler */
-#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
-#define DEF_ASMDIR(x) DEF(TOK_ASMDIR_ ## x, "." #x)
-#define TOK_ASM_int TOK_INT
-
-#define TOK_ASMDIR_FIRST TOK_ASMDIR_byte
-#define TOK_ASMDIR_LAST TOK_ASMDIR_section
-
- DEF_ASMDIR(byte) /* must be first directive */
- DEF_ASMDIR(word)
- DEF_ASMDIR(align)
- DEF_ASMDIR(balign)
- DEF_ASMDIR(p2align)
- DEF_ASMDIR(set)
- DEF_ASMDIR(skip)
- DEF_ASMDIR(space)
- DEF_ASMDIR(string)
- DEF_ASMDIR(asciz)
- DEF_ASMDIR(ascii)
- DEF_ASMDIR(file)
- DEF_ASMDIR(globl)
- DEF_ASMDIR(global)
- DEF_ASMDIR(weak)
- DEF_ASMDIR(hidden)
- DEF_ASMDIR(ident)
- DEF_ASMDIR(size)
- DEF_ASMDIR(type)
- DEF_ASMDIR(text)
- DEF_ASMDIR(data)
- DEF_ASMDIR(bss)
- DEF_ASMDIR(previous)
- DEF_ASMDIR(pushsection)
- DEF_ASMDIR(popsection)
- DEF_ASMDIR(fill)
- DEF_ASMDIR(rept)
- DEF_ASMDIR(endr)
- DEF_ASMDIR(org)
- DEF_ASMDIR(quad)
-#if defined(TCC_TARGET_I386)
- DEF_ASMDIR(code16)
- DEF_ASMDIR(code32)
-#elif defined(TCC_TARGET_X86_64)
- DEF_ASMDIR(code64)
-#endif
- DEF_ASMDIR(short)
- DEF_ASMDIR(long)
- DEF_ASMDIR(int)
- DEF_ASMDIR(section) /* must be last directive */
-
-#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
-#include "i386-tok.h"
-#endif
-
-#if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64
-#include "arm-tok.h"
-#endif
-
-#if defined TCC_TARGET_RISCV64
-#include "riscv64-tok.h"
-#endif
diff --git a/tinycc/tcctools.c b/tinycc/tcctools.c
deleted file mode 100644
index bef21ef..0000000
--- a/tinycc/tcctools.c
+++ /dev/null
@@ -1,631 +0,0 @@
-/* -------------------------------------------------------------- */
-/*
- * TCC - Tiny C Compiler
- *
- * tcctools.c - extra tools and and -m32/64 support
- *
- */
-
-/* -------------------------------------------------------------- */
-/*
- * This program is for making libtcc1.a without ar
- * tiny_libmaker - tiny elf lib maker
- * usage: tiny_libmaker [lib] files...
- * Copyright (c) 2007 Timppa
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "tcc.h"
-
-//#define ARMAG "!<arch>\n"
-#define ARFMAG "`\n"
-
-typedef struct {
- char ar_name[16];
- char ar_date[12];
- char ar_uid[6];
- char ar_gid[6];
- char ar_mode[8];
- char ar_size[10];
- char ar_fmag[2];
-} ArHdr;
-
-static unsigned long le2belong(unsigned long ul) {
- return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
- ((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
-}
-
-/* Returns 1 if s contains any of the chars of list, else 0 */
-static int contains_any(const char *s, const char *list) {
- const char *l;
- for (; *s; s++) {
- for (l = list; *l; l++) {
- if (*s == *l)
- return 1;
- }
- }
- return 0;
-}
-
-static int ar_usage(int ret) {
- fprintf(stderr, "usage: tcc -ar [crstvx] lib [files]\n");
- fprintf(stderr, "create library ([abdiopN] not supported).\n");
- return ret;
-}
-
-ST_FUNC int tcc_tool_ar(TCCState *s1, int argc, char **argv)
-{
- static const ArHdr arhdr_init = {
- "/ ",
- "0 ",
- "0 ",
- "0 ",
- "0 ",
- "0 ",
- ARFMAG
- };
-
- ArHdr arhdr = arhdr_init;
- ArHdr arhdro = arhdr_init;
-
- FILE *fi, *fh = NULL, *fo = NULL;
- ElfW(Ehdr) *ehdr;
- ElfW(Shdr) *shdr;
- ElfW(Sym) *sym;
- int i, fsize, i_lib, i_obj;
- char *buf, *shstr, *symtab = NULL, *strtab = NULL;
- int symtabsize = 0;//, strtabsize = 0;
- char *anames = NULL;
- int *afpos = NULL;
- int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
- char tfile[260], stmp[20];
- char *file, *name;
- int ret = 2;
- const char *ops_conflict = "habdiopN"; // unsupported but destructive if ignored.
- int extract = 0;
- int table = 0;
- int verbose = 0;
-
- i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
- for (i = 1; i < argc; i++) {
- const char *a = argv[i];
- if (*a == '-' && strstr(a, "."))
- ret = 1; // -x.y is always invalid (same as gnu ar)
- if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
- if (contains_any(a, ops_conflict))
- ret = 1;
- if (strstr(a, "x"))
- extract = 1;
- if (strstr(a, "t"))
- table = 1;
- if (strstr(a, "v"))
- verbose = 1;
- } else { // lib or obj files: don't abort - keep validating all args.
- if (!i_lib) // first file is the lib
- i_lib = i;
- else if (!i_obj) // second file is the first obj
- i_obj = i;
- }
- }
-
- if (!i_lib) // i_obj implies also i_lib.
- ret = 1;
- i_obj = i_obj ? i_obj : argc; // An empty archive will be generated if no input file is given
-
- if (ret == 1)
- return ar_usage(ret);
-
- if (extract || table) {
- if ((fh = fopen(argv[i_lib], "rb")) == NULL)
- {
- fprintf(stderr, "tcc: ar: can't open file %s\n", argv[i_lib]);
- goto finish;
- }
- fread(stmp, 1, 8, fh);
- if (memcmp(stmp,ARMAG,8))
- {
-no_ar:
- fprintf(stderr, "tcc: ar: not an ar archive %s\n", argv[i_lib]);
- goto finish;
- }
- while (fread(&arhdr, 1, sizeof(arhdr), fh) == sizeof(arhdr)) {
- char *p, *e;
-
- if (memcmp(arhdr.ar_fmag, ARFMAG, 2))
- goto no_ar;
- p = arhdr.ar_name;
- for (e = p + sizeof arhdr.ar_name; e > p && e[-1] == ' ';)
- e--;
- *e = '\0';
- arhdr.ar_size[sizeof arhdr.ar_size-1] = 0;
- fsize = atoi(arhdr.ar_size);
- buf = tcc_malloc(fsize + 1);
- fread(buf, fsize, 1, fh);
- if (strcmp(arhdr.ar_name,"/") && strcmp(arhdr.ar_name,"/SYM64/")) {
- if (e > p && e[-1] == '/')
- e[-1] = '\0';
- /* tv not implemented */
- if (table || verbose)
- printf("%s%s\n", extract ? "x - " : "", arhdr.ar_name);
- if (extract) {
- if ((fo = fopen(arhdr.ar_name, "wb")) == NULL)
- {
- fprintf(stderr, "tcc: ar: can't create file %s\n",
- arhdr.ar_name);
- tcc_free(buf);
- goto finish;
- }
- fwrite(buf, fsize, 1, fo);
- fclose(fo);
- /* ignore date/uid/gid/mode */
- }
- }
- tcc_free(buf);
- }
- ret = 0;
-finish:
- if (fh)
- fclose(fh);
- return ret;
- }
-
- if ((fh = fopen(argv[i_lib], "wb")) == NULL)
- {
- fprintf(stderr, "tcc: ar: can't create file %s\n", argv[i_lib]);
- goto the_end;
- }
-
- sprintf(tfile, "%s.tmp", argv[i_lib]);
- if ((fo = fopen(tfile, "wb+")) == NULL)
- {
- fprintf(stderr, "tcc: ar: can't create temporary file %s\n", tfile);
- goto the_end;
- }
-
- funcmax = 250;
- afpos = tcc_realloc(NULL, funcmax * sizeof *afpos); // 250 func
- memcpy(&arhdro.ar_mode, "100644", 6);
-
- // i_obj = first input object file
- while (i_obj < argc)
- {
- if (*argv[i_obj] == '-') { // by now, all options start with '-'
- i_obj++;
- continue;
- }
- if ((fi = fopen(argv[i_obj], "rb")) == NULL) {
- fprintf(stderr, "tcc: ar: can't open file %s \n", argv[i_obj]);
- goto the_end;
- }
- if (verbose)
- printf("a - %s\n", argv[i_obj]);
-
- fseek(fi, 0, SEEK_END);
- fsize = ftell(fi);
- fseek(fi, 0, SEEK_SET);
- buf = tcc_malloc(fsize + 1);
- fread(buf, fsize, 1, fi);
- fclose(fi);
-
- // elf header
- ehdr = (ElfW(Ehdr) *)buf;
- if (ehdr->e_ident[4] != ELFCLASSW)
- {
- fprintf(stderr, "tcc: ar: Unsupported Elf Class: %s\n", argv[i_obj]);
- goto the_end;
- }
-
- shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
- shstr = (char *)(buf + shdr->sh_offset);
- for (i = 0; i < ehdr->e_shnum; i++)
- {
- shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
- if (!shdr->sh_offset)
- continue;
- if (shdr->sh_type == SHT_SYMTAB)
- {
- symtab = (char *)(buf + shdr->sh_offset);
- symtabsize = shdr->sh_size;
- }
- if (shdr->sh_type == SHT_STRTAB)
- {
- if (!strcmp(shstr + shdr->sh_name, ".strtab"))
- {
- strtab = (char *)(buf + shdr->sh_offset);
- //strtabsize = shdr->sh_size;
- }
- }
- }
-
- if (symtab && symtabsize)
- {
- int nsym = symtabsize / sizeof(ElfW(Sym));
- //printf("symtab: info size shndx name\n");
- for (i = 1; i < nsym; i++)
- {
- sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym)));
- if (sym->st_shndx &&
- (sym->st_info == 0x10
- || sym->st_info == 0x11
- || sym->st_info == 0x12
- || sym->st_info == 0x20
- || sym->st_info == 0x21
- || sym->st_info == 0x22
- )) {
- //printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
- istrlen = strlen(strtab + sym->st_name)+1;
- anames = tcc_realloc(anames, strpos+istrlen);
- strcpy(anames + strpos, strtab + sym->st_name);
- strpos += istrlen;
- if (++funccnt >= funcmax) {
- funcmax += 250;
- afpos = tcc_realloc(afpos, funcmax * sizeof *afpos); // 250 func more
- }
- afpos[funccnt] = fpos;
- }
- }
- }
-
- file = argv[i_obj];
- for (name = strchr(file, 0);
- name > file && name[-1] != '/' && name[-1] != '\\';
- --name);
- istrlen = strlen(name);
- if (istrlen >= sizeof(arhdro.ar_name))
- istrlen = sizeof(arhdro.ar_name) - 1;
- memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
- memcpy(arhdro.ar_name, name, istrlen);
- arhdro.ar_name[istrlen] = '/';
- sprintf(stmp, "%-10d", fsize);
- memcpy(&arhdro.ar_size, stmp, 10);
- fwrite(&arhdro, sizeof(arhdro), 1, fo);
- fwrite(buf, fsize, 1, fo);
- tcc_free(buf);
- i_obj++;
- fpos += (fsize + sizeof(arhdro));
- }
- hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
- fpos = 0;
- if ((hofs & 1)) // align
- hofs++, fpos = 1;
- // write header
- fwrite(ARMAG, 8, 1, fh);
- // create an empty archive
- if (!funccnt) {
- ret = 0;
- goto the_end;
- }
- sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)) + fpos);
- memcpy(&arhdr.ar_size, stmp, 10);
- fwrite(&arhdr, sizeof(arhdr), 1, fh);
- afpos[0] = le2belong(funccnt);
- for (i=1; i<=funccnt; i++)
- afpos[i] = le2belong(afpos[i] + hofs);
- fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
- fwrite(anames, strpos, 1, fh);
- if (fpos)
- fwrite("", 1, 1, fh);
- // write objects
- fseek(fo, 0, SEEK_END);
- fsize = ftell(fo);
- fseek(fo, 0, SEEK_SET);
- buf = tcc_malloc(fsize + 1);
- fread(buf, fsize, 1, fo);
- fwrite(buf, fsize, 1, fh);
- tcc_free(buf);
- ret = 0;
-the_end:
- if (anames)
- tcc_free(anames);
- if (afpos)
- tcc_free(afpos);
- if (fh)
- fclose(fh);
- if (fo)
- fclose(fo), remove(tfile);
- return ret;
-}
-
-/* -------------------------------------------------------------- */
-/*
- * tiny_impdef creates an export definition file (.def) from a dll
- * on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
- *
- * Copyright (c) 2005,2007 grischka
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifdef TCC_TARGET_PE
-
-ST_FUNC int tcc_tool_impdef(TCCState *s1, int argc, char **argv)
-{
- int ret, v, i;
- char infile[260];
- char outfile[260];
-
- const char *file;
- char *p, *q;
- FILE *fp, *op;
-
-#ifdef _WIN32
- char path[260];
-#endif
-
- infile[0] = outfile[0] = 0;
- fp = op = NULL;
- ret = 1;
- p = NULL;
- v = 0;
-
- for (i = 1; i < argc; ++i) {
- const char *a = argv[i];
- if ('-' == a[0]) {
- if (0 == strcmp(a, "-v")) {
- v = 1;
- } else if (0 == strcmp(a, "-o")) {
- if (++i == argc)
- goto usage;
- strcpy(outfile, argv[i]);
- } else
- goto usage;
- } else if (0 == infile[0])
- strcpy(infile, a);
- else
- goto usage;
- }
-
- if (0 == infile[0]) {
-usage:
- fprintf(stderr,
- "usage: tcc -impdef library.dll [-v] [-o outputfile]\n"
- "create export definition file (.def) from dll\n"
- );
- goto the_end;
- }
-
- if (0 == outfile[0]) {
- strcpy(outfile, tcc_basename(infile));
- q = strrchr(outfile, '.');
- if (NULL == q)
- q = strchr(outfile, 0);
- strcpy(q, ".def");
- }
-
- file = infile;
-#ifdef _WIN32
- if (SearchPath(NULL, file, ".dll", sizeof path, path, NULL))
- file = path;
-#endif
- ret = tcc_get_dllexports(file, &p);
- if (ret || !p) {
- fprintf(stderr, "tcc: impdef: %s '%s'\n",
- ret == -1 ? "can't find file" :
- ret == 1 ? "can't read symbols" :
- ret == 0 ? "no symbols found in" :
- "unknown file type", file);
- ret = 1;
- goto the_end;
- }
-
- if (v)
- printf("-> %s\n", file);
-
- op = fopen(outfile, "wb");
- if (NULL == op) {
- fprintf(stderr, "tcc: impdef: could not create output file: %s\n", outfile);
- goto the_end;
- }
-
- fprintf(op, "LIBRARY %s\n\nEXPORTS\n", tcc_basename(file));
- for (q = p, i = 0; *q; ++i) {
- fprintf(op, "%s\n", q);
- q += strlen(q) + 1;
- }
-
- if (v)
- printf("<- %s (%d symbol%s)\n", outfile, i, &"s"[i<2]);
-
- ret = 0;
-
-the_end:
- if (p)
- tcc_free(p);
- if (fp)
- fclose(fp);
- if (op)
- fclose(op);
- return ret;
-}
-
-#endif /* TCC_TARGET_PE */
-
-/* -------------------------------------------------------------- */
-/*
- * TCC - Tiny C Compiler
- *
- * Copyright (c) 2001-2004 Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-/* re-execute the i386/x86_64 cross-compilers with tcc -m32/-m64: */
-
-#if !defined TCC_TARGET_I386 && !defined TCC_TARGET_X86_64
-
-ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int option)
-{
- tcc_error_noabort("-m%d not implemented.", option);
- return 1;
-}
-
-#else
-#ifdef _WIN32
-#include <process.h>
-
-static char *str_replace(const char *str, const char *p, const char *r)
-{
- const char *s, *s0;
- char *d, *d0;
- int sl, pl, rl;
-
- sl = strlen(str);
- pl = strlen(p);
- rl = strlen(r);
- for (d0 = NULL;; d0 = tcc_malloc(sl + 1)) {
- for (d = d0, s = str; s0 = s, s = strstr(s, p), s; s += pl) {
- if (d) {
- memcpy(d, s0, sl = s - s0), d += sl;
- memcpy(d, r, rl), d += rl;
- } else
- sl += rl - pl;
- }
- if (d) {
- strcpy(d, s0);
- return d0;
- }
- }
-}
-
-static int execvp_win32(const char *prog, char **argv)
-{
- int ret; char **p;
- /* replace all " by \" */
- for (p = argv; *p; ++p)
- if (strchr(*p, '"'))
- *p = str_replace(*p, "\"", "\\\"");
- ret = _spawnvp(P_NOWAIT, prog, (const char *const*)argv);
- if (-1 == ret)
- return ret;
- _cwait(&ret, ret, WAIT_CHILD);
- exit(ret);
-}
-#define execvp execvp_win32
-#endif /* _WIN32 */
-
-ST_FUNC int tcc_tool_cross(TCCState *s1, char **argv, int target)
-{
- char program[4096];
- char *a0 = argv[0];
- int prefix = tcc_basename(a0) - a0;
-
- snprintf(program, sizeof program,
- "%.*s%s"
-#ifdef TCC_TARGET_PE
- "-win32"
-#endif
- "-tcc"
-#ifdef _WIN32
- ".exe"
-#endif
- , prefix, a0, target == 64 ? "x86_64" : "i386");
-
- if (strcmp(a0, program))
- execvp(argv[0] = program, argv);
- tcc_error_noabort("could not run '%s'", program);
- return 1;
-}
-
-#endif /* TCC_TARGET_I386 && TCC_TARGET_X86_64 */
-/* -------------------------------------------------------------- */
-/* enable commandline wildcard expansion (tcc -o x.exe *.c) */
-
-#ifdef _WIN32
-const int _CRT_glob = 1;
-#ifndef _CRT_glob
-const int _dowildcard = 1;
-#endif
-#endif
-
-/* -------------------------------------------------------------- */
-/* generate xxx.d file */
-
-static char *escape_target_dep(const char *s) {
- char *res = tcc_malloc(strlen(s) * 2 + 1);
- int j;
- for (j = 0; *s; s++, j++) {
- if (is_space(*s)) {
- res[j++] = '\\';
- }
- res[j] = *s;
- }
- res[j] = '\0';
- return res;
-}
-
-ST_FUNC int gen_makedeps(TCCState *s1, const char *target, const char *filename)
-{
- FILE *depout;
- char buf[1024], *escaped_target;
- int i, k;
-
- if (!filename) {
- /* compute filename automatically: dir/file.o -> dir/file.d */
- snprintf(buf, sizeof buf, "%.*s.d",
- (int)(tcc_fileextension(target) - target), target);
- filename = buf;
- }
-
- if(!strcmp(filename, "-"))
- depout = fdopen(1, "w");
- else
- /* XXX return err codes instead of error() ? */
- depout = fopen(filename, "w");
- if (!depout)
- return tcc_error_noabort("could not open '%s'", filename);
- if (s1->verbose)
- printf("<- %s\n", filename);
-
- fprintf(depout, "%s:", target);
- for (i = 0; i<s1->nb_target_deps; ++i) {
- for (k = 0; k < i; ++k)
- if (0 == strcmp(s1->target_deps[i], s1->target_deps[k]))
- goto next;
- escaped_target = escape_target_dep(s1->target_deps[i]);
- fprintf(depout, " \\\n %s", escaped_target);
- tcc_free(escaped_target);
- next:;
- }
- fprintf(depout, "\n");
- fclose(depout);
- return 0;
-}
-
-/* -------------------------------------------------------------- */
diff --git a/tinycc/texi2pod.pl b/tinycc/texi2pod.pl
deleted file mode 100644
index d86e176..0000000
--- a/tinycc/texi2pod.pl
+++ /dev/null
@@ -1,427 +0,0 @@
-#! /usr/bin/perl -w
-
-# Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
-
-# This file is part of GNU CC.
-
-# GNU CC is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2, or (at your option)
-# any later version.
-
-# GNU CC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with GNU CC; see the file COPYING. If not, write to
-# the Free Software Foundation, 59 Temple Place - Suite 330,
-# Boston MA 02111-1307, USA.
-
-# This does trivial (and I mean _trivial_) conversion of Texinfo
-# markup to Perl POD format. It's intended to be used to extract
-# something suitable for a manpage from a Texinfo document.
-
-$output = 0;
-$skipping = 0;
-%sects = ();
-$section = "";
-@icstack = ();
-@endwstack = ();
-@skstack = ();
-@instack = ();
-$shift = "";
-%defs = ();
-$fnno = 1;
-$inf = "";
-$ibase = "";
-
-while ($_ = shift) {
- if (/^-D(.*)$/) {
- if ($1 ne "") {
- $flag = $1;
- } else {
- $flag = shift;
- }
- $value = "";
- ($flag, $value) = ($flag =~ /^([^=]+)(?:=(.+))?/);
- die "no flag specified for -D\n"
- unless $flag ne "";
- die "flags may only contain letters, digits, hyphens, dashes and underscores\n"
- unless $flag =~ /^[a-zA-Z0-9_-]+$/;
- $defs{$flag} = $value;
- } elsif (/^-/) {
- usage();
- } else {
- $in = $_, next unless defined $in;
- $out = $_, next unless defined $out;
- usage();
- }
-}
-
-if (defined $in) {
- $inf = gensym();
- open($inf, "<$in") or die "opening \"$in\": $!\n";
- $ibase = $1 if $in =~ m|^(.+)/[^/]+$|;
-} else {
- $inf = \*STDIN;
-}
-
-if (defined $out) {
- open(STDOUT, ">$out") or die "opening \"$out\": $!\n";
-}
-
-while(defined $inf) {
-while(<$inf>) {
- # Certain commands are discarded without further processing.
- /^\@(?:
- [a-z]+index # @*index: useful only in complete manual
- |need # @need: useful only in printed manual
- |(?:end\s+)?group # @group .. @end group: ditto
- |page # @page: ditto
- |node # @node: useful only in .info file
- |(?:end\s+)?ifnottex # @ifnottex .. @end ifnottex: use contents
- )\b/x and next;
-
- chomp;
-
- # Look for filename and title markers.
- /^\@setfilename\s+([^.]+)/ and $fn = $1, next;
- /^\@settitle\s+([^.]+)/ and $tl = postprocess($1), next;
-
- # Identify a man title but keep only the one we are interested in.
- /^\@c\s+man\s+title\s+([A-Za-z0-9-]+)\s+(.+)/ and do {
- if (exists $defs{$1}) {
- $fn = $1;
- $tl = postprocess($2);
- }
- next;
- };
-
- # Look for blocks surrounded by @c man begin SECTION ... @c man end.
- # This really oughta be @ifman ... @end ifman and the like, but such
- # would require rev'ing all other Texinfo translators.
- /^\@c\s+man\s+begin\s+([A-Z]+)\s+([A-Za-z0-9-]+)/ and do {
- $output = 1 if exists $defs{$2};
- $sect = $1;
- next;
- };
- /^\@c\s+man\s+begin\s+([A-Z]+)/ and $sect = $1, $output = 1, next;
- /^\@c\s+man\s+end/ and do {
- $sects{$sect} = "" unless exists $sects{$sect};
- $sects{$sect} .= postprocess($section);
- $section = "";
- $output = 0;
- next;
- };
-
- # handle variables
- /^\@set\s+([a-zA-Z0-9_-]+)\s*(.*)$/ and do {
- $defs{$1} = $2;
- next;
- };
- /^\@clear\s+([a-zA-Z0-9_-]+)/ and do {
- delete $defs{$1};
- next;
- };
-
- next unless $output;
-
- # Discard comments. (Can't do it above, because then we'd never see
- # @c man lines.)
- /^\@c\b/ and next;
-
- # End-block handler goes up here because it needs to operate even
- # if we are skipping.
- /^\@end\s+([a-z]+)/ and do {
- # Ignore @end foo, where foo is not an operation which may
- # cause us to skip, if we are presently skipping.
- my $ended = $1;
- next if $skipping && $ended !~ /^(?:ifset|ifclear|ignore|menu|iftex)$/;
-
- die "\@end $ended without \@$ended at line $.\n" unless defined $endw;
- die "\@$endw ended by \@end $ended at line $.\n" unless $ended eq $endw;
-
- $endw = pop @endwstack;
-
- if ($ended =~ /^(?:ifset|ifclear|ignore|menu|iftex)$/) {
- $skipping = pop @skstack;
- next;
- } elsif ($ended =~ /^(?:example|smallexample|display)$/) {
- $shift = "";
- $_ = ""; # need a paragraph break
- } elsif ($ended =~ /^(?:itemize|enumerate|[fv]?table)$/) {
- $_ = "\n=back\n";
- $ic = pop @icstack;
- } else {
- die "unknown command \@end $ended at line $.\n";
- }
- };
-
- # We must handle commands which can cause skipping even while we
- # are skipping, otherwise we will not process nested conditionals
- # correctly.
- /^\@ifset\s+([a-zA-Z0-9_-]+)/ and do {
- push @endwstack, $endw;
- push @skstack, $skipping;
- $endw = "ifset";
- $skipping = 1 unless exists $defs{$1};
- next;
- };
-
- /^\@ifclear\s+([a-zA-Z0-9_-]+)/ and do {
- push @endwstack, $endw;
- push @skstack, $skipping;
- $endw = "ifclear";
- $skipping = 1 if exists $defs{$1};
- next;
- };
-
- /^\@(ignore|menu|iftex)\b/ and do {
- push @endwstack, $endw;
- push @skstack, $skipping;
- $endw = $1;
- $skipping = 1;
- next;
- };
-
- next if $skipping;
-
- # Character entities. First the ones that can be replaced by raw text
- # or discarded outright:
- s/\@copyright\{\}/(c)/g;
- s/\@dots\{\}/.../g;
- s/\@enddots\{\}/..../g;
- s/\@([.!? ])/$1/g;
- s/\@[:-]//g;
- s/\@bullet(?:\{\})?/*/g;
- s/\@TeX\{\}/TeX/g;
- s/\@pounds\{\}/\#/g;
- s/\@minus(?:\{\})?/-/g;
- s/\\,/,/g;
-
- # Now the ones that have to be replaced by special escapes
- # (which will be turned back into text by unmunge())
- s/&/&amp;/g;
- s/\@\{/&lbrace;/g;
- s/\@\}/&rbrace;/g;
- s/\@\@/&at;/g;
-
- # Inside a verbatim block, handle @var specially.
- if ($shift ne "") {
- s/\@var\{([^\}]*)\}/<$1>/g;
- }
-
- # POD doesn't interpret E<> inside a verbatim block.
- if ($shift eq "") {
- s/</&lt;/g;
- s/>/&gt;/g;
- } else {
- s/</&LT;/g;
- s/>/&GT;/g;
- }
-
- # Single line command handlers.
-
- /^\@include\s+(.+)$/ and do {
- push @instack, $inf;
- $inf = gensym();
-
- # Try cwd and $ibase.
- open($inf, "<" . $1)
- or open($inf, "<" . $ibase . "/" . $1)
- or die "cannot open $1 or $ibase/$1: $!\n";
- next;
- };
-
- /^\@(?:section|unnumbered|unnumberedsec|center)\s+(.+)$/
- and $_ = "\n=head2 $1\n";
- /^\@subsection\s+(.+)$/
- and $_ = "\n=head3 $1\n";
-
- # Block command handlers:
- /^\@itemize\s+(\@[a-z]+|\*|-)/ and do {
- push @endwstack, $endw;
- push @icstack, $ic;
- $ic = $1;
- $_ = "\n=over 4\n";
- $endw = "itemize";
- };
-
- /^\@enumerate(?:\s+([a-zA-Z0-9]+))?/ and do {
- push @endwstack, $endw;
- push @icstack, $ic;
- if (defined $1) {
- $ic = $1 . ".";
- } else {
- $ic = "1.";
- }
- $_ = "\n=over 4\n";
- $endw = "enumerate";
- };
-
- /^\@([fv]?table)\s+(\@[a-z]+)/ and do {
- push @endwstack, $endw;
- push @icstack, $ic;
- $endw = $1;
- $ic = $2;
- $ic =~ s/\@(?:samp|strong|key|gcctabopt|option|env)/B/;
- $ic =~ s/\@(?:code|kbd)/C/;
- $ic =~ s/\@(?:dfn|var|emph|cite|i)/I/;
- $ic =~ s/\@(?:file)/F/;
- $_ = "\n=over 4\n";
- };
-
- /^\@((?:small)?example|display)/ and do {
- push @endwstack, $endw;
- $endw = $1;
- $shift = "\t";
- $_ = ""; # need a paragraph break
- };
-
- /^\@itemx?\s*(.+)?$/ and do {
- if (defined $1) {
- # Entity escapes prevent munging by the <> processing below.
- $_ = "\n=item $ic\&LT;$1\&GT;\n";
- } else {
- $_ = "\n=item $ic\n";
- $ic =~ y/A-Ya-y/B-Zb-z/;
- $ic =~ s/(\d+)/$1 + 1/eg;
- }
- };
-
- $section .= $shift.$_."\n";
-}
-# End of current file.
-close($inf);
-$inf = pop @instack;
-}
-
-die "No filename or title\n" unless defined $fn && defined $tl;
-
-$sects{NAME} = "$fn \- $tl\n";
-$sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES};
-
-for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS ENVIRONMENT FILES
- BUGS NOTES FOOTNOTES SEEALSO AUTHOR COPYRIGHT)) {
- if(exists $sects{$sect}) {
- $head = $sect;
- $head =~ s/SEEALSO/SEE ALSO/;
- print "=head1 $head\n\n";
- print scalar unmunge ($sects{$sect});
- print "\n";
- }
-}
-
-sub usage
-{
- die "usage: $0 [-D toggle...] [infile [outfile]]\n";
-}
-
-sub postprocess
-{
- local $_ = $_[0];
-
- # @value{foo} is replaced by whatever 'foo' is defined as.
- while (m/(\@value\{([a-zA-Z0-9_-]+)\})/g) {
- if (! exists $defs{$2}) {
- print STDERR "Option $2 not defined\n";
- s/\Q$1\E//;
- } else {
- $value = $defs{$2};
- s/\Q$1\E/$value/;
- }
- }
-
- # Formatting commands.
- # Temporary escape for @r.
- s/\@r\{([^\}]*)\}/R<$1>/g;
- s/\@(?:dfn|var|emph|cite|i)\{([^\}]*)\}/I<$1>/g;
- s/\@(?:code|kbd)\{([^\}]*)\}/C<$1>/g;
- s/\@(?:gccoptlist|samp|strong|key|option|env|command|b)\{([^\}]*)\}/B<$1>/g;
- s/\@sc\{([^\}]*)\}/\U$1/g;
- s/\@file\{([^\}]*)\}/F<$1>/g;
- s/\@w\{([^\}]*)\}/S<$1>/g;
- s/\@(?:dmn|math)\{([^\}]*)\}/$1/g;
-
- # Cross references are thrown away, as are @noindent and @refill.
- # (@noindent is impossible in .pod, and @refill is unnecessary.)
- # @* is also impossible in .pod; we discard it and any newline that
- # follows it. Similarly, our macro @gol must be discarded.
-
- s/\(?\@xref\{(?:[^\}]*)\}(?:[^.<]|(?:<[^<>]*>))*\.\)?//g;
- s/\s+\(\@pxref\{(?:[^\}]*)\}\)//g;
- s/;\s+\@pxref\{(?:[^\}]*)\}//g;
- s/\@noindent\s*//g;
- s/\@refill//g;
- s/\@gol//g;
- s/\@\*\s*\n?//g;
-
- # @uref can take one, two, or three arguments, with different
- # semantics each time. @url and @email are just like @uref with
- # one argument, for our purposes.
- s/\@(?:uref|url|email)\{([^\},]*)\}/&lt;B<$1>&gt;/g;
- s/\@uref\{([^\},]*),([^\},]*)\}/$2 (C<$1>)/g;
- s/\@uref\{([^\},]*),([^\},]*),([^\},]*)\}/$3/g;
-
- # Turn B<blah I<blah> blah> into B<blah> I<blah> B<blah> to
- # match Texinfo semantics of @emph inside @samp. Also handle @r
- # inside bold.
- s/&LT;/</g;
- s/&GT;/>/g;
- 1 while s/B<((?:[^<>]|I<[^<>]*>)*)R<([^>]*)>/B<$1>${2}B</g;
- 1 while (s/B<([^<>]*)I<([^>]+)>/B<$1>I<$2>B</g);
- 1 while (s/I<([^<>]*)B<([^>]+)>/I<$1>B<$2>I</g);
- s/[BI]<>//g;
- s/([BI])<(\s+)([^>]+)>/$2$1<$3>/g;
- s/([BI])<([^>]+?)(\s+)>/$1<$2>$3/g;
-
- # Extract footnotes. This has to be done after all other
- # processing because otherwise the regexp will choke on formatting
- # inside @footnote.
- while (/\@footnote/g) {
- s/\@footnote\{([^\}]+)\}/[$fnno]/;
- add_footnote($1, $fnno);
- $fnno++;
- }
-
- return $_;
-}
-
-sub unmunge
-{
- # Replace escaped symbols with their equivalents.
- local $_ = $_[0];
-
- s/&lt;/E<lt>/g;
- s/&gt;/E<gt>/g;
- s/&lbrace;/\{/g;
- s/&rbrace;/\}/g;
- s/&at;/\@/g;
- s/&amp;/&/g;
- return $_;
-}
-
-sub add_footnote
-{
- unless (exists $sects{FOOTNOTES}) {
- $sects{FOOTNOTES} = "\n=over 4\n\n";
- }
-
- $sects{FOOTNOTES} .= "=item $fnno.\n\n"; $fnno++;
- $sects{FOOTNOTES} .= $_[0];
- $sects{FOOTNOTES} .= "\n\n";
-}
-
-# stolen from Symbol.pm
-{
- my $genseq = 0;
- sub gensym
- {
- my $name = "GEN" . $genseq++;
- my $ref = \*{$name};
- delete $::{$name};
- return $ref;
- }
-}
diff --git a/tinycc/x86_64-asm.h b/tinycc/x86_64-asm.h
deleted file mode 100644
index 339e1df..0000000
--- a/tinycc/x86_64-asm.h
+++ /dev/null
@@ -1,544 +0,0 @@
- DEF_ASM_OP0(clc, 0xf8) /* must be first OP0 */
- DEF_ASM_OP0(cld, 0xfc)
- DEF_ASM_OP0(cli, 0xfa)
- DEF_ASM_OP0(clts, 0x0f06)
- DEF_ASM_OP0(cmc, 0xf5)
- DEF_ASM_OP0(lahf, 0x9f)
- DEF_ASM_OP0(sahf, 0x9e)
- DEF_ASM_OP0(pushfq, 0x9c)
- DEF_ASM_OP0(popfq, 0x9d)
- DEF_ASM_OP0(pushf, 0x9c)
- DEF_ASM_OP0(popf, 0x9d)
- DEF_ASM_OP0(stc, 0xf9)
- DEF_ASM_OP0(std, 0xfd)
- DEF_ASM_OP0(sti, 0xfb)
- DEF_ASM_OP0(aaa, 0x37)
- DEF_ASM_OP0(aas, 0x3f)
- DEF_ASM_OP0(daa, 0x27)
- DEF_ASM_OP0(das, 0x2f)
- DEF_ASM_OP0(aad, 0xd50a)
- DEF_ASM_OP0(aam, 0xd40a)
- DEF_ASM_OP0(cbw, 0x6698)
- DEF_ASM_OP0(cwd, 0x6699)
- DEF_ASM_OP0(cwde, 0x98)
- DEF_ASM_OP0(cdq, 0x99)
- DEF_ASM_OP0(cbtw, 0x6698)
- DEF_ASM_OP0(cwtl, 0x98)
- DEF_ASM_OP0(cwtd, 0x6699)
- DEF_ASM_OP0(cltd, 0x99)
- DEF_ASM_OP0(cqto, 0x4899)
- DEF_ASM_OP0(int3, 0xcc)
- DEF_ASM_OP0(into, 0xce)
- DEF_ASM_OP0(iret, 0xcf)
- DEF_ASM_OP0(iretw, 0x66cf)
- DEF_ASM_OP0(iretl, 0xcf)
- DEF_ASM_OP0(iretq, 0x48cf)
- DEF_ASM_OP0(rsm, 0x0faa)
- DEF_ASM_OP0(hlt, 0xf4)
- DEF_ASM_OP0(wait, 0x9b)
- DEF_ASM_OP0(nop, 0x90)
- DEF_ASM_OP0(pause, 0xf390)
- DEF_ASM_OP0(xlat, 0xd7)
-
- DEF_ASM_OP0L(vmcall, 0xc1, 0, OPC_0F01)
- DEF_ASM_OP0L(vmlaunch, 0xc2, 0, OPC_0F01)
- DEF_ASM_OP0L(vmresume, 0xc3, 0, OPC_0F01)
- DEF_ASM_OP0L(vmxoff, 0xc4, 0, OPC_0F01)
-
- /* strings */
-ALT(DEF_ASM_OP0L(cmpsb, 0xa6, 0, OPC_BWLX))
-ALT(DEF_ASM_OP0L(scmpb, 0xa6, 0, OPC_BWLX))
-
-ALT(DEF_ASM_OP0L(insb, 0x6c, 0, OPC_BWL))
-ALT(DEF_ASM_OP0L(outsb, 0x6e, 0, OPC_BWL))
-
-ALT(DEF_ASM_OP0L(lodsb, 0xac, 0, OPC_BWLX))
-ALT(DEF_ASM_OP0L(slodb, 0xac, 0, OPC_BWLX))
-
-ALT(DEF_ASM_OP0L(movsb, 0xa4, 0, OPC_BWLX))
-ALT(DEF_ASM_OP0L(smovb, 0xa4, 0, OPC_BWLX))
-
-ALT(DEF_ASM_OP0L(scasb, 0xae, 0, OPC_BWLX))
-ALT(DEF_ASM_OP0L(sscab, 0xae, 0, OPC_BWLX))
-
-ALT(DEF_ASM_OP0L(stosb, 0xaa, 0, OPC_BWLX))
-ALT(DEF_ASM_OP0L(sstob, 0xaa, 0, OPC_BWLX))
-
- /* bits */
-
-ALT(DEF_ASM_OP2(bsfw, 0x0fbc, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(bsrw, 0x0fbd, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-
-ALT(DEF_ASM_OP2(btw, 0x0fa3, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btw, 0x0fba, 4, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(btsw, 0x0fab, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btsw, 0x0fba, 5, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(btrw, 0x0fb3, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btrw, 0x0fba, 6, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW | OPT_EA))
-
-ALT(DEF_ASM_OP2(popcntw, 0xf30fb8, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-
-ALT(DEF_ASM_OP2(tzcntw, 0xf30fbc, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(lzcntw, 0xf30fbd, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-
- /* prefixes */
- DEF_ASM_OP0(lock, 0xf0)
- DEF_ASM_OP0(rep, 0xf3)
- DEF_ASM_OP0(repe, 0xf3)
- DEF_ASM_OP0(repz, 0xf3)
- DEF_ASM_OP0(repne, 0xf2)
- DEF_ASM_OP0(repnz, 0xf2)
-
- DEF_ASM_OP0(invd, 0x0f08)
- DEF_ASM_OP0(wbinvd, 0x0f09)
- DEF_ASM_OP0(cpuid, 0x0fa2)
- DEF_ASM_OP0(wrmsr, 0x0f30)
- DEF_ASM_OP0(rdtsc, 0x0f31)
- DEF_ASM_OP0(rdmsr, 0x0f32)
- DEF_ASM_OP0(rdpmc, 0x0f33)
-
- DEF_ASM_OP0(syscall, 0x0f05)
- DEF_ASM_OP0(sysret, 0x0f07)
- DEF_ASM_OP0L(sysretq, 0x480f07, 0, 0)
- DEF_ASM_OP0(ud2, 0x0f0b)
-
- /* NOTE: we took the same order as gas opcode definition order */
-/* Right now we can't express the fact that 0xa1/0xa3 can't use $eax and a
- 32 bit moffset as operands.
-ALT(DEF_ASM_OP2(movb, 0xa0, 0, OPC_BWLX, OPT_ADDR, OPT_EAX))
-ALT(DEF_ASM_OP2(movb, 0xa2, 0, OPC_BWLX, OPT_EAX, OPT_ADDR)) */
-ALT(DEF_ASM_OP2(movb, 0x88, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(movb, 0x8a, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
-/* The moves are special: the 0xb8 form supports IM64 (the only insn that
- does) with REG64. It doesn't support IM32 with REG64, it would use
- the full movabs form (64bit immediate). For IM32->REG64 we prefer
- the 0xc7 opcode. So disallow all 64bit forms and code the rest by hand. */
-ALT(DEF_ASM_OP2(movb, 0xb0, 0, OPC_REG | OPC_BWLX, OPT_IM, OPT_REG))
-ALT(DEF_ASM_OP2(mov, 0xb8, 0, OPC_REG, OPT_IM64, OPT_REG64))
-ALT(DEF_ASM_OP2(movq, 0xb8, 0, OPC_REG, OPT_IM64, OPT_REG64))
-ALT(DEF_ASM_OP2(movb, 0xc6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP2(movw, 0x8c, 0, OPC_MODRM | OPC_WLX, OPT_SEG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(movw, 0x8e, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_SEG))
-
-ALT(DEF_ASM_OP2(movw, 0x0f20, 0, OPC_MODRM | OPC_WLX, OPT_CR, OPT_REG64))
-ALT(DEF_ASM_OP2(movw, 0x0f21, 0, OPC_MODRM | OPC_WLX, OPT_DB, OPT_REG64))
-ALT(DEF_ASM_OP2(movw, 0x0f22, 0, OPC_MODRM | OPC_WLX, OPT_REG64, OPT_CR))
-ALT(DEF_ASM_OP2(movw, 0x0f23, 0, OPC_MODRM | OPC_WLX, OPT_REG64, OPT_DB))
-
-ALT(DEF_ASM_OP2(movsbw, 0x660fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG16))
-ALT(DEF_ASM_OP2(movsbl, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(movsbq, 0x0fbe, 0, OPC_MODRM, OPT_REG8 | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(movswl, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(movswq, 0x0fbf, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG))
-ALT(DEF_ASM_OP2(movslq, 0x63, 0, OPC_MODRM, OPT_REG32 | OPT_EA, OPT_REG))
-ALT(DEF_ASM_OP2(movzbw, 0x0fb6, 0, OPC_MODRM | OPC_WLX, OPT_REG8 | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(movzwq, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG))
-
-ALT(DEF_ASM_OP1(pushq, 0x6a, 0, 0, OPT_IM8S))
-ALT(DEF_ASM_OP1(push, 0x6a, 0, 0, OPT_IM8S))
-ALT(DEF_ASM_OP1(pushw, 0x666a, 0, 0, OPT_IM8S))
-ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WLX, OPT_REG64))
-ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WLX, OPT_REG16))
-ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WLX, OPT_REG64 | OPT_EA))
-ALT(DEF_ASM_OP1(pushw, 0x6668, 0, 0, OPT_IM16))
-ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WLX, OPT_IM32))
-ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WLX, OPT_SEG))
-
-ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLX, OPT_REG64))
-ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WLX, OPT_REG16))
-ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WLX, OPT_REGW | OPT_EA))
-ALT(DEF_ASM_OP1(popw, 0x07, 0, OPC_WLX, OPT_SEG))
-
-ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLX, OPT_REGW, OPT_EAX))
-ALT(DEF_ASM_OP2(xchgw, 0x90, 0, OPC_REG | OPC_WLX, OPT_EAX, OPT_REGW))
-ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(xchgb, 0x86, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
-
-ALT(DEF_ASM_OP2(inb, 0xe4, 0, OPC_BWL, OPT_IM8, OPT_EAX))
-ALT(DEF_ASM_OP1(inb, 0xe4, 0, OPC_BWL, OPT_IM8))
-ALT(DEF_ASM_OP2(inb, 0xec, 0, OPC_BWL, OPT_DX, OPT_EAX))
-ALT(DEF_ASM_OP1(inb, 0xec, 0, OPC_BWL, OPT_DX))
-
-ALT(DEF_ASM_OP2(outb, 0xe6, 0, OPC_BWL, OPT_EAX, OPT_IM8))
-ALT(DEF_ASM_OP1(outb, 0xe6, 0, OPC_BWL, OPT_IM8))
-ALT(DEF_ASM_OP2(outb, 0xee, 0, OPC_BWL, OPT_EAX, OPT_DX))
-ALT(DEF_ASM_OP1(outb, 0xee, 0, OPC_BWL, OPT_DX))
-
-ALT(DEF_ASM_OP2(leaw, 0x8d, 0, OPC_MODRM | OPC_WLX, OPT_EA, OPT_REG))
-
-ALT(DEF_ASM_OP2(les, 0xc4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lds, 0xc5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lss, 0x0fb2, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lfs, 0x0fb4, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32))
-
- /* arith */
-ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */
-ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
-ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLX, OPT_IM, OPT_EAX))
-ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG))
-
-ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG))
-ALT(DEF_ASM_OP2(testb, 0xa8, 0, OPC_BWLX, OPT_IM, OPT_EAX))
-ALT(DEF_ASM_OP2(testb, 0xf6, 0, OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG))
-
-ALT(DEF_ASM_OP1(incb, 0xfe, 0, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP1(decb, 0xfe, 1, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP1(notb, 0xf6, 2, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP1(negb, 0xf6, 3, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP1(mulb, 0xf6, 4, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP1(imulb, 0xf6, 5, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-
-ALT(DEF_ASM_OP2(imulw, 0x0faf, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG))
-ALT(DEF_ASM_OP3(imulw, 0x6b, 0, OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(imulw, 0x6b, 0, OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_REGW))
-ALT(DEF_ASM_OP3(imulw, 0x69, 0, OPC_MODRM | OPC_WLX, OPT_IMW, OPT_REGW | OPT_EA, OPT_REGW))
-ALT(DEF_ASM_OP2(imulw, 0x69, 0, OPC_MODRM | OPC_WLX, OPT_IMW, OPT_REGW))
-
-ALT(DEF_ASM_OP1(divb, 0xf6, 6, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP2(divb, 0xf6, 6, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA, OPT_EAX))
-ALT(DEF_ASM_OP1(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA))
-ALT(DEF_ASM_OP2(idivb, 0xf6, 7, OPC_MODRM | OPC_BWLX, OPT_REG | OPT_EA, OPT_EAX))
-
- /* shifts */
-ALT(DEF_ASM_OP2(rolb, 0xc0, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_IM8, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP2(rolb, 0xd2, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_CL, OPT_EA | OPT_REG))
-ALT(DEF_ASM_OP1(rolb, 0xd0, 0, OPC_MODRM | OPC_BWLX | OPC_SHIFT, OPT_EA | OPT_REG))
-
-ALT(DEF_ASM_OP3(shldw, 0x0fa4, 0, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP3(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WLX, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP2(shldw, 0x0fa5, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP3(shrdw, 0x0fac, 0, OPC_MODRM | OPC_WLX, OPT_IM8, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP3(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WLX, OPT_CL, OPT_REGW, OPT_EA | OPT_REGW))
-ALT(DEF_ASM_OP2(shrdw, 0x0fad, 0, OPC_MODRM | OPC_WLX, OPT_REGW, OPT_EA | OPT_REGW))
-
-ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
-ALT(DEF_ASM_OP1(call, 0xe8, 0, 0, OPT_DISP))
-ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
-ALT(DEF_ASM_OP1(jmp, 0xeb, 0, 0, OPT_DISP8))
-
-ALT(DEF_ASM_OP1(lcall, 0xff, 3, OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP1(ljmp, 0xff, 5, OPC_MODRM, OPT_EA))
- DEF_ASM_OP1(ljmpw, 0x66ff, 5, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(ljmpl, 0xff, 5, OPC_MODRM, OPT_EA)
-
-ALT(DEF_ASM_OP1(int, 0xcd, 0, 0, OPT_IM8))
-ALT(DEF_ASM_OP1(seto, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
-ALT(DEF_ASM_OP1(setob, 0x0f90, 0, OPC_MODRM | OPC_TEST, OPT_REG8 | OPT_EA))
- DEF_ASM_OP2(enter, 0xc8, 0, 0, OPT_IM16, OPT_IM8)
- DEF_ASM_OP0(leave, 0xc9)
- DEF_ASM_OP0(ret, 0xc3)
- DEF_ASM_OP0(retq, 0xc3)
-ALT(DEF_ASM_OP1(retq, 0xc2, 0, 0, OPT_IM16))
-ALT(DEF_ASM_OP1(ret, 0xc2, 0, 0, OPT_IM16))
- DEF_ASM_OP0(lret, 0xcb)
-ALT(DEF_ASM_OP1(lret, 0xca, 0, 0, OPT_IM16))
-
-ALT(DEF_ASM_OP1(jo, 0x70, 0, OPC_TEST, OPT_DISP8))
- DEF_ASM_OP1(loopne, 0xe0, 0, 0, OPT_DISP8)
- DEF_ASM_OP1(loopnz, 0xe0, 0, 0, OPT_DISP8)
- DEF_ASM_OP1(loope, 0xe1, 0, 0, OPT_DISP8)
- DEF_ASM_OP1(loopz, 0xe1, 0, 0, OPT_DISP8)
- DEF_ASM_OP1(loop, 0xe2, 0, 0, OPT_DISP8)
- DEF_ASM_OP1(jecxz, 0x67e3, 0, 0, OPT_DISP8)
-
- /* float */
- /* specific fcomp handling */
-ALT(DEF_ASM_OP0L(fcomp, 0xd8d9, 0, 0))
-
-ALT(DEF_ASM_OP1(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST))
-ALT(DEF_ASM_OP2(fadd, 0xd8c0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
-ALT(DEF_ASM_OP2(fadd, 0xdcc0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
-ALT(DEF_ASM_OP2(fmul, 0xdcc8, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
-ALT(DEF_ASM_OP0L(fadd, 0xdec1, 0, OPC_FARITH))
-ALT(DEF_ASM_OP1(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST))
-ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST, OPT_ST0))
-ALT(DEF_ASM_OP2(faddp, 0xdec0, 0, OPC_FARITH | OPC_REG, OPT_ST0, OPT_ST))
-ALT(DEF_ASM_OP0L(faddp, 0xdec1, 0, OPC_FARITH))
-ALT(DEF_ASM_OP1(fadds, 0xd8, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP1(fiaddl, 0xda, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP1(faddl, 0xdc, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-ALT(DEF_ASM_OP1(fiadds, 0xde, 0, OPC_FARITH | OPC_MODRM, OPT_EA))
-
- DEF_ASM_OP0(fucompp, 0xdae9)
- DEF_ASM_OP0(ftst, 0xd9e4)
- DEF_ASM_OP0(fxam, 0xd9e5)
- DEF_ASM_OP0(fld1, 0xd9e8)
- DEF_ASM_OP0(fldl2t, 0xd9e9)
- DEF_ASM_OP0(fldl2e, 0xd9ea)
- DEF_ASM_OP0(fldpi, 0xd9eb)
- DEF_ASM_OP0(fldlg2, 0xd9ec)
- DEF_ASM_OP0(fldln2, 0xd9ed)
- DEF_ASM_OP0(fldz, 0xd9ee)
-
- DEF_ASM_OP0(f2xm1, 0xd9f0)
- DEF_ASM_OP0(fyl2x, 0xd9f1)
- DEF_ASM_OP0(fptan, 0xd9f2)
- DEF_ASM_OP0(fpatan, 0xd9f3)
- DEF_ASM_OP0(fxtract, 0xd9f4)
- DEF_ASM_OP0(fprem1, 0xd9f5)
- DEF_ASM_OP0(fdecstp, 0xd9f6)
- DEF_ASM_OP0(fincstp, 0xd9f7)
- DEF_ASM_OP0(fprem, 0xd9f8)
- DEF_ASM_OP0(fyl2xp1, 0xd9f9)
- DEF_ASM_OP0(fsqrt, 0xd9fa)
- DEF_ASM_OP0(fsincos, 0xd9fb)
- DEF_ASM_OP0(frndint, 0xd9fc)
- DEF_ASM_OP0(fscale, 0xd9fd)
- DEF_ASM_OP0(fsin, 0xd9fe)
- DEF_ASM_OP0(fcos, 0xd9ff)
- DEF_ASM_OP0(fchs, 0xd9e0)
- DEF_ASM_OP0(fabs, 0xd9e1)
- DEF_ASM_OP0(fninit, 0xdbe3)
- DEF_ASM_OP0(fnclex, 0xdbe2)
- DEF_ASM_OP0(fnop, 0xd9d0)
- DEF_ASM_OP0(fwait, 0x9b)
-
- /* fp load */
- DEF_ASM_OP1(fld, 0xd9c0, 0, OPC_REG, OPT_ST)
- DEF_ASM_OP1(fldl, 0xd9c0, 0, OPC_REG, OPT_ST)
- DEF_ASM_OP1(flds, 0xd9, 0, OPC_MODRM, OPT_EA)
-ALT(DEF_ASM_OP1(fldl, 0xdd, 0, OPC_MODRM, OPT_EA))
- DEF_ASM_OP1(fildl, 0xdb, 0, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fildq, 0xdf, 5, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fildll, 0xdf, 5, OPC_MODRM,OPT_EA)
- DEF_ASM_OP1(fldt, 0xdb, 5, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fbld, 0xdf, 4, OPC_MODRM, OPT_EA)
-
- /* fp store */
- DEF_ASM_OP1(fst, 0xddd0, 0, OPC_REG, OPT_ST)
- DEF_ASM_OP1(fstl, 0xddd0, 0, OPC_REG, OPT_ST)
- DEF_ASM_OP1(fsts, 0xd9, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fstps, 0xd9, 3, OPC_MODRM, OPT_EA)
-ALT(DEF_ASM_OP1(fstl, 0xdd, 2, OPC_MODRM, OPT_EA))
- DEF_ASM_OP1(fstpl, 0xdd, 3, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fist, 0xdf, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fistp, 0xdf, 3, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fistl, 0xdb, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fistpl, 0xdb, 3, OPC_MODRM, OPT_EA)
-
- DEF_ASM_OP1(fstp, 0xddd8, 0, OPC_REG, OPT_ST)
- DEF_ASM_OP1(fistpq, 0xdf, 7, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fistpll, 0xdf, 7, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fstpt, 0xdb, 7, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(fbstp, 0xdf, 6, OPC_MODRM, OPT_EA)
-
- /* exchange */
- DEF_ASM_OP0(fxch, 0xd9c9)
-ALT(DEF_ASM_OP1(fxch, 0xd9c8, 0, OPC_REG, OPT_ST))
-
- /* misc FPU */
- DEF_ASM_OP1(fucom, 0xdde0, 0, OPC_REG, OPT_ST )
- DEF_ASM_OP1(fucomp, 0xdde8, 0, OPC_REG, OPT_ST )
-
- DEF_ASM_OP0L(finit, 0xdbe3, 0, OPC_FWAIT)
- DEF_ASM_OP1(fldcw, 0xd9, 5, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fnstcw, 0xd9, 7, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fstcw, 0xd9, 7, OPC_MODRM | OPC_FWAIT, OPT_EA )
- DEF_ASM_OP0(fnstsw, 0xdfe0)
-ALT(DEF_ASM_OP1(fnstsw, 0xdfe0, 0, 0, OPT_EAX ))
-ALT(DEF_ASM_OP1(fnstsw, 0xdd, 7, OPC_MODRM, OPT_EA ))
- DEF_ASM_OP1(fstsw, 0xdfe0, 0, OPC_FWAIT, OPT_EAX )
-ALT(DEF_ASM_OP0L(fstsw, 0xdfe0, 0, OPC_FWAIT))
-ALT(DEF_ASM_OP1(fstsw, 0xdd, 7, OPC_MODRM | OPC_FWAIT, OPT_EA ))
- DEF_ASM_OP0L(fclex, 0xdbe2, 0, OPC_FWAIT)
- DEF_ASM_OP1(fnstenv, 0xd9, 6, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fstenv, 0xd9, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
- DEF_ASM_OP1(fldenv, 0xd9, 4, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fnsave, 0xdd, 6, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fsave, 0xdd, 6, OPC_MODRM | OPC_FWAIT, OPT_EA )
- DEF_ASM_OP1(frstor, 0xdd, 4, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(ffree, 0xddc0, 4, OPC_REG, OPT_ST )
- DEF_ASM_OP1(ffreep, 0xdfc0, 4, OPC_REG, OPT_ST )
- DEF_ASM_OP1(fxsave, 0x0fae, 0, OPC_MODRM, OPT_EA )
- DEF_ASM_OP1(fxrstor, 0x0fae, 1, OPC_MODRM, OPT_EA )
- /* The *q forms of fxrstor/fxsave use a REX prefix.
- If the operand would use extended registers we would have to modify
- it instead of generating a second one. Currently that's no
- problem with TCC, we don't use extended registers. */
- DEF_ASM_OP1(fxsaveq, 0x0fae, 0, OPC_MODRM | OPC_48, OPT_EA )
- DEF_ASM_OP1(fxrstorq, 0x0fae, 1, OPC_MODRM | OPC_48, OPT_EA )
-
- /* segments */
- DEF_ASM_OP2(arpl, 0x63, 0, OPC_MODRM, OPT_REG16, OPT_REG16 | OPT_EA)
-ALT(DEF_ASM_OP2(larw, 0x0f02, 0, OPC_MODRM | OPC_WLX, OPT_REG | OPT_EA, OPT_REG))
- DEF_ASM_OP1(lgdt, 0x0f01, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(lgdtq, 0x0f01, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(lidt, 0x0f01, 3, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(lidtq, 0x0f01, 3, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(lldt, 0x0f00, 2, OPC_MODRM, OPT_EA | OPT_REG)
- DEF_ASM_OP1(lmsw, 0x0f01, 6, OPC_MODRM, OPT_EA | OPT_REG)
-ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WLX, OPT_EA | OPT_REG, OPT_REG))
- DEF_ASM_OP1(ltr, 0x0f00, 3, OPC_MODRM, OPT_EA | OPT_REG16)
- DEF_ASM_OP1(sgdt, 0x0f01, 0, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(sgdtq, 0x0f01, 0, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(sidt, 0x0f01, 1, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(sidtq, 0x0f01, 1, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(sldt, 0x0f00, 0, OPC_MODRM, OPT_REG | OPT_EA)
- DEF_ASM_OP1(smsw, 0x0f01, 4, OPC_MODRM, OPT_REG | OPT_EA)
- DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM, OPT_REG32 | OPT_EA)
-ALT(DEF_ASM_OP1(str, 0x660f00, 1, OPC_MODRM, OPT_REG16))
-ALT(DEF_ASM_OP1(str, 0x0f00, 1, OPC_MODRM | OPC_48, OPT_REG64))
- DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
- DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
- DEF_ASM_OP0L(swapgs, 0x0f01, 7, OPC_MODRM)
-
- /* 486 */
- /* bswap can't be applied to 16bit regs */
- DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
- DEF_ASM_OP1(bswapl, 0x0fc8, 0, OPC_REG, OPT_REG32 )
- DEF_ASM_OP1(bswapq, 0x0fc8, 0, OPC_REG | OPC_48, OPT_REG64 )
-
-ALT(DEF_ASM_OP2(xaddb, 0x0fc0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))
-ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_REG | OPT_EA ))
- DEF_ASM_OP1(invlpg, 0x0f01, 7, OPC_MODRM, OPT_EA )
-
- /* pentium */
- DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
-
- /* AMD 64 */
- DEF_ASM_OP1(cmpxchg16b, 0x0fc7, 1, OPC_MODRM | OPC_48, OPT_EA )
-
- /* pentium pro */
-ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST | OPC_WLX, OPT_REGW | OPT_EA, OPT_REGW))
-
- DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovu, 0xdad8, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovnb, 0xdbc0, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovne, 0xdbc8, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovnbe, 0xdbd0, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcmovnu, 0xdbd8, 0, OPC_REG, OPT_ST, OPT_ST0 )
-
- DEF_ASM_OP2(fucomi, 0xdbe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcomi, 0xdbf0, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fucomip, 0xdfe8, 0, OPC_REG, OPT_ST, OPT_ST0 )
- DEF_ASM_OP2(fcomip, 0xdff0, 0, OPC_REG, OPT_ST, OPT_ST0 )
-
- /* mmx */
- DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
- DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMXSSE )
- /* movd shouldn't accept REG64, but AMD64 spec uses it for 32 and 64 bit
- moves, so let's be compatible. */
-ALT(DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG64, OPT_MMXSSE ))
-ALT(DEF_ASM_OP2(movq, 0x0f6e, 0, OPC_MODRM | OPC_48, OPT_REG64, OPT_MMXSSE ))
-ALT(DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX ))
-ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG32 ))
-ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG64 ))
-ALT(DEF_ASM_OP2(movq, 0x0f7f, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_MMX ))
-ALT(DEF_ASM_OP2(movq, 0x660fd6, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_SSE ))
-ALT(DEF_ASM_OP2(movq, 0xf30f7e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE ))
-ALT(DEF_ASM_OP2(movq, 0x0f7e, 0, OPC_MODRM, OPT_MMXSSE, OPT_EA | OPT_REG64 ))
-
- DEF_ASM_OP2(packssdw, 0x0f6b, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(packsswb, 0x0f63, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(packuswb, 0x0f67, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddb, 0x0ffc, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddw, 0x0ffd, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddd, 0x0ffe, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddsb, 0x0fec, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddsw, 0x0fed, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddusb, 0x0fdc, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(paddusw, 0x0fdd, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pand, 0x0fdb, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pandn, 0x0fdf, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpeqb, 0x0f74, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpeqw, 0x0f75, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpeqd, 0x0f76, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpgtb, 0x0f64, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpgtw, 0x0f65, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pcmpgtd, 0x0f66, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pmaddwd, 0x0ff5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pmulhw, 0x0fe5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pmullw, 0x0fd5, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(por, 0x0feb, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psllw, 0x0ff1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psllw, 0x0f71, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(pslld, 0x0ff2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(pslld, 0x0f72, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psllq, 0x0ff3, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psllq, 0x0f73, 6, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psraw, 0x0fe1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psraw, 0x0f71, 4, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psrad, 0x0fe2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psrad, 0x0f72, 4, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psrlw, 0x0fd1, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psrlw, 0x0f71, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psrld, 0x0fd2, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psrld, 0x0f72, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psrlq, 0x0fd3, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-ALT(DEF_ASM_OP2(psrlq, 0x0f73, 2, OPC_MODRM, OPT_IM8, OPT_MMXSSE ))
- DEF_ASM_OP2(psubb, 0x0ff8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubw, 0x0ff9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubd, 0x0ffa, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubsb, 0x0fe8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubsw, 0x0fe9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubusb, 0x0fd8, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(psubusw, 0x0fd9, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpckhbw, 0x0f68, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpckhwd, 0x0f69, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpckhdq, 0x0f6a, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpcklbw, 0x0f60, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpcklwd, 0x0f61, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(punpckldq, 0x0f62, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pxor, 0x0fef, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
-
- /* sse */
- DEF_ASM_OP1(ldmxcsr, 0x0fae, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(stmxcsr, 0x0fae, 3, OPC_MODRM, OPT_EA)
- DEF_ASM_OP2(movups, 0x0f10, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
-ALT(DEF_ASM_OP2(movups, 0x0f11, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
- DEF_ASM_OP2(movaps, 0x0f28, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
-ALT(DEF_ASM_OP2(movaps, 0x0f29, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
- DEF_ASM_OP2(movhps, 0x0f16, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_SSE )
-ALT(DEF_ASM_OP2(movhps, 0x0f17, 0, OPC_MODRM, OPT_SSE, OPT_EA | OPT_REG32 ))
- DEF_ASM_OP2(addps, 0x0f58, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(cvtpi2ps, 0x0f2a, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_SSE )
- DEF_ASM_OP2(cvtps2pi, 0x0f2d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX )
- DEF_ASM_OP2(cvttps2pi, 0x0f2c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_MMX )
- DEF_ASM_OP2(divps, 0x0f5e, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(maxps, 0x0f5f, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(minps, 0x0f5d, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(mulps, 0x0f59, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(pavgb, 0x0fe0, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(pavgw, 0x0fe3, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(pmaxsw, 0x0fee, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pmaxub, 0x0fde, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pminsw, 0x0fea, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(pminub, 0x0fda, 0, OPC_MODRM, OPT_EA | OPT_MMXSSE, OPT_MMXSSE )
- DEF_ASM_OP2(rcpss, 0x0f53, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(rsqrtps, 0x0f52, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(sqrtps, 0x0f51, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
- DEF_ASM_OP2(subps, 0x0f5c, 0, OPC_MODRM, OPT_EA | OPT_SSE, OPT_SSE )
-
- /* movnti should only accept REG32 and REG64, we accept more */
- DEF_ASM_OP2(movnti, 0x0fc3, 0, OPC_MODRM, OPT_REG, OPT_EA)
- DEF_ASM_OP2(movntil, 0x0fc3, 0, OPC_MODRM, OPT_REG32, OPT_EA)
- DEF_ASM_OP2(movntiq, 0x0fc3, 0, OPC_MODRM | OPC_48, OPT_REG64, OPT_EA)
- DEF_ASM_OP1(prefetchnta, 0x0f18, 0, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(prefetcht0, 0x0f18, 1, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(prefetcht1, 0x0f18, 2, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(prefetcht2, 0x0f18, 3, OPC_MODRM, OPT_EA)
- DEF_ASM_OP1(prefetchw, 0x0f0d, 1, OPC_MODRM, OPT_EA)
- DEF_ASM_OP0L(lfence, 0x0fae, 5, OPC_MODRM)
- DEF_ASM_OP0L(mfence, 0x0fae, 6, OPC_MODRM)
- DEF_ASM_OP0L(sfence, 0x0fae, 7, OPC_MODRM)
- DEF_ASM_OP1(clflush, 0x0fae, 7, OPC_MODRM, OPT_EA)
-#undef ALT
-#undef DEF_ASM_OP0
-#undef DEF_ASM_OP0L
-#undef DEF_ASM_OP1
-#undef DEF_ASM_OP2
-#undef DEF_ASM_OP3
diff --git a/tinycc/x86_64-gen.c b/tinycc/x86_64-gen.c
deleted file mode 100644
index 0fe9cee..0000000
--- a/tinycc/x86_64-gen.c
+++ /dev/null
@@ -1,2328 +0,0 @@
-/*
- * x86-64 code generator for TCC
- *
- * Copyright (c) 2008 Shinichiro Hamaji
- *
- * Based on i386-gen.c by Fabrice Bellard
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifdef TARGET_DEFS_ONLY
-
-/* number of available registers */
-#define NB_REGS 25
-#define NB_ASM_REGS 16
-#define CONFIG_TCC_ASM
-
-/* a register can belong to several classes. The classes must be
- sorted from more general to more precise (see gv2() code which does
- assumptions on it). */
-#define RC_INT 0x0001 /* generic integer register */
-#define RC_FLOAT 0x0002 /* generic float register */
-#define RC_RAX 0x0004
-#define RC_RCX 0x0008
-#define RC_RDX 0x0010
-#define RC_RSI 0x0020
-#define RC_RDI 0x0040
-#define RC_ST0 0x0080 /* only for long double */
-#define RC_R8 0x0100
-#define RC_R9 0x0200
-#define RC_R10 0x0400
-#define RC_R11 0x0800
-#define RC_XMM0 0x1000
-#define RC_XMM1 0x2000
-#define RC_XMM2 0x4000
-#define RC_XMM3 0x8000
-#define RC_XMM4 0x10000
-#define RC_XMM5 0x20000
-#define RC_XMM6 0x40000
-#define RC_XMM7 0x80000
-#define RC_IRET RC_RAX /* function return: integer register */
-#define RC_IRE2 RC_RDX /* function return: second integer register */
-#define RC_FRET RC_XMM0 /* function return: float register */
-#define RC_FRE2 RC_XMM1 /* function return: second float register */
-
-/* pretty names for the registers */
-enum {
- TREG_RAX = 0,
- TREG_RCX = 1,
- TREG_RDX = 2,
- TREG_RSP = 4,
- TREG_RSI = 6,
- TREG_RDI = 7,
-
- TREG_R8 = 8,
- TREG_R9 = 9,
- TREG_R10 = 10,
- TREG_R11 = 11,
-
- TREG_XMM0 = 16,
- TREG_XMM1 = 17,
- TREG_XMM2 = 18,
- TREG_XMM3 = 19,
- TREG_XMM4 = 20,
- TREG_XMM5 = 21,
- TREG_XMM6 = 22,
- TREG_XMM7 = 23,
-
- TREG_ST0 = 24,
-
- TREG_MEM = 0x20
-};
-
-#define REX_BASE(reg) (((reg) >> 3) & 1)
-#define REG_VALUE(reg) ((reg) & 7)
-
-/* return registers for function */
-#define REG_IRET TREG_RAX /* single word int return register */
-#define REG_IRE2 TREG_RDX /* second word return register (for long long) */
-#define REG_FRET TREG_XMM0 /* float return register */
-#define REG_FRE2 TREG_XMM1 /* second float return register */
-
-/* defined if function parameters must be evaluated in reverse order */
-#define INVERT_FUNC_PARAMS
-
-/* pointer size, in bytes */
-#define PTR_SIZE 8
-
-/* long double size and alignment, in bytes */
-#define LDOUBLE_SIZE 16
-#define LDOUBLE_ALIGN 16
-/* maximum alignment (for aligned attribute support) */
-#define MAX_ALIGN 16
-
-/* define if return values need to be extended explicitely
- at caller side (for interfacing with non-TCC compilers) */
-#define PROMOTE_RET
-
-#define TCC_TARGET_NATIVE_STRUCT_COPY
-ST_FUNC void gen_struct_copy(int size);
-
-/******************************************************/
-#else /* ! TARGET_DEFS_ONLY */
-/******************************************************/
-#define USING_GLOBALS
-#include "tcc.h"
-#include <assert.h>
-
-ST_DATA const char * const target_machine_defs =
- "__x86_64__\0"
- "__amd64__\0"
- ;
-
-ST_DATA const int reg_classes[NB_REGS] = {
- /* eax */ RC_INT | RC_RAX,
- /* ecx */ RC_INT | RC_RCX,
- /* edx */ RC_INT | RC_RDX,
- 0,
- 0,
- 0,
- RC_RSI,
- RC_RDI,
- RC_R8,
- RC_R9,
- RC_R10,
- RC_R11,
- 0,
- 0,
- 0,
- 0,
- /* xmm0 */ RC_FLOAT | RC_XMM0,
- /* xmm1 */ RC_FLOAT | RC_XMM1,
- /* xmm2 */ RC_FLOAT | RC_XMM2,
- /* xmm3 */ RC_FLOAT | RC_XMM3,
- /* xmm4 */ RC_FLOAT | RC_XMM4,
- /* xmm5 */ RC_FLOAT | RC_XMM5,
- /* xmm6 an xmm7 are included so gv() can be used on them,
- but they are not tagged with RC_FLOAT because they are
- callee saved on Windows */
- RC_XMM6,
- RC_XMM7,
- /* st0 */ RC_ST0
-};
-
-static unsigned long func_sub_sp_offset;
-static int func_ret_sub;
-
-#if defined(CONFIG_TCC_BCHECK)
-static addr_t func_bound_offset;
-static unsigned long func_bound_ind;
-ST_DATA int func_bound_add_epilog;
-#endif
-
-#ifdef TCC_TARGET_PE
-static int func_scratch, func_alloca;
-#endif
-
-/* XXX: make it faster ? */
-ST_FUNC void g(int c)
-{
- int ind1;
- if (nocode_wanted)
- return;
- ind1 = ind + 1;
- if (ind1 > cur_text_section->data_allocated)
- section_realloc(cur_text_section, ind1);
- cur_text_section->data[ind] = c;
- ind = ind1;
-}
-
-ST_FUNC void o(unsigned int c)
-{
- while (c) {
- g(c);
- c = c >> 8;
- }
-}
-
-ST_FUNC void gen_le16(int v)
-{
- g(v);
- g(v >> 8);
-}
-
-ST_FUNC void gen_le32(int c)
-{
- g(c);
- g(c >> 8);
- g(c >> 16);
- g(c >> 24);
-}
-
-ST_FUNC void gen_le64(int64_t c)
-{
- g(c);
- g(c >> 8);
- g(c >> 16);
- g(c >> 24);
- g(c >> 32);
- g(c >> 40);
- g(c >> 48);
- g(c >> 56);
-}
-
-static void orex(int ll, int r, int r2, int b)
-{
- if ((r & VT_VALMASK) >= VT_CONST)
- r = 0;
- if ((r2 & VT_VALMASK) >= VT_CONST)
- r2 = 0;
- if (ll || REX_BASE(r) || REX_BASE(r2))
- o(0x40 | REX_BASE(r) | (REX_BASE(r2) << 2) | (ll << 3));
- o(b);
-}
-
-/* output a symbol and patch all calls to it */
-ST_FUNC void gsym_addr(int t, int a)
-{
- while (t) {
- unsigned char *ptr = cur_text_section->data + t;
- uint32_t n = read32le(ptr); /* next value */
- write32le(ptr, a < 0 ? -a : a - t - 4);
- t = n;
- }
-}
-
-static int is64_type(int t)
-{
- return ((t & VT_BTYPE) == VT_PTR ||
- (t & VT_BTYPE) == VT_FUNC ||
- (t & VT_BTYPE) == VT_LLONG);
-}
-
-/* instruction + 4 bytes data. Return the address of the data */
-static int oad(int c, int s)
-{
- int t;
- if (nocode_wanted)
- return s;
- o(c);
- t = ind;
- gen_le32(s);
- return t;
-}
-
-/* generate jmp to a label */
-#define gjmp2(instr,lbl) oad(instr,lbl)
-
-ST_FUNC void gen_addr32(int r, Sym *sym, int c)
-{
- if (r & VT_SYM)
- greloca(cur_text_section, sym, ind, R_X86_64_32S, c), c=0;
- gen_le32(c);
-}
-
-/* output constant with relocation if 'r & VT_SYM' is true */
-ST_FUNC void gen_addr64(int r, Sym *sym, int64_t c)
-{
- if (r & VT_SYM)
- greloca(cur_text_section, sym, ind, R_X86_64_64, c), c=0;
- gen_le64(c);
-}
-
-/* output constant with relocation if 'r & VT_SYM' is true */
-ST_FUNC void gen_addrpc32(int r, Sym *sym, int c)
-{
- if (r & VT_SYM)
- greloca(cur_text_section, sym, ind, R_X86_64_PC32, c-4), c=4;
- gen_le32(c-4);
-}
-
-/* output got address with relocation */
-static void gen_gotpcrel(int r, Sym *sym, int c)
-{
-#ifdef TCC_TARGET_PE
- tcc_error("internal error: no GOT on PE: %s %x %x | %02x %02x %02x\n",
- get_tok_str(sym->v, NULL), c, r,
- cur_text_section->data[ind-3],
- cur_text_section->data[ind-2],
- cur_text_section->data[ind-1]
- );
-#endif
- greloca(cur_text_section, sym, ind, R_X86_64_GOTPCREL, -4);
- gen_le32(0);
- if (c) {
- /* we use add c, %xxx for displacement */
- orex(1, r, 0, 0x81);
- o(0xc0 + REG_VALUE(r));
- gen_le32(c);
- }
-}
-
-static void gen_modrm_impl(int op_reg, int r, Sym *sym, int c, int is_got)
-{
- op_reg = REG_VALUE(op_reg) << 3;
- if ((r & VT_VALMASK) == VT_CONST) {
- /* constant memory reference */
- if (!(r & VT_SYM)) {
- /* Absolute memory reference */
- o(0x04 | op_reg); /* [sib] | destreg */
- oad(0x25, c); /* disp32 */
- } else {
- o(0x05 | op_reg); /* (%rip)+disp32 | destreg */
- if (is_got) {
- gen_gotpcrel(r, sym, c);
- } else {
- gen_addrpc32(r, sym, c);
- }
- }
- } else if ((r & VT_VALMASK) == VT_LOCAL) {
- /* currently, we use only ebp as base */
- if (c == (char)c) {
- /* short reference */
- o(0x45 | op_reg);
- g(c);
- } else {
- oad(0x85 | op_reg, c);
- }
- } else if ((r & VT_VALMASK) >= TREG_MEM) {
- if (c) {
- g(0x80 | op_reg | REG_VALUE(r));
- gen_le32(c);
- } else {
- g(0x00 | op_reg | REG_VALUE(r));
- }
- } else {
- g(0x00 | op_reg | REG_VALUE(r));
- }
-}
-
-/* generate a modrm reference. 'op_reg' contains the additional 3
- opcode bits */
-static void gen_modrm(int op_reg, int r, Sym *sym, int c)
-{
- gen_modrm_impl(op_reg, r, sym, c, 0);
-}
-
-/* generate a modrm reference. 'op_reg' contains the additional 3
- opcode bits */
-static void gen_modrm64(int opcode, int op_reg, int r, Sym *sym, int c)
-{
- int is_got;
- is_got = (op_reg & TREG_MEM) && !(sym->type.t & VT_STATIC);
- orex(1, r, op_reg, opcode);
- gen_modrm_impl(op_reg, r, sym, c, is_got);
-}
-
-
-/* load 'r' from value 'sv' */
-void load(int r, SValue *sv)
-{
- int v, t, ft, fc, fr;
- SValue v1;
-
-#ifdef TCC_TARGET_PE
- SValue v2;
- sv = pe_getimport(sv, &v2);
-#endif
-
- fr = sv->r;
- ft = sv->type.t & ~VT_DEFSIGN;
- fc = sv->c.i;
- if (fc != sv->c.i && (fr & VT_SYM))
- tcc_error("64 bit addend in load");
-
- ft &= ~(VT_VOLATILE | VT_CONSTANT);
-
-#ifndef TCC_TARGET_PE
- /* we use indirect access via got */
- if ((fr & VT_VALMASK) == VT_CONST && (fr & VT_SYM) &&
- (fr & VT_LVAL) && !(sv->sym->type.t & VT_STATIC)) {
- /* use the result register as a temporal register */
- int tr = r | TREG_MEM;
- if (is_float(ft)) {
- /* we cannot use float registers as a temporal register */
- tr = get_reg(RC_INT) | TREG_MEM;
- }
- gen_modrm64(0x8b, tr, fr, sv->sym, 0);
-
- /* load from the temporal register */
- fr = tr | VT_LVAL;
- }
-#endif
-
- v = fr & VT_VALMASK;
- if (fr & VT_LVAL) {
- int b, ll;
- if (v == VT_LLOCAL) {
- v1.type.t = VT_PTR;
- v1.r = VT_LOCAL | VT_LVAL;
- v1.c.i = fc;
- fr = r;
- if (!(reg_classes[fr] & (RC_INT|RC_R11)))
- fr = get_reg(RC_INT);
- load(fr, &v1);
- }
- if (fc != sv->c.i) {
- /* If the addends doesn't fit into a 32bit signed
- we must use a 64bit move. We've checked above
- that this doesn't have a sym associated. */
- v1.type.t = VT_LLONG;
- v1.r = VT_CONST;
- v1.c.i = sv->c.i;
- fr = r;
- if (!(reg_classes[fr] & (RC_INT|RC_R11)))
- fr = get_reg(RC_INT);
- load(fr, &v1);
- fc = 0;
- }
- ll = 0;
- /* Like GCC we can load from small enough properly sized
- structs and unions as well.
- XXX maybe move to generic operand handling, but should
- occur only with asm, so tccasm.c might also be a better place */
- if ((ft & VT_BTYPE) == VT_STRUCT) {
- int align;
- switch (type_size(&sv->type, &align)) {
- case 1: ft = VT_BYTE; break;
- case 2: ft = VT_SHORT; break;
- case 4: ft = VT_INT; break;
- case 8: ft = VT_LLONG; break;
- default:
- tcc_error("invalid aggregate type for register load");
- break;
- }
- }
- if ((ft & VT_BTYPE) == VT_FLOAT) {
- b = 0x6e0f66;
- r = REG_VALUE(r); /* movd */
- } else if ((ft & VT_BTYPE) == VT_DOUBLE) {
- b = 0x7e0ff3; /* movq */
- r = REG_VALUE(r);
- } else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
- b = 0xdb, r = 5; /* fldt */
- } else if ((ft & VT_TYPE) == VT_BYTE || (ft & VT_TYPE) == VT_BOOL) {
- b = 0xbe0f; /* movsbl */
- } else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
- b = 0xb60f; /* movzbl */
- } else if ((ft & VT_TYPE) == VT_SHORT) {
- b = 0xbf0f; /* movswl */
- } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
- b = 0xb70f; /* movzwl */
- } else if ((ft & VT_TYPE) == (VT_VOID)) {
- /* Can happen with zero size structs */
- return;
- } else {
- assert(((ft & VT_BTYPE) == VT_INT)
- || ((ft & VT_BTYPE) == VT_LLONG)
- || ((ft & VT_BTYPE) == VT_PTR)
- || ((ft & VT_BTYPE) == VT_FUNC)
- );
- ll = is64_type(ft);
- b = 0x8b;
- }
- if (ll) {
- gen_modrm64(b, r, fr, sv->sym, fc);
- } else {
- orex(ll, fr, r, b);
- gen_modrm(r, fr, sv->sym, fc);
- }
- } else {
- if (v == VT_CONST) {
- if (fr & VT_SYM) {
-#ifdef TCC_TARGET_PE
- orex(1,0,r,0x8d);
- o(0x05 + REG_VALUE(r) * 8); /* lea xx(%rip), r */
- gen_addrpc32(fr, sv->sym, fc);
-#else
- if (sv->sym->type.t & VT_STATIC) {
- orex(1,0,r,0x8d);
- o(0x05 + REG_VALUE(r) * 8); /* lea xx(%rip), r */
- gen_addrpc32(fr, sv->sym, fc);
- } else {
- orex(1,0,r,0x8b);
- o(0x05 + REG_VALUE(r) * 8); /* mov xx(%rip), r */
- gen_gotpcrel(r, sv->sym, fc);
- }
-#endif
- } else if (is64_type(ft)) {
- orex(1,r,0, 0xb8 + REG_VALUE(r)); /* mov $xx, r */
- gen_le64(sv->c.i);
- } else {
- orex(0,r,0, 0xb8 + REG_VALUE(r)); /* mov $xx, r */
- gen_le32(fc);
- }
- } else if (v == VT_LOCAL) {
- orex(1,0,r,0x8d); /* lea xxx(%ebp), r */
- gen_modrm(r, VT_LOCAL, sv->sym, fc);
- } else if (v == VT_CMP) {
- if (fc & 0x100)
- {
- v = vtop->cmp_r;
- fc &= ~0x100;
- /* This was a float compare. If the parity bit is
- set the result was unordered, meaning false for everything
- except TOK_NE, and true for TOK_NE. */
- orex(0, r, 0, 0xb0 + REG_VALUE(r)); /* mov $0/1,%al */
- g(v ^ fc ^ (v == TOK_NE));
- o(0x037a + (REX_BASE(r) << 8));
- }
- orex(0,r,0, 0x0f); /* setxx %br */
- o(fc);
- o(0xc0 + REG_VALUE(r));
- orex(0,r,0, 0x0f);
- o(0xc0b6 + REG_VALUE(r) * 0x900); /* movzbl %al, %eax */
- } else if (v == VT_JMP || v == VT_JMPI) {
- t = v & 1;
- orex(0,r,0,0);
- oad(0xb8 + REG_VALUE(r), t); /* mov $1, r */
- o(0x05eb + (REX_BASE(r) << 8)); /* jmp after */
- gsym(fc);
- orex(0,r,0,0);
- oad(0xb8 + REG_VALUE(r), t ^ 1); /* mov $0, r */
- } else if (v != r) {
- if ((r >= TREG_XMM0) && (r <= TREG_XMM7)) {
- if (v == TREG_ST0) {
- /* gen_cvt_ftof(VT_DOUBLE); */
- o(0xf0245cdd); /* fstpl -0x10(%rsp) */
- /* movsd -0x10(%rsp),%xmmN */
- o(0x100ff2);
- o(0x44 + REG_VALUE(r)*8); /* %xmmN */
- o(0xf024);
- } else {
- assert((v >= TREG_XMM0) && (v <= TREG_XMM7));
- if ((ft & VT_BTYPE) == VT_FLOAT) {
- o(0x100ff3);
- } else {
- assert((ft & VT_BTYPE) == VT_DOUBLE);
- o(0x100ff2);
- }
- o(0xc0 + REG_VALUE(v) + REG_VALUE(r)*8);
- }
- } else if (r == TREG_ST0) {
- assert((v >= TREG_XMM0) && (v <= TREG_XMM7));
- /* gen_cvt_ftof(VT_LDOUBLE); */
- /* movsd %xmmN,-0x10(%rsp) */
- o(0x110ff2);
- o(0x44 + REG_VALUE(r)*8); /* %xmmN */
- o(0xf024);
- o(0xf02444dd); /* fldl -0x10(%rsp) */
- } else {
- orex(is64_type(ft), r, v, 0x89);
- o(0xc0 + REG_VALUE(r) + REG_VALUE(v) * 8); /* mov v, r */
- }
- }
- }
-}
-
-/* store register 'r' in lvalue 'v' */
-void store(int r, SValue *v)
-{
- int fr, bt, ft, fc;
- int op64 = 0;
- /* store the REX prefix in this variable when PIC is enabled */
- int pic = 0;
-
-#ifdef TCC_TARGET_PE
- SValue v2;
- v = pe_getimport(v, &v2);
-#endif
-
- fr = v->r & VT_VALMASK;
- ft = v->type.t;
- fc = v->c.i;
- if (fc != v->c.i && (fr & VT_SYM))
- tcc_error("64 bit addend in store");
- ft &= ~(VT_VOLATILE | VT_CONSTANT);
- bt = ft & VT_BTYPE;
-
-#ifndef TCC_TARGET_PE
- /* we need to access the variable via got */
- if (fr == VT_CONST
- && (v->r & VT_SYM)
- && !(v->sym->type.t & VT_STATIC)) {
- /* mov xx(%rip), %r11 */
- o(0x1d8b4c);
- gen_gotpcrel(TREG_R11, v->sym, v->c.i);
- pic = is64_type(bt) ? 0x49 : 0x41;
- }
-#endif
-
- /* XXX: incorrect if float reg to reg */
- if (bt == VT_FLOAT) {
- o(0x66);
- o(pic);
- o(0x7e0f); /* movd */
- r = REG_VALUE(r);
- } else if (bt == VT_DOUBLE) {
- o(0x66);
- o(pic);
- o(0xd60f); /* movq */
- r = REG_VALUE(r);
- } else if (bt == VT_LDOUBLE) {
- o(0xc0d9); /* fld %st(0) */
- o(pic);
- o(0xdb); /* fstpt */
- r = 7;
- } else {
- if (bt == VT_SHORT)
- o(0x66);
- o(pic);
- if (bt == VT_BYTE || bt == VT_BOOL)
- orex(0, 0, r, 0x88);
- else if (is64_type(bt))
- op64 = 0x89;
- else
- orex(0, 0, r, 0x89);
- }
- if (pic) {
- /* xxx r, (%r11) where xxx is mov, movq, fld, or etc */
- if (op64)
- o(op64);
- o(3 + (r << 3));
- } else if (op64) {
- if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
- gen_modrm64(op64, r, v->r, v->sym, fc);
- } else if (fr != r) {
- orex(1, fr, r, op64);
- o(0xc0 + fr + r * 8); /* mov r, fr */
- }
- } else {
- if (fr == VT_CONST || fr == VT_LOCAL || (v->r & VT_LVAL)) {
- gen_modrm(r, v->r, v->sym, fc);
- } else if (fr != r) {
- o(0xc0 + fr + r * 8); /* mov r, fr */
- }
- }
-}
-
-/* 'is_jmp' is '1' if it is a jump */
-static void gcall_or_jmp(int is_jmp)
-{
- int r;
- if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
- ((vtop->r & VT_SYM) && (vtop->c.i-4) == (int)(vtop->c.i-4))) {
- /* constant symbolic case -> simple relocation */
-#ifdef TCC_TARGET_PE
- greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PC32, (int)(vtop->c.i-4));
-#else
- greloca(cur_text_section, vtop->sym, ind + 1, R_X86_64_PLT32, (int)(vtop->c.i-4));
-#endif
- oad(0xe8 + is_jmp, 0); /* call/jmp im */
- } else {
- /* otherwise, indirect call */
- r = TREG_R11;
- load(r, vtop);
- o(0x41); /* REX */
- o(0xff); /* call/jmp *r */
- o(0xd0 + REG_VALUE(r) + (is_jmp << 4));
- }
-}
-
-#if defined(CONFIG_TCC_BCHECK)
-
-static void gen_bounds_call(int v)
-{
- Sym *sym = external_helper_sym(v);
- oad(0xe8, 0);
-#ifdef TCC_TARGET_PE
- greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4);
-#else
- greloca(cur_text_section, sym, ind-4, R_X86_64_PLT32, -4);
-#endif
-}
-
-#ifdef TCC_TARGET_PE
-# define TREG_FASTCALL_1 TREG_RCX
-#else
-# define TREG_FASTCALL_1 TREG_RDI
-#endif
-
-static void gen_bounds_prolog(void)
-{
- /* leave some room for bound checking code */
- func_bound_offset = lbounds_section->data_offset;
- func_bound_ind = ind;
- func_bound_add_epilog = 0;
- o(0x0d8d48 + ((TREG_FASTCALL_1 == TREG_RDI) * 0x300000)); /*lbound section pointer */
- gen_le32 (0);
- oad(0xb8, 0); /* call to function */
-}
-
-static void gen_bounds_epilog(void)
-{
- addr_t saved_ind;
- addr_t *bounds_ptr;
- Sym *sym_data;
- int offset_modified = func_bound_offset != lbounds_section->data_offset;
-
- if (!offset_modified && !func_bound_add_epilog)
- return;
-
- /* add end of table info */
- bounds_ptr = section_ptr_add(lbounds_section, sizeof(addr_t));
- *bounds_ptr = 0;
-
- sym_data = get_sym_ref(&char_pointer_type, lbounds_section,
- func_bound_offset, PTR_SIZE);
-
- /* generate bound local allocation */
- if (offset_modified) {
- saved_ind = ind;
- ind = func_bound_ind;
- greloca(cur_text_section, sym_data, ind + 3, R_X86_64_PC32, -4);
- ind = ind + 7;
- gen_bounds_call(TOK___bound_local_new);
- ind = saved_ind;
- }
-
- /* generate bound check local freeing */
- o(0x5250); /* save returned value, if any */
- o(0x20ec8348); /* sub $32,%rsp */
- o(0x290f); /* movaps %xmm0,0x10(%rsp) */
- o(0x102444);
- o(0x240c290f); /* movaps %xmm1,(%rsp) */
- greloca(cur_text_section, sym_data, ind + 3, R_X86_64_PC32, -4);
- o(0x0d8d48 + ((TREG_FASTCALL_1 == TREG_RDI) * 0x300000)); /* lea xxx(%rip), %rcx/rdi */
- gen_le32 (0);
- gen_bounds_call(TOK___bound_local_delete);
- o(0x280f); /* movaps 0x10(%rsp),%xmm0 */
- o(0x102444);
- o(0x240c280f); /* movaps (%rsp),%xmm1 */
- o(0x20c48348); /* add $32,%rsp */
- o(0x585a); /* restore returned value, if any */
-}
-#endif
-
-#ifdef TCC_TARGET_PE
-
-#define REGN 4
-static const uint8_t arg_regs[REGN] = {
- TREG_RCX, TREG_RDX, TREG_R8, TREG_R9
-};
-
-/* Prepare arguments in R10 and R11 rather than RCX and RDX
- because gv() will not ever use these */
-static int arg_prepare_reg(int idx) {
- if (idx == 0 || idx == 1)
- /* idx=0: r10, idx=1: r11 */
- return idx + 10;
- else
- return idx >= 0 && idx < REGN ? arg_regs[idx] : 0;
-}
-
-/* Generate function call. The function address is pushed first, then
- all the parameters in call order. This functions pops all the
- parameters and the function address. */
-
-static void gen_offs_sp(int b, int r, int d)
-{
- orex(1,0,r & 0x100 ? 0 : r, b);
- if (d == (char)d) {
- o(0x2444 | (REG_VALUE(r) << 3));
- g(d);
- } else {
- o(0x2484 | (REG_VALUE(r) << 3));
- gen_le32(d);
- }
-}
-
-static int using_regs(int size)
-{
- return !(size > 8 || (size & (size - 1)));
-}
-
-/* Return the number of registers needed to return the struct, or 0 if
- returning via struct pointer. */
-ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
-{
- int size, align;
- *ret_align = 1; // Never have to re-align return values for x86-64
- *regsize = 8;
- size = type_size(vt, &align);
- if (!using_regs(size))
- return 0;
- if (size == 8)
- ret->t = VT_LLONG;
- else if (size == 4)
- ret->t = VT_INT;
- else if (size == 2)
- ret->t = VT_SHORT;
- else
- ret->t = VT_BYTE;
- ret->ref = NULL;
- return 1;
-}
-
-static int is_sse_float(int t) {
- int bt;
- bt = t & VT_BTYPE;
- return bt == VT_DOUBLE || bt == VT_FLOAT;
-}
-
-static int gfunc_arg_size(CType *type) {
- int align;
- if (type->t & (VT_ARRAY|VT_BITFIELD))
- return 8;
- return type_size(type, &align);
-}
-
-void gfunc_call(int nb_args)
-{
- int size, r, args_size, i, d, bt, struct_size;
- int arg;
-
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- gbound_args(nb_args);
-#endif
-
- args_size = (nb_args < REGN ? REGN : nb_args) * PTR_SIZE;
- arg = nb_args;
-
- /* for struct arguments, we need to call memcpy and the function
- call breaks register passing arguments we are preparing.
- So, we process arguments which will be passed by stack first. */
- struct_size = args_size;
- for(i = 0; i < nb_args; i++) {
- SValue *sv;
-
- --arg;
- sv = &vtop[-i];
- bt = (sv->type.t & VT_BTYPE);
- size = gfunc_arg_size(&sv->type);
-
- if (using_regs(size))
- continue; /* arguments smaller than 8 bytes passed in registers or on stack */
-
- if (bt == VT_STRUCT) {
- /* align to stack align size */
- size = (size + 15) & ~15;
- /* generate structure store */
- r = get_reg(RC_INT);
- gen_offs_sp(0x8d, r, struct_size);
- struct_size += size;
-
- /* generate memcpy call */
- vset(&sv->type, r | VT_LVAL, 0);
- vpushv(sv);
- vstore();
- --vtop;
- } else if (bt == VT_LDOUBLE) {
- gv(RC_ST0);
- gen_offs_sp(0xdb, 0x107, struct_size);
- struct_size += 16;
- }
- }
-
- if (func_scratch < struct_size)
- func_scratch = struct_size;
-
- arg = nb_args;
- struct_size = args_size;
-
- for(i = 0; i < nb_args; i++) {
- --arg;
- bt = (vtop->type.t & VT_BTYPE);
-
- size = gfunc_arg_size(&vtop->type);
- if (!using_regs(size)) {
- /* align to stack align size */
- size = (size + 15) & ~15;
- if (arg >= REGN) {
- d = get_reg(RC_INT);
- gen_offs_sp(0x8d, d, struct_size);
- gen_offs_sp(0x89, d, arg*8);
- } else {
- d = arg_prepare_reg(arg);
- gen_offs_sp(0x8d, d, struct_size);
- }
- struct_size += size;
- } else {
- if (is_sse_float(vtop->type.t)) {
- if (tcc_state->nosse)
- tcc_error("SSE disabled");
- if (arg >= REGN) {
- gv(RC_XMM0);
- /* movq %xmm0, j*8(%rsp) */
- gen_offs_sp(0xd60f66, 0x100, arg*8);
- } else {
- /* Load directly to xmmN register */
- gv(RC_XMM0 << arg);
- d = arg_prepare_reg(arg);
- /* mov %xmmN, %rxx */
- o(0x66);
- orex(1,d,0, 0x7e0f);
- o(0xc0 + arg*8 + REG_VALUE(d));
- }
- } else {
- if (bt == VT_STRUCT) {
- vtop->type.ref = NULL;
- vtop->type.t = size > 4 ? VT_LLONG : size > 2 ? VT_INT
- : size > 1 ? VT_SHORT : VT_BYTE;
- }
-
- r = gv(RC_INT);
- if (arg >= REGN) {
- gen_offs_sp(0x89, r, arg*8);
- } else {
- d = arg_prepare_reg(arg);
- orex(1,d,r,0x89); /* mov */
- o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d));
- }
- }
- }
- vtop--;
- }
- save_regs(0);
- /* Copy R10 and R11 into RCX and RDX, respectively */
- if (nb_args > 0) {
- o(0xd1894c); /* mov %r10, %rcx */
- if (nb_args > 1) {
- o(0xda894c); /* mov %r11, %rdx */
- }
- }
-
- gcall_or_jmp(0);
-
- if ((vtop->r & VT_SYM) && vtop->sym->v == TOK_alloca) {
- /* need to add the "func_scratch" area after alloca */
- o(0x48); func_alloca = oad(0x05, func_alloca); /* add $NN, %rax */
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- gen_bounds_call(TOK___bound_alloca_nr); /* new region */
-#endif
- }
- vtop--;
-}
-
-
-#define FUNC_PROLOG_SIZE 11
-
-/* generate function prolog of type 't' */
-void gfunc_prolog(Sym *func_sym)
-{
- CType *func_type = &func_sym->type;
- int addr, reg_param_index, bt, size;
- Sym *sym;
- CType *type;
-
- func_ret_sub = 0;
- func_scratch = 32;
- func_alloca = 0;
- loc = 0;
-
- addr = PTR_SIZE * 2;
- ind += FUNC_PROLOG_SIZE;
- func_sub_sp_offset = ind;
- reg_param_index = 0;
-
- sym = func_type->ref;
-
- /* if the function returns a structure, then add an
- implicit pointer parameter */
- size = gfunc_arg_size(&func_vt);
- if (!using_regs(size)) {
- gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
- func_vc = addr;
- reg_param_index++;
- addr += 8;
- }
-
- /* define parameters */
- while ((sym = sym->next) != NULL) {
- type = &sym->type;
- bt = type->t & VT_BTYPE;
- size = gfunc_arg_size(type);
- if (!using_regs(size)) {
- if (reg_param_index < REGN) {
- gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
- }
- sym_push(sym->v & ~SYM_FIELD, type,
- VT_LLOCAL | VT_LVAL, addr);
- } else {
- if (reg_param_index < REGN) {
- /* save arguments passed by register */
- if ((bt == VT_FLOAT) || (bt == VT_DOUBLE)) {
- if (tcc_state->nosse)
- tcc_error("SSE disabled");
- o(0xd60f66); /* movq */
- gen_modrm(reg_param_index, VT_LOCAL, NULL, addr);
- } else {
- gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
- }
- }
- sym_push(sym->v & ~SYM_FIELD, type,
- VT_LOCAL | VT_LVAL, addr);
- }
- addr += 8;
- reg_param_index++;
- }
-
- while (reg_param_index < REGN) {
- if (func_var) {
- gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
- addr += 8;
- }
- reg_param_index++;
- }
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- gen_bounds_prolog();
-#endif
-}
-
-/* generate function epilog */
-void gfunc_epilog(void)
-{
- int v, saved_ind;
-
- /* align local size to word & save local variables */
- func_scratch = (func_scratch + 15) & -16;
- loc = (loc & -16) - func_scratch;
-
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- gen_bounds_epilog();
-#endif
-
- o(0xc9); /* leave */
- if (func_ret_sub == 0) {
- o(0xc3); /* ret */
- } else {
- o(0xc2); /* ret n */
- g(func_ret_sub);
- g(func_ret_sub >> 8);
- }
-
- saved_ind = ind;
- ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
- v = -loc;
-
- if (v >= 4096) {
- Sym *sym = external_helper_sym(TOK___chkstk);
- oad(0xb8, v); /* mov stacksize, %eax */
- oad(0xe8, 0); /* call __chkstk, (does the stackframe too) */
- greloca(cur_text_section, sym, ind-4, R_X86_64_PC32, -4);
- o(0x90); /* fill for FUNC_PROLOG_SIZE = 11 bytes */
- } else {
- o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
- o(0xec8148); /* sub rsp, stacksize */
- gen_le32(v);
- }
-
- /* add the "func_scratch" area after each alloca seen */
- gsym_addr(func_alloca, -func_scratch);
-
- cur_text_section->data_offset = saved_ind;
- pe_add_unwind_data(ind, saved_ind, v);
- ind = cur_text_section->data_offset;
-}
-
-#else
-
-static void gadd_sp(int val)
-{
- if (val == (char)val) {
- o(0xc48348);
- g(val);
- } else {
- oad(0xc48148, val); /* add $xxx, %rsp */
- }
-}
-
-typedef enum X86_64_Mode {
- x86_64_mode_none,
- x86_64_mode_memory,
- x86_64_mode_integer,
- x86_64_mode_sse,
- x86_64_mode_x87
-} X86_64_Mode;
-
-static X86_64_Mode classify_x86_64_merge(X86_64_Mode a, X86_64_Mode b)
-{
- if (a == b)
- return a;
- else if (a == x86_64_mode_none)
- return b;
- else if (b == x86_64_mode_none)
- return a;
- else if ((a == x86_64_mode_memory) || (b == x86_64_mode_memory))
- return x86_64_mode_memory;
- else if ((a == x86_64_mode_integer) || (b == x86_64_mode_integer))
- return x86_64_mode_integer;
- else if ((a == x86_64_mode_x87) || (b == x86_64_mode_x87))
- return x86_64_mode_memory;
- else
- return x86_64_mode_sse;
-}
-
-static X86_64_Mode classify_x86_64_inner(CType *ty)
-{
- X86_64_Mode mode;
- Sym *f;
-
- switch (ty->t & VT_BTYPE) {
- case VT_VOID: return x86_64_mode_none;
-
- case VT_INT:
- case VT_BYTE:
- case VT_SHORT:
- case VT_LLONG:
- case VT_BOOL:
- case VT_PTR:
- case VT_FUNC:
- return x86_64_mode_integer;
-
- case VT_FLOAT:
- case VT_DOUBLE: return x86_64_mode_sse;
-
- case VT_LDOUBLE: return x86_64_mode_x87;
-
- case VT_STRUCT:
- f = ty->ref;
-
- mode = x86_64_mode_none;
- for (f = f->next; f; f = f->next)
- mode = classify_x86_64_merge(mode, classify_x86_64_inner(&f->type));
-
- return mode;
- }
- assert(0);
- return 0;
-}
-
-static X86_64_Mode classify_x86_64_arg(CType *ty, CType *ret, int *psize, int *palign, int *reg_count)
-{
- X86_64_Mode mode;
- int size, align, ret_t = 0;
-
- if (ty->t & (VT_BITFIELD|VT_ARRAY)) {
- *psize = 8;
- *palign = 8;
- *reg_count = 1;
- ret_t = ty->t;
- mode = x86_64_mode_integer;
- } else {
- size = type_size(ty, &align);
- *psize = (size + 7) & ~7;
- *palign = (align + 7) & ~7;
- *reg_count = 0; /* avoid compiler warning */
-
- if (size > 16) {
- mode = x86_64_mode_memory;
- } else {
- mode = classify_x86_64_inner(ty);
- switch (mode) {
- case x86_64_mode_integer:
- if (size > 8) {
- *reg_count = 2;
- ret_t = VT_QLONG;
- } else {
- *reg_count = 1;
- if (size > 4)
- ret_t = VT_LLONG;
- else if (size > 2)
- ret_t = VT_INT;
- else if (size > 1)
- ret_t = VT_SHORT;
- else
- ret_t = VT_BYTE;
- if ((ty->t & VT_BTYPE) == VT_STRUCT || (ty->t & VT_UNSIGNED))
- ret_t |= VT_UNSIGNED;
- }
- break;
-
- case x86_64_mode_x87:
- *reg_count = 1;
- ret_t = VT_LDOUBLE;
- break;
-
- case x86_64_mode_sse:
- if (size > 8) {
- *reg_count = 2;
- ret_t = VT_QFLOAT;
- } else {
- *reg_count = 1;
- ret_t = (size > 4) ? VT_DOUBLE : VT_FLOAT;
- }
- break;
- default: break; /* nothing to be done for x86_64_mode_memory and x86_64_mode_none*/
- }
- }
- }
-
- if (ret) {
- ret->ref = NULL;
- ret->t = ret_t;
- }
-
- return mode;
-}
-
-ST_FUNC int classify_x86_64_va_arg(CType *ty)
-{
- /* This definition must be synced with stdarg.h */
- enum __va_arg_type {
- __va_gen_reg, __va_float_reg, __va_stack
- };
- int size, align, reg_count;
- X86_64_Mode mode = classify_x86_64_arg(ty, NULL, &size, &align, &reg_count);
- switch (mode) {
- default: return __va_stack;
- case x86_64_mode_integer: return __va_gen_reg;
- case x86_64_mode_sse: return __va_float_reg;
- }
-}
-
-/* Return the number of registers needed to return the struct, or 0 if
- returning via struct pointer. */
-ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)
-{
- int size, align, reg_count;
- *ret_align = 1; // Never have to re-align return values for x86-64
- *regsize = 8;
- return (classify_x86_64_arg(vt, ret, &size, &align, &reg_count) != x86_64_mode_memory);
-}
-
-#define REGN 6
-static const uint8_t arg_regs[REGN] = {
- TREG_RDI, TREG_RSI, TREG_RDX, TREG_RCX, TREG_R8, TREG_R9
-};
-
-static int arg_prepare_reg(int idx) {
- if (idx == 2 || idx == 3)
- /* idx=2: r10, idx=3: r11 */
- return idx + 8;
- else
- return idx >= 0 && idx < REGN ? arg_regs[idx] : 0;
-}
-
-/* Generate function call. The function address is pushed first, then
- all the parameters in call order. This functions pops all the
- parameters and the function address. */
-void gfunc_call(int nb_args)
-{
- X86_64_Mode mode;
- CType type;
- int size, align, r, args_size, stack_adjust, i, reg_count, k;
- int nb_reg_args = 0;
- int nb_sse_args = 0;
- int sse_reg, gen_reg;
- char *onstack = tcc_malloc((nb_args + 1) * sizeof (char));
-
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- gbound_args(nb_args);
-#endif
-
- /* calculate the number of integer/float register arguments, remember
- arguments to be passed via stack (in onstack[]), and also remember
- if we have to align the stack pointer to 16 (onstack[i] == 2). Needs
- to be done in a left-to-right pass over arguments. */
- stack_adjust = 0;
- for(i = nb_args - 1; i >= 0; i--) {
- mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count);
- if (size == 0) continue;
- if (mode == x86_64_mode_sse && nb_sse_args + reg_count <= 8) {
- nb_sse_args += reg_count;
- onstack[i] = 0;
- } else if (mode == x86_64_mode_integer && nb_reg_args + reg_count <= REGN) {
- nb_reg_args += reg_count;
- onstack[i] = 0;
- } else if (mode == x86_64_mode_none) {
- onstack[i] = 0;
- } else {
- if (align == 16 && (stack_adjust &= 15)) {
- onstack[i] = 2;
- stack_adjust = 0;
- } else
- onstack[i] = 1;
- stack_adjust += size;
- }
- }
-
- if (nb_sse_args && tcc_state->nosse)
- tcc_error("SSE disabled but floating point arguments passed");
-
- /* fetch cpu flag before generating any code */
- if ((vtop->r & VT_VALMASK) == VT_CMP)
- gv(RC_INT);
-
- /* for struct arguments, we need to call memcpy and the function
- call breaks register passing arguments we are preparing.
- So, we process arguments which will be passed by stack first. */
- gen_reg = nb_reg_args;
- sse_reg = nb_sse_args;
- args_size = 0;
- stack_adjust &= 15;
- for (i = k = 0; i < nb_args;) {
- mode = classify_x86_64_arg(&vtop[-i].type, NULL, &size, &align, &reg_count);
- if (size) {
- if (!onstack[i + k]) {
- ++i;
- continue;
- }
- /* Possibly adjust stack to align SSE boundary. We're processing
- args from right to left while allocating happens left to right
- (stack grows down), so the adjustment needs to happen _after_
- an argument that requires it. */
- if (stack_adjust) {
- o(0x50); /* push %rax; aka sub $8,%rsp */
- args_size += 8;
- stack_adjust = 0;
- }
- if (onstack[i + k] == 2)
- stack_adjust = 1;
- }
-
- vrotb(i+1);
-
- switch (vtop->type.t & VT_BTYPE) {
- case VT_STRUCT:
- /* allocate the necessary size on stack */
- o(0x48);
- oad(0xec81, size); /* sub $xxx, %rsp */
- /* generate structure store */
- r = get_reg(RC_INT);
- orex(1, r, 0, 0x89); /* mov %rsp, r */
- o(0xe0 + REG_VALUE(r));
- vset(&vtop->type, r | VT_LVAL, 0);
- vswap();
- /* keep stack aligned for (__bound_)memmove call */
- o(0x10ec8348); /* sub $16,%rsp */
- o(0xf0e48348); /* and $-16,%rsp */
- orex(0,r,0,0x50 + REG_VALUE(r)); /* push r (last %rsp) */
- o(0x08ec8348); /* sub $8,%rsp */
- vstore();
- o(0x08c48348); /* add $8,%rsp */
- o(0x5c); /* pop %rsp */
- break;
-
- case VT_LDOUBLE:
- gv(RC_ST0);
- oad(0xec8148, size); /* sub $xxx, %rsp */
- o(0x7cdb); /* fstpt 0(%rsp) */
- g(0x24);
- g(0x00);
- break;
-
- case VT_FLOAT:
- case VT_DOUBLE:
- assert(mode == x86_64_mode_sse);
- r = gv(RC_FLOAT);
- o(0x50); /* push $rax */
- /* movq %xmmN, (%rsp) */
- o(0xd60f66);
- o(0x04 + REG_VALUE(r)*8);
- o(0x24);
- break;
-
- default:
- assert(mode == x86_64_mode_integer);
- /* simple type */
- /* XXX: implicit cast ? */
- r = gv(RC_INT);
- orex(0,r,0,0x50 + REG_VALUE(r)); /* push r */
- break;
- }
- args_size += size;
-
- vpop();
- --nb_args;
- k++;
- }
-
- tcc_free(onstack);
-
- /* XXX This should be superfluous. */
- save_regs(0); /* save used temporary registers */
-
- /* then, we prepare register passing arguments.
- Note that we cannot set RDX and RCX in this loop because gv()
- may break these temporary registers. Let's use R10 and R11
- instead of them */
- assert(gen_reg <= REGN);
- assert(sse_reg <= 8);
- for(i = 0; i < nb_args; i++) {
- mode = classify_x86_64_arg(&vtop->type, &type, &size, &align, &reg_count);
- if (size == 0) continue;
- /* Alter stack entry type so that gv() knows how to treat it */
- vtop->type = type;
- if (mode == x86_64_mode_sse) {
- if (reg_count == 2) {
- sse_reg -= 2;
- gv(RC_FRET); /* Use pair load into xmm0 & xmm1 */
- if (sse_reg) { /* avoid redundant movaps %xmm0, %xmm0 */
- /* movaps %xmm1, %xmmN */
- o(0x280f);
- o(0xc1 + ((sse_reg+1) << 3));
- /* movaps %xmm0, %xmmN */
- o(0x280f);
- o(0xc0 + (sse_reg << 3));
- }
- } else {
- assert(reg_count == 1);
- --sse_reg;
- /* Load directly to register */
- gv(RC_XMM0 << sse_reg);
- }
- } else if (mode == x86_64_mode_integer) {
- /* simple type */
- /* XXX: implicit cast ? */
- int d;
- gen_reg -= reg_count;
- r = gv(RC_INT);
- d = arg_prepare_reg(gen_reg);
- orex(1,d,r,0x89); /* mov */
- o(0xc0 + REG_VALUE(r) * 8 + REG_VALUE(d));
- if (reg_count == 2) {
- d = arg_prepare_reg(gen_reg+1);
- orex(1,d,vtop->r2,0x89); /* mov */
- o(0xc0 + REG_VALUE(vtop->r2) * 8 + REG_VALUE(d));
- }
- }
- vtop--;
- }
- assert(gen_reg == 0);
- assert(sse_reg == 0);
-
- /* We shouldn't have many operands on the stack anymore, but the
- call address itself is still there, and it might be in %eax
- (or edx/ecx) currently, which the below writes would clobber.
- So evict all remaining operands here. */
- save_regs(0);
-
- /* Copy R10 and R11 into RDX and RCX, respectively */
- if (nb_reg_args > 2) {
- o(0xd2894c); /* mov %r10, %rdx */
- if (nb_reg_args > 3) {
- o(0xd9894c); /* mov %r11, %rcx */
- }
- }
-
- if (vtop->type.ref->f.func_type != FUNC_NEW) /* implies FUNC_OLD or FUNC_ELLIPSIS */
- oad(0xb8, nb_sse_args < 8 ? nb_sse_args : 8); /* mov nb_sse_args, %eax */
- gcall_or_jmp(0);
- if (args_size)
- gadd_sp(args_size);
- vtop--;
-}
-
-#define FUNC_PROLOG_SIZE 11
-
-static void push_arg_reg(int i) {
- loc -= 8;
- gen_modrm64(0x89, arg_regs[i], VT_LOCAL, NULL, loc);
-}
-
-/* generate function prolog of type 't' */
-void gfunc_prolog(Sym *func_sym)
-{
- CType *func_type = &func_sym->type;
- X86_64_Mode mode, ret_mode;
- int i, addr, align, size, reg_count;
- int param_addr = 0, reg_param_index, sse_param_index;
- Sym *sym;
- CType *type;
-
- sym = func_type->ref;
- addr = PTR_SIZE * 2;
- loc = 0;
- ind += FUNC_PROLOG_SIZE;
- func_sub_sp_offset = ind;
- func_ret_sub = 0;
- ret_mode = classify_x86_64_arg(&func_vt, NULL, &size, &align, &reg_count);
-
- if (func_var) {
- int seen_reg_num, seen_sse_num, seen_stack_size;
- seen_reg_num = ret_mode == x86_64_mode_memory;
- seen_sse_num = 0;
- /* frame pointer and return address */
- seen_stack_size = PTR_SIZE * 2;
- /* count the number of seen parameters */
- sym = func_type->ref;
- while ((sym = sym->next) != NULL) {
- type = &sym->type;
- mode = classify_x86_64_arg(type, NULL, &size, &align, &reg_count);
- switch (mode) {
- default:
- stack_arg:
- seen_stack_size = ((seen_stack_size + align - 1) & -align) + size;
- break;
-
- case x86_64_mode_integer:
- if (seen_reg_num + reg_count > REGN)
- goto stack_arg;
- seen_reg_num += reg_count;
- break;
-
- case x86_64_mode_sse:
- if (seen_sse_num + reg_count > 8)
- goto stack_arg;
- seen_sse_num += reg_count;
- break;
- }
- }
-
- loc -= 24;
- /* movl $0x????????, -0x18(%rbp) */
- o(0xe845c7);
- gen_le32(seen_reg_num * 8);
- /* movl $0x????????, -0x14(%rbp) */
- o(0xec45c7);
- gen_le32(seen_sse_num * 16 + 48);
- /* leaq $0x????????, %r11 */
- o(0x9d8d4c);
- gen_le32(seen_stack_size);
- /* movq %r11, -0x10(%rbp) */
- o(0xf05d894c);
- /* leaq $-192(%rbp), %r11 */
- o(0x9d8d4c);
- gen_le32(-176 - 24);
- /* movq %r11, -0x8(%rbp) */
- o(0xf85d894c);
-
- /* save all register passing arguments */
- for (i = 0; i < 8; i++) {
- loc -= 16;
- if (!tcc_state->nosse) {
- o(0xd60f66); /* movq */
- gen_modrm(7 - i, VT_LOCAL, NULL, loc);
- }
- /* movq $0, loc+8(%rbp) */
- o(0x85c748);
- gen_le32(loc + 8);
- gen_le32(0);
- }
- for (i = 0; i < REGN; i++) {
- push_arg_reg(REGN-1-i);
- }
- }
-
- sym = func_type->ref;
- reg_param_index = 0;
- sse_param_index = 0;
-
- /* if the function returns a structure, then add an
- implicit pointer parameter */
- if (ret_mode == x86_64_mode_memory) {
- push_arg_reg(reg_param_index);
- func_vc = loc;
- reg_param_index++;
- }
- /* define parameters */
- while ((sym = sym->next) != NULL) {
- type = &sym->type;
- mode = classify_x86_64_arg(type, NULL, &size, &align, &reg_count);
- switch (mode) {
- case x86_64_mode_sse:
- if (tcc_state->nosse)
- tcc_error("SSE disabled but floating point arguments used");
- if (sse_param_index + reg_count <= 8) {
- /* save arguments passed by register */
- loc -= reg_count * 8;
- param_addr = loc;
- for (i = 0; i < reg_count; ++i) {
- o(0xd60f66); /* movq */
- gen_modrm(sse_param_index, VT_LOCAL, NULL, param_addr + i*8);
- ++sse_param_index;
- }
- } else {
- addr = (addr + align - 1) & -align;
- param_addr = addr;
- addr += size;
- }
- break;
-
- case x86_64_mode_memory:
- case x86_64_mode_x87:
- addr = (addr + align - 1) & -align;
- param_addr = addr;
- addr += size;
- break;
-
- case x86_64_mode_integer: {
- if (reg_param_index + reg_count <= REGN) {
- /* save arguments passed by register */
- loc -= reg_count * 8;
- param_addr = loc;
- for (i = 0; i < reg_count; ++i) {
- gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, param_addr + i*8);
- ++reg_param_index;
- }
- } else {
- addr = (addr + align - 1) & -align;
- param_addr = addr;
- addr += size;
- }
- break;
- }
- default: break; /* nothing to be done for x86_64_mode_none */
- }
- sym_push(sym->v & ~SYM_FIELD, type,
- VT_LOCAL | VT_LVAL, param_addr);
- }
-
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- gen_bounds_prolog();
-#endif
-}
-
-/* generate function epilog */
-void gfunc_epilog(void)
-{
- int v, saved_ind;
-
-#ifdef CONFIG_TCC_BCHECK
- if (tcc_state->do_bounds_check)
- gen_bounds_epilog();
-#endif
- o(0xc9); /* leave */
- if (func_ret_sub == 0) {
- o(0xc3); /* ret */
- } else {
- o(0xc2); /* ret n */
- g(func_ret_sub);
- g(func_ret_sub >> 8);
- }
- /* align local size to word & save local variables */
- v = (-loc + 15) & -16;
- saved_ind = ind;
- ind = func_sub_sp_offset - FUNC_PROLOG_SIZE;
- o(0xe5894855); /* push %rbp, mov %rsp, %rbp */
- o(0xec8148); /* sub rsp, stacksize */
- gen_le32(v);
- ind = saved_ind;
-}
-
-#endif /* not PE */
-
-ST_FUNC void gen_fill_nops(int bytes)
-{
- while (bytes--)
- g(0x90);
-}
-
-/* generate a jump to a label */
-int gjmp(int t)
-{
- return gjmp2(0xe9, t);
-}
-
-/* generate a jump to a fixed address */
-void gjmp_addr(int a)
-{
- int r;
- r = a - ind - 2;
- if (r == (char)r) {
- g(0xeb);
- g(r);
- } else {
- oad(0xe9, a - ind - 5);
- }
-}
-
-ST_FUNC int gjmp_append(int n, int t)
-{
- void *p;
- /* insert vtop->c jump list in t */
- if (n) {
- uint32_t n1 = n, n2;
- while ((n2 = read32le(p = cur_text_section->data + n1)))
- n1 = n2;
- write32le(p, t);
- t = n;
- }
- return t;
-}
-
-ST_FUNC int gjmp_cond(int op, int t)
-{
- if (op & 0x100)
- {
- /* This was a float compare. If the parity flag is set
- the result was unordered. For anything except != this
- means false and we don't jump (anding both conditions).
- For != this means true (oring both).
- Take care about inverting the test. We need to jump
- to our target if the result was unordered and test wasn't NE,
- otherwise if unordered we don't want to jump. */
- int v = vtop->cmp_r;
- op &= ~0x100;
- if (op ^ v ^ (v != TOK_NE))
- o(0x067a); /* jp +6 */
- else
- {
- g(0x0f);
- t = gjmp2(0x8a, t); /* jp t */
- }
- }
- g(0x0f);
- t = gjmp2(op - 16, t);
- return t;
-}
-
-/* generate an integer binary operation */
-void gen_opi(int op)
-{
- int r, fr, opc, c;
- int ll, uu, cc;
-
- ll = is64_type(vtop[-1].type.t);
- uu = (vtop[-1].type.t & VT_UNSIGNED) != 0;
- cc = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
-
- switch(op) {
- case '+':
- case TOK_ADDC1: /* add with carry generation */
- opc = 0;
- gen_op8:
- if (cc && (!ll || (int)vtop->c.i == vtop->c.i)) {
- /* constant case */
- vswap();
- r = gv(RC_INT);
- vswap();
- c = vtop->c.i;
- if (c == (char)c) {
- /* XXX: generate inc and dec for smaller code ? */
- orex(ll, r, 0, 0x83);
- o(0xc0 | (opc << 3) | REG_VALUE(r));
- g(c);
- } else {
- orex(ll, r, 0, 0x81);
- oad(0xc0 | (opc << 3) | REG_VALUE(r), c);
- }
- } else {
- gv2(RC_INT, RC_INT);
- r = vtop[-1].r;
- fr = vtop[0].r;
- orex(ll, r, fr, (opc << 3) | 0x01);
- o(0xc0 + REG_VALUE(r) + REG_VALUE(fr) * 8);
- }
- vtop--;
- if (op >= TOK_ULT && op <= TOK_GT)
- vset_VT_CMP(op);
- break;
- case '-':
- case TOK_SUBC1: /* sub with carry generation */
- opc = 5;
- goto gen_op8;
- case TOK_ADDC2: /* add with carry use */
- opc = 2;
- goto gen_op8;
- case TOK_SUBC2: /* sub with carry use */
- opc = 3;
- goto gen_op8;
- case '&':
- opc = 4;
- goto gen_op8;
- case '^':
- opc = 6;
- goto gen_op8;
- case '|':
- opc = 1;
- goto gen_op8;
- case '*':
- gv2(RC_INT, RC_INT);
- r = vtop[-1].r;
- fr = vtop[0].r;
- orex(ll, fr, r, 0xaf0f); /* imul fr, r */
- o(0xc0 + REG_VALUE(fr) + REG_VALUE(r) * 8);
- vtop--;
- break;
- case TOK_SHL:
- opc = 4;
- goto gen_shift;
- case TOK_SHR:
- opc = 5;
- goto gen_shift;
- case TOK_SAR:
- opc = 7;
- gen_shift:
- opc = 0xc0 | (opc << 3);
- if (cc) {
- /* constant case */
- vswap();
- r = gv(RC_INT);
- vswap();
- orex(ll, r, 0, 0xc1); /* shl/shr/sar $xxx, r */
- o(opc | REG_VALUE(r));
- g(vtop->c.i & (ll ? 63 : 31));
- } else {
- /* we generate the shift in ecx */
- gv2(RC_INT, RC_RCX);
- r = vtop[-1].r;
- orex(ll, r, 0, 0xd3); /* shl/shr/sar %cl, r */
- o(opc | REG_VALUE(r));
- }
- vtop--;
- break;
- case TOK_UDIV:
- case TOK_UMOD:
- uu = 1;
- goto divmod;
- case '/':
- case '%':
- case TOK_PDIV:
- uu = 0;
- divmod:
- /* first operand must be in eax */
- /* XXX: need better constraint for second operand */
- gv2(RC_RAX, RC_RCX);
- r = vtop[-1].r;
- fr = vtop[0].r;
- vtop--;
- save_reg(TREG_RDX);
- orex(ll, 0, 0, uu ? 0xd231 : 0x99); /* xor %edx,%edx : cqto */
- orex(ll, fr, 0, 0xf7); /* div fr, %eax */
- o((uu ? 0xf0 : 0xf8) + REG_VALUE(fr));
- if (op == '%' || op == TOK_UMOD)
- r = TREG_RDX;
- else
- r = TREG_RAX;
- vtop->r = r;
- break;
- default:
- opc = 7;
- goto gen_op8;
- }
-}
-
-void gen_opl(int op)
-{
- gen_opi(op);
-}
-
-void vpush_const(int t, int v)
-{
- CType ctype = { t | VT_CONSTANT, 0 };
- vpushsym(&ctype, external_global_sym(v, &ctype));
- vtop->r |= VT_LVAL;
-}
-
-/* generate a floating point operation 'v = t1 op t2' instruction. The
- two operands are guaranteed to have the same floating point type */
-/* XXX: need to use ST1 too */
-void gen_opf(int op)
-{
- int a, ft, fc, swapped, r;
- int bt = vtop->type.t & VT_BTYPE;
- int float_type = bt == VT_LDOUBLE ? RC_ST0 : RC_FLOAT;
-
- if (op == TOK_NEG) { /* unary minus */
- gv(float_type);
- if (float_type == RC_ST0) {
- o(0xe0d9); /* fchs */
- } else {
- /* -0.0, in libtcc1.c */
- vpush_const(bt, bt == VT_FLOAT ? TOK___mzerosf : TOK___mzerodf);
- gv(RC_FLOAT);
- if (bt == VT_DOUBLE)
- o(0x66);
- /* xorp[sd] %xmm1, %xmm0 */
- o(0xc0570f | (REG_VALUE(vtop[0].r) + REG_VALUE(vtop[-1].r)*8) << 16);
- vtop--;
- }
- return;
- }
-
- /* convert constants to memory references */
- if ((vtop[-1].r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
- vswap();
- gv(float_type);
- vswap();
- }
- if ((vtop[0].r & (VT_VALMASK | VT_LVAL)) == VT_CONST)
- gv(float_type);
-
- /* must put at least one value in the floating point register */
- if ((vtop[-1].r & VT_LVAL) &&
- (vtop[0].r & VT_LVAL)) {
- vswap();
- gv(float_type);
- vswap();
- }
- swapped = 0;
- /* swap the stack if needed so that t1 is the register and t2 is
- the memory reference */
- if (vtop[-1].r & VT_LVAL) {
- vswap();
- swapped = 1;
- }
- if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
- if (op >= TOK_ULT && op <= TOK_GT) {
- /* load on stack second operand */
- load(TREG_ST0, vtop);
- save_reg(TREG_RAX); /* eax is used by FP comparison code */
- if (op == TOK_GE || op == TOK_GT)
- swapped = !swapped;
- else if (op == TOK_EQ || op == TOK_NE)
- swapped = 0;
- if (swapped)
- o(0xc9d9); /* fxch %st(1) */
- if (op == TOK_EQ || op == TOK_NE)
- o(0xe9da); /* fucompp */
- else
- o(0xd9de); /* fcompp */
- o(0xe0df); /* fnstsw %ax */
- if (op == TOK_EQ) {
- o(0x45e480); /* and $0x45, %ah */
- o(0x40fC80); /* cmp $0x40, %ah */
- } else if (op == TOK_NE) {
- o(0x45e480); /* and $0x45, %ah */
- o(0x40f480); /* xor $0x40, %ah */
- op = TOK_NE;
- } else if (op == TOK_GE || op == TOK_LE) {
- o(0x05c4f6); /* test $0x05, %ah */
- op = TOK_EQ;
- } else {
- o(0x45c4f6); /* test $0x45, %ah */
- op = TOK_EQ;
- }
- vtop--;
- vset_VT_CMP(op);
- } else {
- /* no memory reference possible for long double operations */
- load(TREG_ST0, vtop);
- swapped = !swapped;
-
- switch(op) {
- default:
- case '+':
- a = 0;
- break;
- case '-':
- a = 4;
- if (swapped)
- a++;
- break;
- case '*':
- a = 1;
- break;
- case '/':
- a = 6;
- if (swapped)
- a++;
- break;
- }
- ft = vtop->type.t;
- fc = vtop->c.i;
- o(0xde); /* fxxxp %st, %st(1) */
- o(0xc1 + (a << 3));
- vtop--;
- }
- } else {
- if (op >= TOK_ULT && op <= TOK_GT) {
- /* if saved lvalue, then we must reload it */
- r = vtop->r;
- fc = vtop->c.i;
- if ((r & VT_VALMASK) == VT_LLOCAL) {
- SValue v1;
- r = get_reg(RC_INT);
- v1.type.t = VT_PTR;
- v1.r = VT_LOCAL | VT_LVAL;
- v1.c.i = fc;
- load(r, &v1);
- fc = 0;
- vtop->r = r = r | VT_LVAL;
- }
-
- if (op == TOK_EQ || op == TOK_NE) {
- swapped = 0;
- } else {
- if (op == TOK_LE || op == TOK_LT)
- swapped = !swapped;
- if (op == TOK_LE || op == TOK_GE) {
- op = 0x93; /* setae */
- } else {
- op = 0x97; /* seta */
- }
- }
-
- if (swapped) {
- gv(RC_FLOAT);
- vswap();
- }
- assert(!(vtop[-1].r & VT_LVAL));
-
- if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
- o(0x66);
- if (op == TOK_EQ || op == TOK_NE)
- o(0x2e0f); /* ucomisd */
- else
- o(0x2f0f); /* comisd */
-
- if (vtop->r & VT_LVAL) {
- gen_modrm(vtop[-1].r, r, vtop->sym, fc);
- } else {
- o(0xc0 + REG_VALUE(vtop[0].r) + REG_VALUE(vtop[-1].r)*8);
- }
-
- vtop--;
- vset_VT_CMP(op | 0x100);
- vtop->cmp_r = op;
- } else {
- assert((vtop->type.t & VT_BTYPE) != VT_LDOUBLE);
- switch(op) {
- default:
- case '+':
- a = 0;
- break;
- case '-':
- a = 4;
- break;
- case '*':
- a = 1;
- break;
- case '/':
- a = 6;
- break;
- }
- ft = vtop->type.t;
- fc = vtop->c.i;
- assert((ft & VT_BTYPE) != VT_LDOUBLE);
-
- r = vtop->r;
- /* if saved lvalue, then we must reload it */
- if ((vtop->r & VT_VALMASK) == VT_LLOCAL) {
- SValue v1;
- r = get_reg(RC_INT);
- v1.type.t = VT_PTR;
- v1.r = VT_LOCAL | VT_LVAL;
- v1.c.i = fc;
- load(r, &v1);
- fc = 0;
- vtop->r = r = r | VT_LVAL;
- }
-
- assert(!(vtop[-1].r & VT_LVAL));
- if (swapped) {
- assert(vtop->r & VT_LVAL);
- gv(RC_FLOAT);
- vswap();
- }
-
- if ((ft & VT_BTYPE) == VT_DOUBLE) {
- o(0xf2);
- } else {
- o(0xf3);
- }
- o(0x0f);
- o(0x58 + a);
-
- if (vtop->r & VT_LVAL) {
- gen_modrm(vtop[-1].r, r, vtop->sym, fc);
- } else {
- o(0xc0 + REG_VALUE(vtop[0].r) + REG_VALUE(vtop[-1].r)*8);
- }
-
- vtop--;
- }
- }
-}
-
-/* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
- and 'long long' cases. */
-void gen_cvt_itof(int t)
-{
- if ((t & VT_BTYPE) == VT_LDOUBLE) {
- save_reg(TREG_ST0);
- gv(RC_INT);
- if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
- /* signed long long to float/double/long double (unsigned case
- is handled generically) */
- o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
- o(0x242cdf); /* fildll (%rsp) */
- o(0x08c48348); /* add $8, %rsp */
- } else if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
- (VT_INT | VT_UNSIGNED)) {
- /* unsigned int to float/double/long double */
- o(0x6a); /* push $0 */
- g(0x00);
- o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
- o(0x242cdf); /* fildll (%rsp) */
- o(0x10c48348); /* add $16, %rsp */
- } else {
- /* int to float/double/long double */
- o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
- o(0x2404db); /* fildl (%rsp) */
- o(0x08c48348); /* add $8, %rsp */
- }
- vtop->r = TREG_ST0;
- } else {
- int r = get_reg(RC_FLOAT);
- gv(RC_INT);
- o(0xf2 + ((t & VT_BTYPE) == VT_FLOAT?1:0));
- if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
- (VT_INT | VT_UNSIGNED) ||
- (vtop->type.t & VT_BTYPE) == VT_LLONG) {
- o(0x48); /* REX */
- }
- o(0x2a0f);
- o(0xc0 + (vtop->r & VT_VALMASK) + REG_VALUE(r)*8); /* cvtsi2sd */
- vtop->r = r;
- }
-}
-
-/* convert from one floating point type to another */
-void gen_cvt_ftof(int t)
-{
- int ft, bt, tbt;
-
- ft = vtop->type.t;
- bt = ft & VT_BTYPE;
- tbt = t & VT_BTYPE;
-
- if (bt == VT_FLOAT) {
- gv(RC_FLOAT);
- if (tbt == VT_DOUBLE) {
- o(0x140f); /* unpcklps */
- o(0xc0 + REG_VALUE(vtop->r)*9);
- o(0x5a0f); /* cvtps2pd */
- o(0xc0 + REG_VALUE(vtop->r)*9);
- } else if (tbt == VT_LDOUBLE) {
- save_reg(RC_ST0);
- /* movss %xmm0,-0x10(%rsp) */
- o(0x110ff3);
- o(0x44 + REG_VALUE(vtop->r)*8);
- o(0xf024);
- o(0xf02444d9); /* flds -0x10(%rsp) */
- vtop->r = TREG_ST0;
- }
- } else if (bt == VT_DOUBLE) {
- gv(RC_FLOAT);
- if (tbt == VT_FLOAT) {
- o(0x140f66); /* unpcklpd */
- o(0xc0 + REG_VALUE(vtop->r)*9);
- o(0x5a0f66); /* cvtpd2ps */
- o(0xc0 + REG_VALUE(vtop->r)*9);
- } else if (tbt == VT_LDOUBLE) {
- save_reg(RC_ST0);
- /* movsd %xmm0,-0x10(%rsp) */
- o(0x110ff2);
- o(0x44 + REG_VALUE(vtop->r)*8);
- o(0xf024);
- o(0xf02444dd); /* fldl -0x10(%rsp) */
- vtop->r = TREG_ST0;
- }
- } else {
- int r;
- gv(RC_ST0);
- r = get_reg(RC_FLOAT);
- if (tbt == VT_DOUBLE) {
- o(0xf0245cdd); /* fstpl -0x10(%rsp) */
- /* movsd -0x10(%rsp),%xmm0 */
- o(0x100ff2);
- o(0x44 + REG_VALUE(r)*8);
- o(0xf024);
- vtop->r = r;
- } else if (tbt == VT_FLOAT) {
- o(0xf0245cd9); /* fstps -0x10(%rsp) */
- /* movss -0x10(%rsp),%xmm0 */
- o(0x100ff3);
- o(0x44 + REG_VALUE(r)*8);
- o(0xf024);
- vtop->r = r;
- }
- }
-}
-
-/* convert fp to int 't' type */
-void gen_cvt_ftoi(int t)
-{
- int ft, bt, size, r;
- ft = vtop->type.t;
- bt = ft & VT_BTYPE;
- if (bt == VT_LDOUBLE) {
- gen_cvt_ftof(VT_DOUBLE);
- bt = VT_DOUBLE;
- }
-
- gv(RC_FLOAT);
- if (t != VT_INT)
- size = 8;
- else
- size = 4;
-
- r = get_reg(RC_INT);
- if (bt == VT_FLOAT) {
- o(0xf3);
- } else if (bt == VT_DOUBLE) {
- o(0xf2);
- } else {
- assert(0);
- }
- orex(size == 8, r, 0, 0x2c0f); /* cvttss2si or cvttsd2si */
- o(0xc0 + REG_VALUE(vtop->r) + REG_VALUE(r)*8);
- vtop->r = r;
-}
-
-// Generate sign extension from 32 to 64 bits:
-ST_FUNC void gen_cvt_sxtw(void)
-{
- int r = gv(RC_INT);
- /* x86_64 specific: movslq */
- o(0x6348);
- o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
-}
-
-/* char/short to int conversion */
-ST_FUNC void gen_cvt_csti(int t)
-{
- int r, sz, xl, ll;
- r = gv(RC_INT);
- sz = !(t & VT_UNSIGNED);
- xl = (t & VT_BTYPE) == VT_SHORT;
- ll = (vtop->type.t & VT_BTYPE) == VT_LLONG;
- orex(ll, r, 0, 0xc0b60f /* mov[sz] %a[xl], %eax */
- | (sz << 3 | xl) << 8
- | (REG_VALUE(r) << 3 | REG_VALUE(r)) << 16
- );
-}
-
-/* increment tcov counter */
-ST_FUNC void gen_increment_tcov (SValue *sv)
-{
- o(0x058348); /* addq $1, xxx(%rip) */
- greloca(cur_text_section, sv->sym, ind, R_X86_64_PC32, -5);
- gen_le32(0);
- o(1);
-}
-
-/* computed goto support */
-ST_FUNC void ggoto(void)
-{
- gcall_or_jmp(1);
- vtop--;
-}
-
-/* Save the stack pointer onto the stack and return the location of its address */
-ST_FUNC void gen_vla_sp_save(int addr) {
- /* mov %rsp,addr(%rbp)*/
- gen_modrm64(0x89, TREG_RSP, VT_LOCAL, NULL, addr);
-}
-
-/* Restore the SP from a location on the stack */
-ST_FUNC void gen_vla_sp_restore(int addr) {
- gen_modrm64(0x8b, TREG_RSP, VT_LOCAL, NULL, addr);
-}
-
-#ifdef TCC_TARGET_PE
-/* Save result of gen_vla_alloc onto the stack */
-ST_FUNC void gen_vla_result(int addr) {
- /* mov %rax,addr(%rbp)*/
- gen_modrm64(0x89, TREG_RAX, VT_LOCAL, NULL, addr);
-}
-#endif
-
-/* Subtract from the stack pointer, and push the resulting value onto the stack */
-ST_FUNC void gen_vla_alloc(CType *type, int align) {
- int use_call = 0;
-
-#if defined(CONFIG_TCC_BCHECK)
- use_call = tcc_state->do_bounds_check;
-#endif
-#ifdef TCC_TARGET_PE /* alloca does more than just adjust %rsp on Windows */
- use_call = 1;
-#endif
- if (use_call)
- {
- vpush_helper_func(TOK_alloca);
- vswap(); /* Move alloca ref past allocation size */
- gfunc_call(1);
- }
- else {
- int r;
- r = gv(RC_INT); /* allocation size */
- /* sub r,%rsp */
- o(0x2b48);
- o(0xe0 | REG_VALUE(r));
- /* We align to 16 bytes rather than align */
- /* and ~15, %rsp */
- o(0xf0e48348);
- vpop();
- }
-}
-
-/*
- * Assmuing the top part of the stack looks like below,
- * src dest src
- */
-ST_FUNC void gen_struct_copy(int size)
-{
- int n = size / PTR_SIZE;
-#ifdef TCC_TARGET_PE
- o(0x5756); /* push rsi, rdi */
-#endif
- gv2(RC_RDI, RC_RSI);
- if (n <= 4) {
- while (n)
- o(0xa548), --n;
- } else {
- vpushi(n);
- gv(RC_RCX);
- o(0xa548f3);
- vpop();
- }
- if (size & 0x04)
- o(0xa5);
- if (size & 0x02)
- o(0xa566);
- if (size & 0x01)
- o(0xa4);
-#ifdef TCC_TARGET_PE
- o(0x5e5f); /* pop rdi, rsi */
-#endif
- vpop();
- vpop();
-}
-
-/* end of x86-64 code generator */
-/*************************************************************/
-#endif /* ! TARGET_DEFS_ONLY */
-/******************************************************/
diff --git a/tinycc/x86_64-link.c b/tinycc/x86_64-link.c
deleted file mode 100644
index 1b6aa09..0000000
--- a/tinycc/x86_64-link.c
+++ /dev/null
@@ -1,403 +0,0 @@
-#ifdef TARGET_DEFS_ONLY
-
-#define EM_TCC_TARGET EM_X86_64
-
-/* relocation type for 32 bit data relocation */
-#define R_DATA_32 R_X86_64_32S
-#define R_DATA_PTR R_X86_64_64
-#define R_JMP_SLOT R_X86_64_JUMP_SLOT
-#define R_GLOB_DAT R_X86_64_GLOB_DAT
-#define R_COPY R_X86_64_COPY
-#define R_RELATIVE R_X86_64_RELATIVE
-
-#define R_NUM R_X86_64_NUM
-
-#define ELF_START_ADDR 0x400000
-#define ELF_PAGE_SIZE 0x200000
-
-#define PCRELATIVE_DLLPLT 1
-#define RELOCATE_DLLPLT 1
-
-#else /* !TARGET_DEFS_ONLY */
-
-#include "tcc.h"
-
-#ifdef NEED_RELOC_TYPE
-/* Returns 1 for a code relocation, 0 for a data relocation. For unknown
- relocations, returns -1. */
-int code_reloc (int reloc_type)
-{
- switch (reloc_type) {
- case R_X86_64_32:
- case R_X86_64_32S:
- case R_X86_64_64:
- case R_X86_64_GOTPC32:
- case R_X86_64_GOTPC64:
- case R_X86_64_GOTPCREL:
- case R_X86_64_GOTPCRELX:
- case R_X86_64_REX_GOTPCRELX:
- case R_X86_64_GOTTPOFF:
- case R_X86_64_GOT32:
- case R_X86_64_GOT64:
- case R_X86_64_GLOB_DAT:
- case R_X86_64_COPY:
- case R_X86_64_RELATIVE:
- case R_X86_64_GOTOFF64:
- case R_X86_64_TLSGD:
- case R_X86_64_TLSLD:
- case R_X86_64_DTPOFF32:
- case R_X86_64_TPOFF32:
- case R_X86_64_DTPOFF64:
- case R_X86_64_TPOFF64:
- return 0;
-
- case R_X86_64_PC32:
- case R_X86_64_PC64:
- case R_X86_64_PLT32:
- case R_X86_64_PLTOFF64:
- case R_X86_64_JUMP_SLOT:
- return 1;
- }
- return -1;
-}
-
-/* Returns an enumerator to describe whether and when the relocation needs a
- GOT and/or PLT entry to be created. See tcc.h for a description of the
- different values. */
-int gotplt_entry_type (int reloc_type)
-{
- switch (reloc_type) {
- case R_X86_64_GLOB_DAT:
- case R_X86_64_JUMP_SLOT:
- case R_X86_64_COPY:
- case R_X86_64_RELATIVE:
- return NO_GOTPLT_ENTRY;
-
- /* The following relocs wouldn't normally need GOT or PLT
- slots, but we need them for simplicity in the link
- editor part. See our caller for comments. */
- case R_X86_64_32:
- case R_X86_64_32S:
- case R_X86_64_64:
- case R_X86_64_PC32:
- case R_X86_64_PC64:
- return AUTO_GOTPLT_ENTRY;
-
- case R_X86_64_GOTTPOFF:
- return BUILD_GOT_ONLY;
-
- case R_X86_64_GOT32:
- case R_X86_64_GOT64:
- case R_X86_64_GOTPC32:
- case R_X86_64_GOTPC64:
- case R_X86_64_GOTOFF64:
- case R_X86_64_GOTPCREL:
- case R_X86_64_GOTPCRELX:
- case R_X86_64_TLSGD:
- case R_X86_64_TLSLD:
- case R_X86_64_DTPOFF32:
- case R_X86_64_TPOFF32:
- case R_X86_64_DTPOFF64:
- case R_X86_64_TPOFF64:
- case R_X86_64_REX_GOTPCRELX:
- case R_X86_64_PLT32:
- case R_X86_64_PLTOFF64:
- return ALWAYS_GOTPLT_ENTRY;
- }
-
- return -1;
-}
-
-#ifdef NEED_BUILD_GOT
-ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_attr *attr)
-{
- Section *plt = s1->plt;
- uint8_t *p;
- int modrm;
- unsigned plt_offset, relofs;
-
- modrm = 0x25;
-
- /* empty PLT: create PLT0 entry that pushes the library identifier
- (GOT + PTR_SIZE) and jumps to ld.so resolution routine
- (GOT + 2 * PTR_SIZE) */
- if (plt->data_offset == 0) {
- p = section_ptr_add(plt, 16);
- p[0] = 0xff; /* pushl got + PTR_SIZE */
- p[1] = modrm + 0x10;
- write32le(p + 2, PTR_SIZE);
- p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
- p[7] = modrm;
- write32le(p + 8, PTR_SIZE * 2);
- }
- plt_offset = plt->data_offset;
-
- /* The PLT slot refers to the relocation entry it needs via offset.
- The reloc entry is created below, so its offset is the current
- data_offset */
- relofs = s1->plt->reloc ? s1->plt->reloc->data_offset : 0;
-
- /* Jump to GOT entry where ld.so initially put the address of ip + 4 */
- p = section_ptr_add(plt, 16);
- p[0] = 0xff; /* jmp *(got + x) */
- p[1] = modrm;
- write32le(p + 2, got_offset);
- p[6] = 0x68; /* push $xxx */
- /* On x86-64, the relocation is referred to by _index_ */
- write32le(p + 7, relofs / sizeof (ElfW_Rel) - 1);
- p[11] = 0xe9; /* jmp plt_start */
- write32le(p + 12, -(plt->data_offset));
- return plt_offset;
-}
-
-/* relocate the PLT: compute addresses and offsets in the PLT now that final
- address for PLT and GOT are known (see fill_program_header) */
-ST_FUNC void relocate_plt(TCCState *s1)
-{
- uint8_t *p, *p_end;
-
- if (!s1->plt)
- return;
-
- p = s1->plt->data;
- p_end = p + s1->plt->data_offset;
-
- if (p < p_end) {
- int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
- add32le(p + 2, x);
- add32le(p + 8, x - 6);
- p += 16;
- while (p < p_end) {
- add32le(p + 2, x + (s1->plt->data - p));
- p += 16;
- }
- }
-
- if (s1->plt->reloc) {
- ElfW_Rel *rel;
- int x = s1->plt->sh_addr + 16 + 6;
- p = s1->got->data;
- for_each_elem(s1->plt->reloc, 0, rel, ElfW_Rel) {
- write64le(p + rel->r_offset, x);
- x += 16;
- }
- }
-}
-#endif
-#endif
-
-void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t addr, addr_t val)
-{
- int sym_index, esym_index;
-
- sym_index = ELFW(R_SYM)(rel->r_info);
-
- switch (type) {
- case R_X86_64_64:
- if (s1->output_type & TCC_OUTPUT_DYN) {
- esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
- qrel->r_offset = rel->r_offset;
- if (esym_index) {
- qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_64);
- qrel->r_addend = rel->r_addend;
- qrel++;
- break;
- } else {
- qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
- qrel->r_addend = read64le(ptr) + val;
- qrel++;
- }
- }
- add64le(ptr, val);
- break;
- case R_X86_64_32:
- case R_X86_64_32S:
- if (s1->output_type & TCC_OUTPUT_DYN) {
- /* XXX: this logic may depend on TCC's codegen
- now TCC uses R_X86_64_32 even for a 64bit pointer */
- qrel->r_offset = rel->r_offset;
- qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
- /* Use sign extension! */
- qrel->r_addend = (int)read32le(ptr) + val;
- qrel++;
- }
- add32le(ptr, val);
- break;
-
- case R_X86_64_PC32:
- if (s1->output_type == TCC_OUTPUT_DLL) {
- /* DLL relocation */
- esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
- if (esym_index) {
- qrel->r_offset = rel->r_offset;
- qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
- /* Use sign extension! */
- qrel->r_addend = (int)read32le(ptr) + rel->r_addend;
- qrel++;
- break;
- }
- }
- goto plt32pc32;
-
- case R_X86_64_PLT32:
- /* fallthrough: val already holds the PLT slot address */
-
- plt32pc32:
- {
- long long diff;
- diff = (long long)val - addr;
- if (diff < -2147483648LL || diff > 2147483647LL) {
-#ifdef TCC_TARGET_PE
- /* ignore overflow with undefined weak symbols */
- if (((ElfW(Sym)*)symtab_section->data)[sym_index].st_shndx != SHN_UNDEF)
-#endif
- tcc_error_noabort("internal error: relocation failed");
- }
- add32le(ptr, diff);
- }
- break;
-
- case R_X86_64_COPY:
- break;
-
- case R_X86_64_PLTOFF64:
- add64le(ptr, val - s1->got->sh_addr + rel->r_addend);
- break;
-
- case R_X86_64_PC64:
- if (s1->output_type == TCC_OUTPUT_DLL) {
- /* DLL relocation */
- esym_index = get_sym_attr(s1, sym_index, 0)->dyn_index;
- if (esym_index) {
- qrel->r_offset = rel->r_offset;
- qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC64);
- qrel->r_addend = read64le(ptr) + rel->r_addend;
- qrel++;
- break;
- }
- }
- add64le(ptr, val - addr);
- break;
-
- case R_X86_64_GLOB_DAT:
- case R_X86_64_JUMP_SLOT:
- /* They don't need addend */
- write64le(ptr, val - rel->r_addend);
- break;
- case R_X86_64_GOTPCREL:
- case R_X86_64_GOTPCRELX:
- case R_X86_64_REX_GOTPCRELX:
- add32le(ptr, s1->got->sh_addr - addr +
- get_sym_attr(s1, sym_index, 0)->got_offset - 4);
- break;
- case R_X86_64_GOTPC32:
- add32le(ptr, s1->got->sh_addr - addr + rel->r_addend);
- break;
- case R_X86_64_GOTPC64:
- add64le(ptr, s1->got->sh_addr - addr + rel->r_addend);
- break;
- case R_X86_64_GOTTPOFF:
- add32le(ptr, val - s1->got->sh_addr);
- break;
- case R_X86_64_GOT32:
- /* we load the got offset */
- add32le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
- break;
- case R_X86_64_GOT64:
- /* we load the got offset */
- add64le(ptr, get_sym_attr(s1, sym_index, 0)->got_offset);
- break;
- case R_X86_64_GOTOFF64:
- add64le(ptr, val - s1->got->sh_addr);
- break;
- case R_X86_64_TLSGD:
- {
- static const unsigned char expect[] = {
- /* .byte 0x66; lea 0(%rip),%rdi */
- 0x66, 0x48, 0x8d, 0x3d, 0x00, 0x00, 0x00, 0x00,
- /* .word 0x6666; rex64; call __tls_get_addr@PLT */
- 0x66, 0x66, 0x48, 0xe8, 0x00, 0x00, 0x00, 0x00 };
- static const unsigned char replace[] = {
- /* mov %fs:0,%rax */
- 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00,
- /* lea -4(%rax),%rax */
- 0x48, 0x8d, 0x80, 0x00, 0x00, 0x00, 0x00 };
-
- if (memcmp (ptr-4, expect, sizeof(expect)) == 0) {
- ElfW(Sym) *sym;
- Section *sec;
- int32_t x;
-
- memcpy(ptr-4, replace, sizeof(replace));
- rel[1].r_info = ELFW(R_INFO)(0, R_X86_64_NONE);
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- sec = s1->sections[sym->st_shndx];
- x = sym->st_value - sec->sh_addr - sec->data_offset;
- add32le(ptr + 8, x);
- }
- else
- tcc_error_noabort("unexpected R_X86_64_TLSGD pattern");
- }
- break;
- case R_X86_64_TLSLD:
- {
- static const unsigned char expect[] = {
- /* lea 0(%rip),%rdi */
- 0x48, 0x8d, 0x3d, 0x00, 0x00, 0x00, 0x00,
- /* call __tls_get_addr@PLT */
- 0xe8, 0x00, 0x00, 0x00, 0x00 };
- static const unsigned char replace[] = {
- /* data16 data16 data16 mov %fs:0,%rax */
- 0x66, 0x66, 0x66, 0x64, 0x48, 0x8b, 0x04, 0x25,
- 0x00, 0x00, 0x00, 0x00 };
-
- if (memcmp (ptr-3, expect, sizeof(expect)) == 0) {
- memcpy(ptr-3, replace, sizeof(replace));
- rel[1].r_info = ELFW(R_INFO)(0, R_X86_64_NONE);
- }
- else
- tcc_error_noabort("unexpected R_X86_64_TLSLD pattern");
- }
- break;
- case R_X86_64_DTPOFF32:
- case R_X86_64_TPOFF32:
- {
- ElfW(Sym) *sym;
- Section *sec;
- int32_t x;
-
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- sec = s1->sections[sym->st_shndx];
- x = val - sec->sh_addr - sec->data_offset;
- add32le(ptr, x);
- }
- break;
- case R_X86_64_DTPOFF64:
- case R_X86_64_TPOFF64:
- {
- ElfW(Sym) *sym;
- Section *sec;
- int32_t x;
-
- sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
- sec = s1->sections[sym->st_shndx];
- x = val - sec->sh_addr - sec->data_offset;
- add64le(ptr, x);
- }
- break;
- case R_X86_64_NONE:
- break;
- case R_X86_64_RELATIVE:
-#ifdef TCC_TARGET_PE
- add32le(ptr, val - s1->pe_imagebase);
-#endif
- /* do nothing */
- break;
- default:
- fprintf(stderr,"FIXME: handle reloc type %d at %x [%p] to %x\n",
- type, (unsigned)addr, ptr, (unsigned)val);
- break;
- }
-}
-
-#endif /* !TARGET_DEFS_ONLY */