Compare commits
186 Commits
ravi-distr
...
master
Author | SHA1 | Date |
---|---|---|
Pavel R. | 7adbc171f6 | 3 years ago |
Pavel R. | 072d2c37f0 | 3 years ago |
Pavel R. | 21fd437e89 | 3 years ago |
annelin | 73de201165 | 3 years ago |
annelin | be65484feb | 3 years ago |
annelin | 7d376acf62 | 3 years ago |
Pavel R. | 3995761bf1 | 3 years ago |
Pavel R. | 5359ca1d5f | 3 years ago |
Dibyendu Majumdar | d022074ae6 | 3 years ago |
Dibyendu Majumdar | cf3be2e688 | 3 years ago |
Dibyendu Majumdar | bbf2c29077 | 3 years ago |
Dibyendu Majumdar | 2c81edafa0 | 3 years ago |
Dibyendu Majumdar | b073242254 | 3 years ago |
Dibyendu Majumdar | 6eb43324dd | 3 years ago |
Dibyendu Majumdar | 4bfc061a2a | 3 years ago |
Dibyendu Majumdar | 3efaddee6b | 3 years ago |
Dibyendu Majumdar | d5e324fd53 | 3 years ago |
Dibyendu Majumdar | e3d8203bd9 | 3 years ago |
Dibyendu Majumdar | 53ec0c19b3 | 3 years ago |
XmiliaH | 5ca801596a | 3 years ago |
Dibyendu Majumdar | 58980db5cb | 3 years ago |
Dibyendu Majumdar | 347ae985bc | 3 years ago |
Dibyendu Majumdar | 063a55604e | 3 years ago |
Dibyendu Majumdar | 8e815bd67a | 3 years ago |
Dibyendu Majumdar | 658f04c3d8 | 3 years ago |
Dibyendu Majumdar | 8fd3a1bbab | 3 years ago |
Dibyendu Majumdar | b5afdfaa46 | 3 years ago |
Dibyendu Majumdar | 88ccaf34a0 | 3 years ago |
Dibyendu Majumdar | 5c30d255c7 | 3 years ago |
Dibyendu Majumdar | 248c730c43 | 3 years ago |
Dibyendu Majumdar | 4a20693671 | 3 years ago |
Dibyendu Majumdar | cb6943a1eb | 3 years ago |
XmiliaH | 837dc959cf | 3 years ago |
Dibyendu Majumdar | 754fcefc26 | 3 years ago |
XmiliaH | b4359b9391 | 3 years ago |
XmiliaH | a9537957d5 | 3 years ago |
XmiliaH | 435480f4db | 3 years ago |
XmiliaH | 62ab591343 | 3 years ago |
XmiliaH | f80e4d5442 | 3 years ago |
XmiliaH | 7789f4f32d | 3 years ago |
XmiliaH | c0122cd816 | 3 years ago |
XmiliaH | 58cdc8d7dc | 3 years ago |
XmiliaH | 6af3d804a4 | 3 years ago |
XmiliaH | 871b76fea2 | 3 years ago |
XmiliaH | 0b43c94a4d | 3 years ago |
XmiliaH | e85634270f | 3 years ago |
XmiliaH | 4cce67ec13 | 3 years ago |
Dibyendu Majumdar | a2ec53624d | 3 years ago |
Dibyendu Majumdar | 9bceadd099 | 3 years ago |
Dibyendu Majumdar | 25dbc31393 | 3 years ago |
Dibyendu Majumdar | 2c5b958d04 | 3 years ago |
Dibyendu Majumdar | b0a5b01142 | 3 years ago |
Dibyendu Majumdar | 170fd797a2 | 3 years ago |
Dibyendu Majumdar | b2cc7c30c5 | 3 years ago |
Dibyendu Majumdar | 2decef927a | 3 years ago |
Dibyendu Majumdar | 486145900b | 3 years ago |
Dibyendu Majumdar | a3b933aa43 | 3 years ago |
Dibyendu Majumdar | 1e8597de7d | 3 years ago |
Dibyendu Majumdar | 9ced7e2bc0 | 3 years ago |
Dibyendu Majumdar | fe7c76fff5 | 3 years ago |
Dibyendu Majumdar | ad4fc4e2d2 | 3 years ago |
Dibyendu Majumdar | 2c44bdd68b | 3 years ago |
Dibyendu Majumdar | 8bd404f62e | 3 years ago |
Dibyendu Majumdar | 4342fc7630 | 3 years ago |
Dibyendu Majumdar | 927ddbf6a0 | 3 years ago |
Dibyendu Majumdar | b549302d70 | 3 years ago |
Dibyendu Majumdar | 56a59a1f31 | 3 years ago |
Dibyendu Majumdar | 773ebd9d32 | 3 years ago |
Dibyendu Majumdar | def4d76ac9 | 3 years ago |
Dibyendu Majumdar | ef24ca67cb | 3 years ago |
Dibyendu Majumdar | 77cd6b9527 | 3 years ago |
Dibyendu Majumdar | 61a8ac889f | 3 years ago |
Dibyendu Majumdar | 102c8bee8b | 3 years ago |
Dibyendu Majumdar | 3e05644f51 | 3 years ago |
Dibyendu Majumdar | f7f59eed0f | 3 years ago |
Dibyendu Majumdar | 2aeeea4dd3 | 3 years ago |
Dibyendu Majumdar | 31774723ff | 3 years ago |
Dibyendu Majumdar | cc0c098011 | 3 years ago |
Dibyendu Majumdar | f072326ea4 | 3 years ago |
Dibyendu Majumdar | 66615703a6 | 3 years ago |
Dibyendu Majumdar | ef30fb2065 | 3 years ago |
Dibyendu Majumdar | 2335973259 | 3 years ago |
Dibyendu Majumdar | fae2a2bf77 | 3 years ago |
Dibyendu Majumdar | 08c05100cf | 3 years ago |
Dibyendu Majumdar | 3b09a22e96 | 3 years ago |
Dibyendu Majumdar | 1f1d8cb428 | 3 years ago |
Dibyendu Majumdar | 9083492dcb | 3 years ago |
Dibyendu Majumdar | e6890743f0 | 3 years ago |
Dibyendu Majumdar | 9cc59144ad | 3 years ago |
Dibyendu Majumdar | f27792f050 | 3 years ago |
Dibyendu Majumdar | df748ee844 | 3 years ago |
Dibyendu Majumdar | ed90926c8d | 3 years ago |
Dibyendu Majumdar | 1fb5b08491 | 3 years ago |
Dibyendu Majumdar | facb56e0c1 | 3 years ago |
Dibyendu Majumdar | 9a86f11bc3 | 3 years ago |
Dibyendu Majumdar | 92fd0e3faf | 3 years ago |
Dibyendu Majumdar | 54fc5277d6 | 3 years ago |
Dibyendu Majumdar | c11122376e | 3 years ago |
Dibyendu Majumdar | 36639d863a | 3 years ago |
Dibyendu Majumdar | 71644f5450 | 3 years ago |
Dibyendu Majumdar | b717be20e0 | 3 years ago |
Dibyendu Majumdar | 249f22c215 | 3 years ago |
Dibyendu Majumdar | 2f76a1e869 | 3 years ago |
Dibyendu Majumdar | 4acc325c97 | 3 years ago |
Dibyendu Majumdar | ec2d27a7dc | 3 years ago |
Dibyendu Majumdar | 7320131275 | 3 years ago |
Dibyendu Majumdar | f9c4b5dbec | 3 years ago |
Dibyendu Majumdar | 0c3277ad4a | 3 years ago |
Dibyendu Majumdar | d6422fe2e3 | 3 years ago |
Dibyendu Majumdar | 66511033fd | 3 years ago |
Dibyendu Majumdar | 05f365352c | 3 years ago |
Dibyendu Majumdar | 219d44c2ba | 3 years ago |
Dibyendu Majumdar | e4a240be77 | 3 years ago |
Dibyendu Majumdar | 2ace67282d | 3 years ago |
Dibyendu Majumdar | 6909d79f61 | 3 years ago |
Dibyendu Majumdar | 16ea0643cd | 3 years ago |
Dibyendu Majumdar | a83afe2d02 | 3 years ago |
Dibyendu Majumdar | d5668379b1 | 3 years ago |
Dibyendu Majumdar | 849819e891 | 3 years ago |
Dibyendu Majumdar | 53ff35455a | 3 years ago |
Dibyendu Majumdar | f9acba8142 | 3 years ago |
Dibyendu Majumdar | 389c98ee35 | 3 years ago |
Dibyendu Majumdar | e9cb48e15c | 3 years ago |
Dibyendu Majumdar | f346122073 | 3 years ago |
Dibyendu Majumdar | 001dceb996 | 3 years ago |
Dibyendu Majumdar | 0f6a4084ae | 3 years ago |
Dibyendu Majumdar | 95ac6123a9 | 3 years ago |
Dibyendu Majumdar | 8d6e403f30 | 3 years ago |
Dibyendu Majumdar | bb218051ba | 4 years ago |
Dibyendu Majumdar | bc4142428c | 4 years ago |
Dibyendu Majumdar | 86c2020411 | 4 years ago |
Dibyendu Majumdar | 5a0c3600fc | 4 years ago |
Dibyendu Majumdar | a54f156304 | 4 years ago |
Dibyendu Majumdar | 8cec4cc827 | 4 years ago |
Dibyendu Majumdar | a82d42b847 | 4 years ago |
Dibyendu Majumdar | a3bf9dc10e | 4 years ago |
Dibyendu Majumdar | ea6c408c97 | 4 years ago |
Dibyendu Majumdar | 487624cee9 | 4 years ago |
Dibyendu Majumdar | e361bd7387 | 4 years ago |
Dibyendu Majumdar | 69840eacdb | 4 years ago |
Dibyendu Majumdar | d0b3ed989b | 4 years ago |
Dibyendu Majumdar | f6378c97b4 | 4 years ago |
Dibyendu Majumdar | 7f94078e8e | 4 years ago |
Dibyendu Majumdar | 174cfa0168 | 4 years ago |
Dibyendu Majumdar | 523f07ba57 | 4 years ago |
Dibyendu Majumdar | 71bb74f773 | 4 years ago |
Dibyendu Majumdar | 6b273f7468 | 4 years ago |
Dibyendu Majumdar | a3940b0120 | 4 years ago |
Dibyendu Majumdar | b1f36a56e1 | 4 years ago |
Dibyendu Majumdar | 6daf1a5529 | 4 years ago |
Dibyendu Majumdar | 4819f38a80 | 4 years ago |
Dibyendu Majumdar | 4f7cab694c | 4 years ago |
Dibyendu Majumdar | d65beddb75 | 4 years ago |
Dibyendu Majumdar | 45f823b604 | 4 years ago |
Dibyendu Majumdar | a45eaa8a24 | 4 years ago |
Dibyendu Majumdar | 902f5c1653 | 4 years ago |
Dibyendu Majumdar | 48617fda44 | 4 years ago |
Dibyendu Majumdar | fba87f24f1 | 4 years ago |
Dibyendu Majumdar | 90a26a4b88 | 4 years ago |
Dibyendu Majumdar | 0f698f354c | 4 years ago |
Dibyendu Majumdar | 7515ef9d89 | 4 years ago |
Dibyendu Majumdar | 2a6c5575e3 | 4 years ago |
Dibyendu Majumdar | 98c96c11eb | 4 years ago |
Dibyendu Majumdar | 2cab1f104a | 4 years ago |
Dibyendu Majumdar | be67d117c2 | 4 years ago |
Dibyendu Majumdar | 430f9a532b | 4 years ago |
Dibyendu Majumdar | e20df095df | 4 years ago |
Dibyendu Majumdar | 90f54987eb | 4 years ago |
Dibyendu Majumdar | cde0a39bc2 | 4 years ago |
Dibyendu Majumdar | 16d59f65ee | 4 years ago |
Dibyendu Majumdar | 534abc7525 | 4 years ago |
Dibyendu Majumdar | 02a7796f77 | 4 years ago |
Dibyendu Majumdar | 34c6b33a2f | 4 years ago |
Dibyendu Majumdar | 0d22f81b2a | 4 years ago |
Dibyendu Majumdar | ee056a1bd6 | 4 years ago |
Dibyendu Majumdar | 40e020916a | 4 years ago |
Dibyendu Majumdar | 57f6fc82f7 | 4 years ago |
Dibyendu Majumdar | c4535d5d9f | 4 years ago |
Dibyendu Majumdar | 940a80d9bb | 4 years ago |
Dibyendu Majumdar | 4d348e0609 | 4 years ago |
Dibyendu Majumdar | f76b4690f0 | 4 years ago |
Dibyendu Majumdar | 42cfa54e9e | 4 years ago |
Dibyendu Majumdar | 81555acc72 | 4 years ago |
Dibyendu Majumdar | 7e219f76bd | 4 years ago |
Dibyendu Majumdar | 8b854b0a02 | 4 years ago |
Dibyendu Majumdar | 920cd2dab8 | 4 years ago |
@ -0,0 +1,7 @@
|
||||
# [Choice] Debian / Ubuntu version: debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
|
||||
ARG VARIANT=buster
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/cpp:dev-${VARIANT}
|
||||
|
||||
# [Optional] Uncomment this section to install additional packages.
|
||||
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
@ -0,0 +1,12 @@
|
||||
# [Choice] Debian / Ubuntu version: debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
|
||||
ARG VARIANT=buster
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/base:${VARIANT}
|
||||
|
||||
# Install needed packages. Use a separate RUN statement to add your own dependencies.
|
||||
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
&& apt-get -y install build-essential cmake cppcheck valgrind clang lldb llvm gdb \
|
||||
&& apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# [Optional] Uncomment this section to install additional OS packages.
|
||||
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "C++",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
// Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-10, debian-9, ubuntu-20.04, ubuntu-18.04
|
||||
"args": { "VARIANT": "debian-10" }
|
||||
},
|
||||
"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined"],
|
||||
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
"terminal.integrated.shell.linux": "/bin/bash"
|
||||
},
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"ms-vscode.cpptools"
|
||||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "gcc -v",
|
||||
|
||||
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "vscode"
|
||||
}
|
@ -0,0 +1,195 @@
|
||||
Ravi Programming Language
|
||||
=========================
|
||||
|
||||
![image](https://travis-ci.org/dibyendumajumdar/ravi.svg?branch=master%0A%20:target:%20https://travis-ci.org/dibyendumajumdar/ravi)
|
||||
|
||||
Ravi is a dialect of [Lua](http://www.lua.org/) with limited optional
|
||||
static typing and features [MIR](https://github.com/vnmakarov/mir)
|
||||
powered JIT compilers. The name Ravi comes from the Sanskrit word for
|
||||
the Sun. Interestingly a precursor to Lua was
|
||||
[Sol](http://www.lua.org/history.html) which had support for static
|
||||
types; Sol means the Sun in Portugese.
|
||||
|
||||
Lua is perfect as a small embeddable dynamic language so why a
|
||||
derivative? Ravi extends Lua with static typing for improved performance
|
||||
when JIT compilation is enabled. However, the static typing is optional
|
||||
and therefore Lua programs are also valid Ravi programs.
|
||||
|
||||
There are other attempts to add static typing to Lua - e.g. [Typed
|
||||
Lua](https://github.com/andremm/typedlua) but these efforts are mostly
|
||||
about adding static type checks in the language while leaving the VM
|
||||
unmodified. The Typed Lua effort is very similar to the approach taken
|
||||
by Typescript in the JavaScript world. The static typing is to aid
|
||||
programming in the large - the code is eventually translated to standard
|
||||
Lua and executed in the unmodified Lua VM.
|
||||
|
||||
My motivation is somewhat different - I want to enhance the VM to
|
||||
support more efficient operations when types are known. Type information
|
||||
can be exploited by JIT compilation technology to improve performance.
|
||||
At the same time, I want to keep the language safe and therefore usable
|
||||
by non-expert programmers.
|
||||
|
||||
Of course there is the fantastic [LuaJIT](http://luajit.org)
|
||||
implementation. Ravi has a different goal compared to LuaJIT. Ravi
|
||||
prioritizes ease of maintenance and support, language safety, and
|
||||
compatibility with Lua 5.3, over maximum performance. For more detailed
|
||||
comparison please refer to the documentation links below.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- Optional static typing - for details [see the reference
|
||||
manual](https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-reference.html).
|
||||
- Type specific bytecodes to improve performance
|
||||
- Compatibility with Lua 5.3 (see Compatibility section below)
|
||||
- Generational GC from Lua 5.4
|
||||
- `defer` statement for releasing resources
|
||||
- Compact JIT backend [MIR](https://github.com/vnmakarov/mir).
|
||||
- A [distribution with
|
||||
batteries](https://github.com/dibyendumajumdar/Suravi).
|
||||
- A [Visual Studio Code debugger
|
||||
extension](https://marketplace.visualstudio.com/items?itemName=ravilang.ravi-debug)
|
||||
- interpreted mode debugger.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
- For the Lua extensions in Ravi see the [Reference
|
||||
Manual](https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-reference.html).
|
||||
- [MIR JIT Build
|
||||
instructions](https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-mir-instructions.html).
|
||||
- Also see [Ravi
|
||||
Documentation](http://the-ravi-programming-language.readthedocs.org/en/latest/index.html).
|
||||
- and the slides I presented at the [Lua 2015
|
||||
Workshop](http://www.lua.org/wshop15.html).
|
||||
|
||||
Lua Goodies
|
||||
-----------
|
||||
|
||||
- [An Introduction to
|
||||
Lua](http://the-ravi-programming-language.readthedocs.io/en/latest/lua-introduction.html)
|
||||
attempts to provide a quick overview of Lua for folks coming from
|
||||
other languages.
|
||||
- [Lua 5.3 Bytecode
|
||||
Reference](http://the-ravi-programming-language.readthedocs.io/en/latest/lua_bytecode_reference.html)
|
||||
is my attempt to bring up to date the [Lua 5.1 Bytecode
|
||||
Reference](http://luaforge.net/docman/83/98/ANoFrillsIntroToLua51VMInstructions.pdf).
|
||||
- A [patch for Lua
|
||||
5.3](https://github.com/dibyendumajumdar/ravi/blob/master/patches/defer_statement_for_Lua_5_3.patch)
|
||||
implements the 'defer' statement.
|
||||
- A [patch for Lua
|
||||
5.4.[0-2]](https://github.com/dibyendumajumdar/ravi/blob/master/patches/defer_statement_for_Lua_5_4.patch)
|
||||
implements the 'defer' statement.
|
||||
- Updated [patch for Lua
|
||||
5.4.3](https://github.com/dibyendumajumdar/ravi/blob/master/patches/defer_statement_patch_for_Lua_5_4_3.patch)
|
||||
implements the 'defer' statement.
|
||||
|
||||
Lua 5.4 Position Statement
|
||||
--------------------------
|
||||
|
||||
Lua 5.4 relationship to Ravi is as follows:
|
||||
|
||||
- Generational GC - back-ported to Ravi.
|
||||
- New random number generator - back-ported to Ravi.
|
||||
- Multiple user values can be associated with userdata - under
|
||||
consideration.
|
||||
- `<const>` variables - not planned.
|
||||
- `<close>` variables - Ravi has `'defer'` statement which is the
|
||||
better option in my opinion, hence no plans to support `<close>`
|
||||
variables.
|
||||
- Interpreter performance improvements - these are beneficial to Lua
|
||||
interpreter but not to the JIT backends, hence not much point in
|
||||
back-porting.
|
||||
- Table implementation changes - under consideration.
|
||||
- String to number coercion is now part of string library metamethods
|
||||
- back-ported to Ravi.
|
||||
- utf8 library accepts codepoints up to 2\^31 - back-ported to Ravi.
|
||||
- Removal of compatibility layers for 5.1, and 5.2 - not implemented
|
||||
as Ravi continues to provide these layers as per Lua 5.3.
|
||||
|
||||
Compatibility with Lua 5.3
|
||||
--------------------------
|
||||
|
||||
Ravi should be able to run all Lua 5.3 programs in interpreted mode, but
|
||||
following should be noted:
|
||||
|
||||
- Ravi supports optional typing and enhanced types such as arrays (see
|
||||
the documentation). Programs using these features cannot be run by
|
||||
standard Lua. However all types in Ravi can be passed to Lua
|
||||
functions; operations on Ravi arrays within Lua code will be subject
|
||||
to restrictions as described in the section above on arrays.
|
||||
- Values crossing from Lua to Ravi will be subjected to typechecks
|
||||
should these values be assigned to typed variables.
|
||||
- Upvalues cannot subvert the static typing of local variables (issue
|
||||
\#26) when types are annotated.
|
||||
- Certain Lua limits are reduced due to changed byte code structure.
|
||||
These are described below.
|
||||
- Ravi uses an extended bytecode which means it is not compatible with
|
||||
Lua 5.x bytecode.
|
||||
- Ravi incorporates the new Generational GC from Lua 5.4, hence the GC
|
||||
interface has changed.
|
||||
|
||||
Limit name Lua value Ravi value
|
||||
------------------ -------------- --------------
|
||||
MAXUPVAL 255 125
|
||||
LUAI\_MAXCCALLS 200 125
|
||||
MAXREGS 255 125
|
||||
MAXVARS 200 125
|
||||
MAXARGLINE 250 120
|
||||
|
||||
When JIT compilation is enabled there are following additional
|
||||
constraints:
|
||||
|
||||
- Ravi will only execute JITed code from the main Lua thread; any
|
||||
secondary threads (coroutines) execute in interpreter mode.
|
||||
- In JITed code tailcalls are implemented as regular calls so unlike
|
||||
the interpreter VM which supports infinite tail recursion JIT
|
||||
compiled code only supports tail recursion to a depth of about 110
|
||||
(issue \#17)
|
||||
- Debug api and hooks are not supported in JIT mode
|
||||
|
||||
History
|
||||
-------
|
||||
|
||||
- 2015
|
||||
: - Implemented JIT compilation using LLVM
|
||||
- Implemented [libgccjit based alternative
|
||||
JIT](https://github.com/dibyendumajumdar/ravi/tree/gccjit-ravi534)
|
||||
(now discontinued)
|
||||
|
||||
- 2016
|
||||
: - Implemented debugger for Ravi and Lua 5.3 for [Visual Studio
|
||||
Code](https://github.com/dibyendumajumdar/ravi/tree/master/vscode-debugger)
|
||||
|
||||
- 2017
|
||||
: - Embedded C compiler using dmrC project (C JIT compiler) (now
|
||||
discontinued)
|
||||
- Additional type-annotations
|
||||
|
||||
- 2018
|
||||
: - Implemented [Eclipse OMR JIT
|
||||
backend](https://github.com/dibyendumajumdar/ravi/tree/omrjit)
|
||||
(now discontinued)
|
||||
- Created [Ravi with
|
||||
batteries](https://github.com/dibyendumajumdar/Suravi).
|
||||
|
||||
- 2019
|
||||
: - New language feature - defer statement
|
||||
- New JIT backend [MIR](https://github.com/vnmakarov/mir).
|
||||
|
||||
- 2020
|
||||
: - [New parser / type checker /
|
||||
compiler](https://github.com/dibyendumajumdar/ravi-compiler)
|
||||
- Generational GC back-ported from Lua 5.4
|
||||
- Support for [LLVM
|
||||
backend](https://github.com/dibyendumajumdar/ravi/tree/llvm)
|
||||
archived
|
||||
|
||||
- 2021 (Plan)
|
||||
: - Integrated AOT and JIT compilation support
|
||||
- Ravi 1.0 release
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
MIT License
|
@ -1,125 +0,0 @@
|
||||
=========================
|
||||
Ravi Programming Language
|
||||
=========================
|
||||
.. image:: https://travis-ci.org/dibyendumajumdar/ravi.svg?branch=master
|
||||
:target: https://travis-ci.org/dibyendumajumdar/ravi
|
||||
|
||||
Ravi is a derivative/dialect of `Lua 5.3 <http://www.lua.org/>`_ with limited optional static typing and
|
||||
features `MIR <https://github.com/vnmakarov/mir>`_ and `LLVM <http://www.llvm.org/>`_ powered JIT compilers.
|
||||
The name Ravi comes from the Sanskrit word for the Sun.
|
||||
Interestingly a precursor to Lua was `Sol <http://www.lua.org/history.html>`_ which had support for
|
||||
static types; Sol means the Sun in Portugese.
|
||||
|
||||
Lua is perfect as a small embeddable dynamic language so why a derivative? Ravi extends Lua with
|
||||
static typing for improved performance when JIT compilation is enabled. However, the static typing is
|
||||
optional and therefore Lua programs are also valid Ravi programs.
|
||||
|
||||
There are other attempts to add static typing to Lua - e.g. `Typed Lua <https://github.com/andremm/typedlua>`_ but
|
||||
these efforts are mostly about adding static type checks in the language while leaving the VM unmodified.
|
||||
The Typed Lua effort is very similar to the approach taken by Typescript in the JavaScript world.
|
||||
The static typing is to aid programming in the large - the code is eventually translated to standard Lua
|
||||
and executed in the unmodified Lua VM.
|
||||
|
||||
My motivation is somewhat different - I want to enhance the VM to support more efficient operations when types are
|
||||
known. Type information can be exploited by JIT compilation technology to improve performance. At the same time,
|
||||
I want to keep the language safe and therefore usable by non-expert programmers.
|
||||
|
||||
Of course there is the fantastic `LuaJIT <http://luajit.org>`_ implementation. Ravi has a different goal compared to
|
||||
LuaJIT. Ravi prioritizes ease of maintenance and support, language safety, and compatibility with Lua 5.3,
|
||||
over maximum performance. For more detailed comparison please refer to the documentation links below.
|
||||
|
||||
Features
|
||||
========
|
||||
* Optional static typing - for details `see the reference manual <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-reference.html>`_.
|
||||
* Type specific bytecodes to improve performance
|
||||
* Compatibility with Lua 5.3 (see Compatibility section below)
|
||||
* Generational GC from Lua 5.4
|
||||
* ``defer`` statement for releasing resources
|
||||
* Compact JIT backend `MIR <https://github.com/vnmakarov/mir>`_; only Linux and x86-64 supported for now.
|
||||
* `LLVM <http://www.llvm.org/>`_ supported as alternative JIT backend.
|
||||
* A `distribution with batteries <https://github.com/dibyendumajumdar/Suravi>`_.
|
||||
|
||||
Documentation
|
||||
=============
|
||||
* For the Lua extensions in Ravi see the `Reference Manual <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-reference.html>`_.
|
||||
* `MIR JIT Build instructions <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-mir-instructions.html>`_.
|
||||
* `LLVM JIT Build instructions <https://the-ravi-programming-language.readthedocs.io/en/latest/ravi-llvm-instructions.html>`_.
|
||||
* Also see `Ravi Documentation <http://the-ravi-programming-language.readthedocs.org/en/latest/index.html>`_.
|
||||
* and the slides I presented at the `Lua 2015 Workshop <http://www.lua.org/wshop15.html>`_.
|
||||
|
||||
Lua Goodies
|
||||
===========
|
||||
* `An Introduction to Lua <http://the-ravi-programming-language.readthedocs.io/en/latest/lua-introduction.html>`_ attempts to provide a quick overview of Lua for folks coming from other languages.
|
||||
* `Lua 5.3 Bytecode Reference <http://the-ravi-programming-language.readthedocs.io/en/latest/lua_bytecode_reference.html>`_ is my attempt to bring up to date the `Lua 5.1 Bytecode Reference <http://luaforge.net/docman/83/98/ANoFrillsIntroToLua51VMInstructions.pdf>`_.
|
||||
* A `patch for Lua 5.3 <http://lua-users.org/lists/lua-l/2020-01/msg00004.html>`_ implements the 'defer' statement.
|
||||
|
||||
Lua 5.4 Position Statement
|
||||
==========================
|
||||
Lua 5.4 relationship to Ravi is as follows:
|
||||
|
||||
* Generational GC - back-ported to Ravi.
|
||||
* New random number generator - back-ported to Ravi.
|
||||
* Multiple user values can be associated with userdata - under consideration.
|
||||
* ``<const>`` variables - not planned.
|
||||
* ``<close>`` variables - Ravi has ``'defer'`` statement which is better option in my opinion, hence no plans to support ``<close>`` variables.
|
||||
* Interpreter performance improvements - these are beneficial to Lua interpreter but not to the JIT backends, hence not much point in back-porting.
|
||||
* Table implementation changes - under consideration.
|
||||
* String to number coercion is now part of string library metamethods - back-ported to Ravi.
|
||||
* utf8 library accepts codepoints up to 2^31 - back-ported to Ravi.
|
||||
* Removal of compatibility layers for 5.1, and 5.2 - not implemented as Ravi continues to provide these layers as per Lua 5.3.
|
||||
|
||||
Compatibility with Lua 5.3
|
||||
==========================
|
||||
Ravi should be able to run all Lua 5.3 programs in interpreted mode, but following should be noted:
|
||||
|
||||
* Ravi supports optional typing and enhanced types such as arrays (described above). Programs using these features cannot be run by standard Lua. However all types in Ravi can be passed to Lua functions; operations on Ravi arrays within Lua code will be subject to restrictions as described in the section above on arrays.
|
||||
* Values crossing from Lua to Ravi will be subjected to typechecks should these values be assigned to typed variables.
|
||||
* Upvalues cannot subvert the static typing of local variables (issue #26) when types are annotated.
|
||||
* Certain Lua limits are reduced due to changed byte code structure. These are described below.
|
||||
* Ravi uses an extended bytecode which means it is not compatible with Lua 5.3 bytecode.
|
||||
* Ravi incorporates the new Generational GC from Lua 5.4, hence the GC interface has changed.
|
||||
|
||||
+-----------------+-------------+-------------+
|
||||
| Limit name | Lua value | Ravi value |
|
||||
+=================+=============+=============+
|
||||
| MAXUPVAL | 255 | 125 |
|
||||
+-----------------+-------------+-------------+
|
||||
| LUAI_MAXCCALLS | 200 | 125 |
|
||||
+-----------------+-------------+-------------+
|
||||
| MAXREGS | 255 | 125 |
|
||||
+-----------------+-------------+-------------+
|
||||
| MAXVARS | 200 | 125 |
|
||||
+-----------------+-------------+-------------+
|
||||
| MAXARGLINE | 250 | 120 |
|
||||
+-----------------+-------------+-------------+
|
||||
|
||||
When JIT compilation is enabled there are following additional constraints:
|
||||
|
||||
* Ravi will only execute JITed code from the main Lua thread; any secondary threads (coroutines) execute in interpreter mode.
|
||||
* In JITed code tailcalls are implemented as regular calls so unlike the interpreter VM which supports infinite tail recursion JIT compiled code only supports tail recursion to a depth of about 110 (issue #17)
|
||||
|
||||
History
|
||||
=======
|
||||
* 2015
|
||||
- Implemented JIT compilation using LLVM
|
||||
- Implemented libgccjit based alternative JIT (now discontinued)
|
||||
* 2016
|
||||
- Implemented debugger for Ravi and Lua 5.3 for `Visual Studio Code <https://github.com/dibyendumajumdar/ravi/tree/master/vscode-debugger>`_
|
||||
* 2017
|
||||
- Embedded C compiler using dmrC project (C JIT compiler) (now discontinued)
|
||||
- Additional type-annotations
|
||||
* 2018
|
||||
- Implemented Eclipse OMR JIT backend (now discontinued)
|
||||
- Created `Ravi with batteries <https://github.com/dibyendumajumdar/Suravi>`_.
|
||||
* 2019
|
||||
- New language feature - `defer` statement
|
||||
- New JIT backend `MIR <https://github.com/vnmakarov/mir>`_.
|
||||
|
||||
* 2020 (Plan)
|
||||
- `New optimizing byte code generator based on new parser / type checker <https://github.com/dibyendumajumdar/ravi-compiler>`_
|
||||
- Generational GC back-ported from Lua 5.4
|
||||
- Ravi 1.0 release
|
||||
|
||||
License
|
||||
=======
|
||||
MIT License
|
@ -1,16 +0,0 @@
|
||||
# Run this on LLVM 10 source dir
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
cmake3 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/Software/llvm10 \
|
||||
-DLLVM_TARGETS_TO_BUILD="X86" \
|
||||
-DLLVM_BUILD_TOOLS=OFF \
|
||||
-DLLVM_INCLUDE_TOOLS=OFF \
|
||||
-DLLVM_BUILD_EXAMPLES=OFF \
|
||||
-DLLVM_INCLUDE_EXAMPLES=OFF \
|
||||
-DLLVM_BUILD_TESTS=OFF \
|
||||
-DLLVM_INCLUDE_TESTS=OFF \
|
||||
-DLLVM_OPTIMIZED_TABLEGEN=ON \
|
||||
..
|
||||
make install
|
@ -1,5 +0,0 @@
|
||||
mkdir llvm32
|
||||
cd llvm32
|
||||
rem cmake -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM37_32\share\llvm\cmake -DBUILD_STATIC=OFF ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM39_32\lib\cmake\llvm -DSTATIC_BUILD=OFF ..
|
||||
cd ..
|
@ -1,5 +0,0 @@
|
||||
mkdir llvm32
|
||||
cd llvm32
|
||||
rem cmake -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM37_32\share\llvm\cmake ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM39\lib\cmake\llvm -DSTATIC_BUILD=ON ..
|
||||
cd ..
|
@ -1,5 +0,0 @@
|
||||
mkdir llvm32d
|
||||
cd llvm32d
|
||||
rem cmake -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM37_32\share\llvm\cmake ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=\d\ravi32 -G "Visual Studio 14" -DLLVM_JIT=ON -DLLVM_DIR=\d\LLVM39D_32\lib\cmake\llvm -DSTATIC_BUILD=ON ..
|
||||
cd ..
|
@ -1,6 +0,0 @@
|
||||
mkdir llvm64d
|
||||
cd llvm64d
|
||||
rem cmake -DCMAKE_INSTALL_PREFIX=c:\ravi64llvmd -G "Visual Studio 14 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\LLVM37debug\share\llvm\cmake ..
|
||||
rem cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=c:\d\ravi64llvmd -G "Visual Studio 15 2017 Win64" -DLLVM_JIT=ON -DEMBEDDED_DMRC=ON -DLLVM_DIR=c:\d\LLVM39D64\lib\cmake\llvm ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm501d\lib\cmake\llvm ..
|
||||
cd ..
|
@ -1,7 +0,0 @@
|
||||
mkdir llvm64
|
||||
cd llvm64
|
||||
rem pre LLVM 3.9
|
||||
rem cmake -DCMAKE_INSTALL_PREFIX=c:\ravi -G "Visual Studio 14 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\LLVM37\share\llvm\cmake ..
|
||||
rem cmake -DCMAKE_INSTALL_PREFIX=c:\ravi -G "Visual Studio 15 2017 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\d\LLVM40_64\lib\cmake\llvm ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DSTATIC_BUILD=ON -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm601r\lib\cmake\llvm ..
|
||||
cd ..
|
@ -1,5 +0,0 @@
|
||||
rmdir /s llvm8
|
||||
mkdir llvm8
|
||||
cd llvm8
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm801\lib\cmake\llvm ..
|
||||
cd ..
|
@ -1,5 +0,0 @@
|
||||
rmdir /s llvm10d
|
||||
mkdir llvm10d
|
||||
cd llvm10d
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 16 2019" -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm10d\lib\cmake\llvm ..
|
||||
cd ..
|
@ -1,6 +0,0 @@
|
||||
rmdir /s llvm9r
|
||||
mkdir llvm9r
|
||||
cd llvm9r
|
||||
rem cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm900r\lib\cmake\llvm ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 16 2019" -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm900r\lib\cmake\llvm ..
|
||||
cd ..
|
@ -1,4 +0,0 @@
|
||||
mkdir omrjit
|
||||
cd omrjit
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Debug -DOMR_JIT=ON ..
|
||||
cd ..
|
@ -1,4 +0,0 @@
|
||||
mkdir xcodellvm
|
||||
cd xcodellvm
|
||||
#cmake -DCMAKE_BUILD_TYPE=Debug -G Xcode -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -G Xcode -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..
|
@ -1,5 +0,0 @@
|
||||
mkdir buildllvmd
|
||||
cd buildllvmd
|
||||
#cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
|
||||
#cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DLTESTS=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DLTESTS=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravillvm -DLLVM_DIR=$HOME/Software/llvm600/lib/cmake/llvm ..
|
@ -1,7 +0,0 @@
|
||||
rm -rf buildllvm
|
||||
mkdir buildllvm
|
||||
cd buildllvm
|
||||
#cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
|
||||
#cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..
|
||||
#cmake -DCMAKE_BUILD_TYPE=Release -DSTATIC_BUILD=ON -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/Software/ravi -DLLVM_DIR=$HOME/Software/llvm801/lib/cmake/llvm ..
|
||||
cmake3 -DCMAKE_BUILD_TYPE=Release -DSTATIC_BUILD=ON -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/Software/ravi -DLLVM_DIR=$HOME/Software/llvm10/lib/cmake/llvm ..
|
@ -1,3 +0,0 @@
|
||||
mkdir omrjit
|
||||
cd omrjit
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DOMR_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi ..
|
@ -1,121 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* 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.
|
||||
******************************************************************************/
|
||||
#ifndef RAVI_LLVM_H
|
||||
#define RAVI_LLVM_H
|
||||
|
||||
#ifdef USE_LLVM
|
||||
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
|
||||
#if (LLVM_VERSION_MAJOR < 3 || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5 || LLVM_VERSION_MAJOR == 7)
|
||||
#error Unsupported LLVM version
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 5
|
||||
#define USE_ORC_JIT 1
|
||||
#else
|
||||
#define USE_ORC_JIT 0
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 8 && !defined(_WIN32)
|
||||
#define USE_ORCv2_JIT 0
|
||||
#else
|
||||
#define USE_ORCv2_JIT 0
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 10
|
||||
#undef USE_ORCv2_JIT
|
||||
#define USE_ORCv2_JIT 1
|
||||
#endif
|
||||
|
||||
// In lua.c we include this just to get version numbers
|
||||
// We cannot have C++ headers in that case
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/ExecutionEngine/ExecutionEngine.h"
|
||||
#include "llvm/ExecutionEngine/MCJIT.h"
|
||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/MDBuilder.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7
|
||||
#include "llvm/PassManager.h"
|
||||
#else
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#endif
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/DynamicLibrary.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
|
||||
|
||||
#if USE_ORC_JIT || USE_ORCv2_JIT
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
|
||||
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
|
||||
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
|
||||
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
|
||||
#include "llvm/ExecutionEngine/Orc/IRTransformLayer.h"
|
||||
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
|
||||
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
|
||||
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
|
||||
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
|
||||
#include "llvm/IR/Mangler.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Transforms/Scalar/GVN.h"
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 8
|
||||
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
|
||||
#include "llvm/ExecutionEngine/Orc/Legacy.h"
|
||||
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
#endif //__cplusplus
|
||||
|
||||
#endif //USE_LLVM
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,98 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2018-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
aarch64 call ABI target specific code.
|
||||
*/
|
||||
|
||||
typedef int target_arg_info_t;
|
||||
|
||||
static void target_init_arg_vars (c2m_ctx_t c2m_ctx, target_arg_info_t *arg_info) {}
|
||||
|
||||
static int target_return_by_addr_p (c2m_ctx_t c2m_ctx, struct type *ret_type) {
|
||||
return ((ret_type->mode == TM_STRUCT || ret_type->mode == TM_UNION)
|
||||
&& type_size (c2m_ctx, ret_type) > 2 * 8);
|
||||
}
|
||||
|
||||
static int reg_aggregate_size (c2m_ctx_t c2m_ctx, struct type *type) {
|
||||
int size;
|
||||
|
||||
if (type->mode != TM_STRUCT && type->mode != TM_UNION) return -1;
|
||||
return (size = type_size (c2m_ctx, type)) <= 2 * 8 ? size : -1;
|
||||
}
|
||||
|
||||
static void target_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type,
|
||||
target_arg_info_t *arg_info, VARR (MIR_type_t) * res_types,
|
||||
VARR (MIR_var_t) * arg_vars) {
|
||||
MIR_var_t var;
|
||||
int size;
|
||||
|
||||
if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0) {
|
||||
simple_add_res_proto (c2m_ctx, ret_type, arg_info, res_types, arg_vars);
|
||||
return;
|
||||
}
|
||||
if (size == 0) return;
|
||||
VARR_PUSH (MIR_type_t, res_types, MIR_T_I64);
|
||||
if (size > 8) VARR_PUSH (MIR_type_t, res_types, MIR_T_I64);
|
||||
}
|
||||
|
||||
static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type,
|
||||
target_arg_info_t *arg_info, size_t call_arg_area_offset) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
int size;
|
||||
|
||||
if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0)
|
||||
return simple_add_call_res_op (c2m_ctx, ret_type, arg_info, call_arg_area_offset);
|
||||
if (size == 0) return -1;
|
||||
VARR_PUSH (MIR_op_t, call_ops,
|
||||
MIR_new_reg_op (ctx, get_new_temp (c2m_ctx, MIR_T_I64).mir_op.u.reg));
|
||||
if (size > 8)
|
||||
VARR_PUSH (MIR_op_t, call_ops,
|
||||
MIR_new_reg_op (ctx, get_new_temp (c2m_ctx, MIR_T_I64).mir_op.u.reg));
|
||||
return size <= 8 ? 1 : 2;
|
||||
}
|
||||
|
||||
static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res,
|
||||
MIR_insn_t call, size_t call_ops_start) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
int size;
|
||||
|
||||
if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0)
|
||||
return simple_gen_post_call_res_code (c2m_ctx, ret_type, res, call, call_ops_start);
|
||||
if (size != 0)
|
||||
gen_multiple_load_store (c2m_ctx, ret_type, &VARR_ADDR (MIR_op_t, call_ops)[call_ops_start + 2],
|
||||
res.mir_op, FALSE);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
int i, size;
|
||||
|
||||
if ((size = reg_aggregate_size (c2m_ctx, ret_type)) < 0) {
|
||||
simple_add_ret_ops (c2m_ctx, ret_type, res);
|
||||
return;
|
||||
}
|
||||
assert (res.mir_op.mode == MIR_OP_MEM && VARR_LENGTH (MIR_op_t, ret_ops) == 0 && size <= 2 * 8);
|
||||
for (i = 0; size > 0; size -= 8, i++)
|
||||
VARR_PUSH (MIR_op_t, ret_ops, get_new_temp (c2m_ctx, MIR_T_I64).mir_op);
|
||||
gen_multiple_load_store (c2m_ctx, ret_type, VARR_ADDR (MIR_op_t, ret_ops), res.mir_op, TRUE);
|
||||
}
|
||||
|
||||
static MIR_type_t target_get_blk_type (c2m_ctx_t c2m_ctx, struct type *arg_type) {
|
||||
return MIR_T_BLK; /* one BLK is enough */
|
||||
}
|
||||
|
||||
static void target_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type,
|
||||
target_arg_info_t *arg_info, VARR (MIR_var_t) * arg_vars) {
|
||||
simple_add_arg_proto (c2m_ctx, name, arg_type, arg_info, arg_vars);
|
||||
}
|
||||
|
||||
static void target_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type,
|
||||
target_arg_info_t *arg_info, op_t arg) {
|
||||
simple_add_call_arg_op (c2m_ctx, arg_type, arg_info, arg);
|
||||
}
|
||||
|
||||
static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type,
|
||||
decl_t param_decl, target_arg_info_t *arg_info) {
|
||||
return FALSE;
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 5.2.4.2.2 */
|
||||
static char float_str[]
|
||||
= "#ifndef __FLOAT_H\n"
|
||||
"#define __FLOAT_H\n"
|
||||
"\n"
|
||||
"#define FLT_RADIX 2\n"
|
||||
"\n"
|
||||
"#define FLT_MANT_DIG 24\n"
|
||||
"#define DBL_MANT_DIG 53\n"
|
||||
"#define LDBL_MANT_DIG DBL_MANT_DIG\n"
|
||||
"\n"
|
||||
"#define FLT_DECIMAL_DIG 9\n"
|
||||
"#define DBL_DECIMAL_DIG 17\n"
|
||||
"#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG\n"
|
||||
"#define FLT_DIG FLT_DECIMAL_DIG\n"
|
||||
"#define DBL_DIG DBL_DECIMAL_DIG\n"
|
||||
"#define LDBL_DIG LDBL_DECIMAL_DIG\n"
|
||||
"\n"
|
||||
"#define DECIMAL_DIG LDBL_DECIMAL_DIG\n"
|
||||
"\n"
|
||||
"#define FLT_MIN_EXP -125\n"
|
||||
"#define DBL_MIN_EXP -1021\n"
|
||||
"#define LDBL_MIN_EXP DBL_MIN_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MIN_10_EXP -37\n"
|
||||
"#define DBL_MIN_10_EXP -307\n"
|
||||
"#define LDBL_MIN_10_EXP DBL_MIN_10_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX_EXP 128\n"
|
||||
"#define DBL_MAX_EXP 1024\n"
|
||||
"#define LDBL_MAX_EXP DBL_MAX_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX_10_EXP 38\n"
|
||||
"#define DBL_MAX_10_EXP 308\n"
|
||||
"#define LDBL_MAX_10_EXP DBL_MAX_10_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX 0x1.fffffep+127\n"
|
||||
"#define DBL_MAX 0x1.fffffffffffffp+1023\n"
|
||||
"#define LDBL_MAX DBL_MAX\n"
|
||||
"\n"
|
||||
"#define FLT_EPSILON 0x1p-23\n"
|
||||
"#define DBL_EPSILON 0x1p-52\n"
|
||||
"#define LDBL_EPSILON DBL_EPSILON\n"
|
||||
"\n"
|
||||
"#define FLT_MIN 0x1p-126\n"
|
||||
"#define DBL_MIN 0x1p-1022\n"
|
||||
"#define LDBL_MIN DBL_MIN\n"
|
||||
"\n"
|
||||
"#define FLT_TRUE_MIN 0x1p-149\n"
|
||||
"#define DBL_TRUE_MIN 0x0.0000000000001p-1022\n"
|
||||
"#define LDBL_TRUE_MIN DBL_TRUE_MIN\n"
|
||||
"\n"
|
||||
"#define FLT_EVAL_METHOD 0\n"
|
||||
"#define FLT_ROUNDS 1 /* round to the nearest */\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __FLOAT_H */\n";
|
@ -0,0 +1,38 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See 5.2.4.2 */
|
||||
static char limits_str[]
|
||||
= "#ifndef __LIMITS_H\n"
|
||||
"#define __LIMITS_H\n"
|
||||
"\n"
|
||||
"#define CHAR_BIT 8\n"
|
||||
"\n"
|
||||
"#define SCHAR_MIN (-SCHAR_MAX - 1)\n"
|
||||
"#define SCHAR_MAX 127\n"
|
||||
"#define UCHAR_MAX (SCHAR_MAX * 2 + 1)\n"
|
||||
"\n"
|
||||
"#define MB_LEN_MAX 1\n"
|
||||
"\n"
|
||||
"#define SHRT_MIN (-SHRT_MAX - 1)\n"
|
||||
"#define SHRT_MAX 32767\n"
|
||||
"#define USHRT_MAX (SHRT_MAX * 2 + 1)\n"
|
||||
"\n"
|
||||
"#define INT_MIN (-INT_MAX - 1)\n"
|
||||
"#define INT_MAX 2147483647\n"
|
||||
"#define UINT_MAX (INT_MAX * 2u + 1u)\n"
|
||||
"\n"
|
||||
"#define LONG_MIN (-LONG_MAX - 1l)\n"
|
||||
"#define LONG_MAX 9223372036854775807l\n"
|
||||
"#define ULONG_MAX (LONG_MAX * 2ul + 1ul)\n"
|
||||
"\n"
|
||||
"#define LLONG_MIN LONG_MIN\n"
|
||||
"#define LLONG_MAX LONG_MAX\n"
|
||||
"#define ULLONG_MAX ULONG_MAX\n"
|
||||
"\n"
|
||||
"/* signed char by default */\n"
|
||||
"#define CHAR_MIN SCHAR_MIN\n"
|
||||
"#define CHAR_MAX SCHAR_MAX\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __LIMITS_H */\n";
|
@ -1,5 +1,5 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
static char aarch64_mirc[]
|
@ -0,0 +1,27 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
static char stdarg_str[]
|
||||
= "#ifndef __STDARG_H\n"
|
||||
"#define __STDARG_H\n"
|
||||
"\n"
|
||||
"typedef struct {\n"
|
||||
" void *__stack;\n"
|
||||
" void *__gr_top;\n"
|
||||
" void *__vr_top;\n"
|
||||
" int __gr_offs;\n"
|
||||
" int __vr_offs;\n"
|
||||
"} va_list;\n"
|
||||
"\n"
|
||||
"#define va_start(ap, param) __builtin_va_start (ap)\n"
|
||||
"#define va_arg(ap, type) __builtin_va_arg(ap, (type *) 0)\n"
|
||||
"#define va_end(ap) 0\n"
|
||||
"#define va_copy(dest, src) ((dest)[0] = (src)[0])\n"
|
||||
"\n"
|
||||
"/* For standard headers of a GNU system: */\n"
|
||||
"#ifndef __GNUC_VA_LIST\n"
|
||||
"#define __GNUC_VA_LIST 1\n"
|
||||
"#endif\n"
|
||||
"typedef va_list __gnuc_va_list;\n"
|
||||
"#endif /* #ifndef __STDARG_H */\n";
|
@ -0,0 +1,19 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.19 */
|
||||
static char stddef_str[]
|
||||
= "#ifndef __STDDEF_H\n"
|
||||
"#define __STDDEF_H\n"
|
||||
"\n"
|
||||
"typedef long ptrdiff_t;\n"
|
||||
"typedef unsigned long size_t;\n"
|
||||
"typedef long double max_align_t;\n"
|
||||
"typedef unsigned int wchar_t;\n"
|
||||
"\n"
|
||||
"#define NULL ((void *) 0)\n"
|
||||
"\n"
|
||||
"#define offsetof(type, member_designator) ((size_t) & ((type *) 0)->member_designator)\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __STDDEF_H */\n";
|
@ -0,0 +1,130 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.20 */
|
||||
static char stdint_str[]
|
||||
= "#ifndef _STDINT_H\n"
|
||||
"#define _STDINT_H 1\n"
|
||||
"\n"
|
||||
"#ifndef __int8_t_defined\n"
|
||||
"#define __int8_t_defined\n"
|
||||
"typedef signed char int8_t;\n"
|
||||
"#endif\n"
|
||||
"typedef short int int16_t;\n"
|
||||
"typedef int int32_t;\n"
|
||||
"typedef long int int64_t;\n"
|
||||
"\n"
|
||||
"typedef unsigned char uint8_t;\n"
|
||||
"typedef unsigned short int uint16_t;\n"
|
||||
"typedef unsigned int uint32_t;\n"
|
||||
"typedef unsigned long int uint64_t;\n"
|
||||
"\n"
|
||||
"typedef signed char int_least8_t;\n"
|
||||
"typedef short int int_least16_t;\n"
|
||||
"typedef int int_least32_t;\n"
|
||||
"typedef long int int_least64_t;\n"
|
||||
"\n"
|
||||
"typedef unsigned char uint_least8_t;\n"
|
||||
"typedef unsigned short int uint_least16_t;\n"
|
||||
"typedef unsigned int uint_least32_t;\n"
|
||||
"typedef unsigned long int uint_least64_t;\n"
|
||||
"\n"
|
||||
"typedef signed char int_fast8_t;\n"
|
||||
"typedef long int int_fast16_t;\n"
|
||||
"typedef long int int_fast32_t;\n"
|
||||
"typedef long int int_fast64_t;\n"
|
||||
"\n"
|
||||
"typedef unsigned char uint_fast8_t;\n"
|
||||
"typedef unsigned long int uint_fast16_t;\n"
|
||||
"typedef unsigned long int uint_fast32_t;\n"
|
||||
"typedef unsigned long int uint_fast64_t;\n"
|
||||
"\n"
|
||||
"#define __intptr_t_defined\n"
|
||||
"typedef long int intptr_t;\n"
|
||||
"typedef unsigned long int uintptr_t;\n"
|
||||
"\n"
|
||||
"typedef long int intmax_t;\n"
|
||||
"typedef unsigned long int uintmax_t;\n"
|
||||
"\n"
|
||||
"#define __INT64_C(c) c##L\n"
|
||||
"#define __UINT64_C(c) c##UL\n"
|
||||
"\n"
|
||||
"#define INT8_MIN (-128)\n"
|
||||
"#define INT16_MIN (-32768)\n"
|
||||
"#define INT32_MIN (-2147483648)\n"
|
||||
"#define INT64_MIN (-9223372036854775808l)\n"
|
||||
"\n"
|
||||
"#define INT8_MAX (127)\n"
|
||||
"#define INT16_MAX (32767)\n"
|
||||
"#define INT32_MAX (2147483647)\n"
|
||||
"#define INT64_MAX (9223372036854775807l)\n"
|
||||
"\n"
|
||||
"#define UINT8_MAX (255)\n"
|
||||
"#define UINT16_MAX (65535)\n"
|
||||
"#define UINT32_MAX (4294967295u)\n"
|
||||
"#define UINT64_MAX (18446744073709551615ul)\n"
|
||||
"\n"
|
||||
"#define INT_LEAST8_MIN (-128)\n"
|
||||
"#define INT_LEAST16_MIN (-32768)\n"
|
||||
"#define INT_LEAST32_MIN (-2147483648)\n"
|
||||
"#define INT_LEAST64_MIN (-9223372036854775808L)\n"
|
||||
"\n"
|
||||
"#define INT_LEAST8_MAX (127)\n"
|
||||
"#define INT_LEAST16_MAX (32767)\n"
|
||||
"#define INT_LEAST32_MAX (2147483647)\n"
|
||||
"#define INT_LEAST64_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define UINT_LEAST8_MAX (255)\n"
|
||||
"#define UINT_LEAST16_MAX (65535)\n"
|
||||
"#define UINT_LEAST32_MAX (4294967295U)\n"
|
||||
"#define UINT_LEAST64_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INT_FAST8_MIN (-128)\n"
|
||||
"#define INT_FAST16_MIN (-9223372036854775808L)\n"
|
||||
"#define INT_FAST32_MIN (-9223372036854775808L)\n"
|
||||
"#define INT_FAST64_MIN (-9223372036854775808L)\n"
|
||||
"\n"
|
||||
"#define INT_FAST8_MAX (127)\n"
|
||||
"#define INT_FAST16_MAX (9223372036854775807L)\n"
|
||||
"#define INT_FAST32_MAX (9223372036854775807L)\n"
|
||||
"#define INT_FAST64_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define UINT_FAST8_MAX (255)\n"
|
||||
"#define UINT_FAST16_MAX (18446744073709551615UL)\n"
|
||||
"#define UINT_FAST32_MAX (18446744073709551615UL)\n"
|
||||
"#define UINT_FAST64_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INTPTR_MIN (-9223372036854775808L)\n"
|
||||
"#define INTPTR_MAX (9223372036854775807L)\n"
|
||||
"#define UINTPTR_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INTMAX_MIN (-9223372036854775808L)\n"
|
||||
"#define INTMAX_MAX (9223372036854775807L)\n"
|
||||
"#define UINTMAX_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define PTRDIFF_MIN (-9223372036854775808L)\n"
|
||||
"#define PTRDIFF_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define SIZE_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"/* For signed wchar_t and wint_t: */\n"
|
||||
"#define WCHAR_MIN INT32_MIN\n"
|
||||
"#define WCHAR_MAX INT32_MAX\n"
|
||||
"#define WINT_MIN WCHAR_MIN\n"
|
||||
"#define WINT_MAX WCHAR_MAX\n"
|
||||
"\n"
|
||||
"#define INT8_C(value) value\n"
|
||||
"#define INT16_C(value) value\n"
|
||||
"#define INT32_C(value) value\n"
|
||||
"#define INT64_C(value) value##L\n"
|
||||
"\n"
|
||||
"#define UINT8_C(value) value\n"
|
||||
"#define UINT16_C(value) value\n"
|
||||
"#define UINT32_C(value) value##U\n"
|
||||
"#define UINT64_C(value) value##UL\n"
|
||||
"\n"
|
||||
"#define INTMAX_C(value) value##L\n"
|
||||
"#define UINTMAX_C(value) value##UL\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef _STDINT_H */\n";
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,21 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.9 */
|
||||
static char iso646_str[]
|
||||
= "#ifndef __ISO646_H\n"
|
||||
"#define __ISO646_H\n"
|
||||
"\n"
|
||||
"#define and &&\n"
|
||||
"#define and_eq &=\n"
|
||||
"#define bitand &\n"
|
||||
"#define bitor |\n"
|
||||
"#define compl ~\n"
|
||||
"#define not !\n"
|
||||
"#define not_eq !=\n"
|
||||
"#define or ||\n"
|
||||
"#define or_eq |=\n"
|
||||
"#define xor ^\n"
|
||||
"#define xor_eq ^=\n"
|
||||
"#endif /* #ifndef __ISO646_H */\n";
|
@ -0,0 +1,14 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.15 */
|
||||
static char stdalign_str[]
|
||||
= "#ifndef __STDALIGN_H\n"
|
||||
"#define __STDALIGN_H\n"
|
||||
"\n"
|
||||
"#define alignas _Alignas\n"
|
||||
"#define alignof _Alignof\n"
|
||||
"#define __alignas_is_defined 1\n"
|
||||
"#define __alignof_is_defined 1\n"
|
||||
"#endif /* #ifndef __STDALIGN_H */\n";
|
@ -0,0 +1,14 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.18 */
|
||||
static char stdbool_str[]
|
||||
= "#ifndef __STDBOOL_H\n"
|
||||
"#define __STDBOOL_H\n"
|
||||
"\n"
|
||||
"#define bool _Bool\n"
|
||||
"#define true 1\n"
|
||||
"#define false 0\n"
|
||||
"#define __bool_true_false_are_defined 1\n"
|
||||
"#endif /* #ifndef __STDBOOL_H */\n";
|
@ -0,0 +1,11 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.23 */
|
||||
static char stdnoreturn_str[]
|
||||
= "#ifndef __STDNORETURN_H\n"
|
||||
"#define __STDNORETURN_H\n"
|
||||
"\n"
|
||||
"#define noreturn _Noreturn\n"
|
||||
"#endif /* #ifndef __STDNORETURN_H */\n";
|
@ -0,0 +1,310 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2018-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
ppc64 call ABI target specific code.
|
||||
*/
|
||||
|
||||
typedef int target_arg_info_t;
|
||||
|
||||
static void target_init_arg_vars (c2m_ctx_t c2m_ctx, target_arg_info_t *arg_info) {}
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
static MIR_type_t fp_homogeneous_type (c2m_ctx_t c2m_ctx, struct type *param_type, int *num) {
|
||||
return MIR_T_UNDEF;
|
||||
}
|
||||
#else
|
||||
static MIR_type_t fp_homogeneous_type_1 (c2m_ctx_t c2m_ctx, MIR_type_t curr_type, struct type *type,
|
||||
int *num) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
int n;
|
||||
MIR_type_t t;
|
||||
|
||||
if (type->mode == TM_STRUCT || type->mode == TM_UNION || type->mode == TM_ARR) {
|
||||
switch (type->mode) {
|
||||
case TM_ARR: { /* Arrays are handled as small records. */
|
||||
struct arr_type *arr_type = type->u.arr_type;
|
||||
struct expr *cexpr = arr_type->size->attr;
|
||||
|
||||
if ((t = fp_homogeneous_type_1 (c2m_ctx, curr_type, type->u.arr_type->el_type, &n))
|
||||
== MIR_T_UNDEF)
|
||||
return MIR_T_UNDEF;
|
||||
*num = arr_type->size->code == N_IGNORE || !cexpr->const_p ? 1 : cexpr->u.i_val;
|
||||
return t;
|
||||
}
|
||||
case TM_STRUCT:
|
||||
case TM_UNION:
|
||||
t = curr_type;
|
||||
*num = 0;
|
||||
for (node_t el = NL_HEAD (NL_EL (type->u.tag_type->u.ops, 1)->u.ops); el != NULL;
|
||||
el = NL_NEXT (el))
|
||||
if (el->code == N_MEMBER) {
|
||||
decl_t decl = el->attr;
|
||||
|
||||
if ((t = fp_homogeneous_type_1 (c2m_ctx, t, decl->decl_spec.type, &n)) == MIR_T_UNDEF)
|
||||
return MIR_T_UNDEF;
|
||||
if (type->mode == TM_STRUCT)
|
||||
*num += n;
|
||||
else if (*num < n)
|
||||
*num = n;
|
||||
}
|
||||
return t;
|
||||
default: assert (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
assert (scalar_type_p (type));
|
||||
if ((t = get_mir_type (c2m_ctx, type)) != MIR_T_F && t != MIR_T_D) return MIR_T_UNDEF;
|
||||
if (curr_type != t && curr_type != MIR_T_UNDEF) return MIR_T_UNDEF;
|
||||
*num = 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
static MIR_type_t fp_homogeneous_type (c2m_ctx_t c2m_ctx, struct type *param_type, int *num) {
|
||||
if (param_type->mode != TM_STRUCT && param_type->mode != TM_UNION) return MIR_T_UNDEF;
|
||||
return fp_homogeneous_type_1 (c2m_ctx, MIR_T_UNDEF, param_type, num);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int reg_aggregate_p (c2m_ctx_t c2m_ctx, struct type *ret_type) {
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
return FALSE;
|
||||
#else
|
||||
return type_size (c2m_ctx, ret_type) <= 2 * 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int target_return_by_addr_p (c2m_ctx_t c2m_ctx, struct type *ret_type) {
|
||||
MIR_type_t type;
|
||||
int n;
|
||||
|
||||
if (ret_type->mode != TM_STRUCT && ret_type->mode != TM_UNION) return FALSE;
|
||||
if (((type = fp_homogeneous_type (c2m_ctx, ret_type, &n)) == MIR_T_F || type == MIR_T_D)
|
||||
&& n <= 8)
|
||||
return FALSE;
|
||||
return !reg_aggregate_p (c2m_ctx, ret_type);
|
||||
}
|
||||
|
||||
static void target_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type,
|
||||
target_arg_info_t *arg_info, VARR (MIR_type_t) * res_types,
|
||||
VARR (MIR_var_t) * arg_vars) {
|
||||
MIR_var_t var;
|
||||
MIR_type_t type;
|
||||
int i, n, size;
|
||||
|
||||
if (void_type_p (ret_type)) return;
|
||||
if (((type = fp_homogeneous_type (c2m_ctx, ret_type, &n)) == MIR_T_F || type == MIR_T_D)
|
||||
&& n <= 8) {
|
||||
for (i = 0; i < n; i++) VARR_PUSH (MIR_type_t, res_types, type);
|
||||
} else if (ret_type->mode != TM_STRUCT && ret_type->mode != TM_UNION) {
|
||||
VARR_PUSH (MIR_type_t, res_types, get_mir_type (c2m_ctx, ret_type));
|
||||
} else if (reg_aggregate_p (c2m_ctx, ret_type)) {
|
||||
size = type_size (c2m_ctx, ret_type);
|
||||
for (; size > 0; size -= 8) VARR_PUSH (MIR_type_t, res_types, MIR_T_I64);
|
||||
} else {
|
||||
var.name = RET_ADDR_NAME;
|
||||
var.type = MIR_T_RBLK;
|
||||
var.size = type_size (c2m_ctx, ret_type);
|
||||
VARR_PUSH (MIR_var_t, arg_vars, var);
|
||||
}
|
||||
}
|
||||
|
||||
static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type,
|
||||
target_arg_info_t *arg_info, size_t call_arg_area_offset) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
MIR_type_t type;
|
||||
op_t temp;
|
||||
int i, n, size;
|
||||
|
||||
if (void_type_p (ret_type)) return -1;
|
||||
if (((type = fp_homogeneous_type (c2m_ctx, ret_type, &n)) == MIR_T_F || type == MIR_T_D)
|
||||
&& n <= 8) {
|
||||
for (i = 0; i < n; i++) {
|
||||
temp = get_new_temp (c2m_ctx, type);
|
||||
VARR_PUSH (MIR_op_t, call_ops, temp.mir_op);
|
||||
}
|
||||
return n;
|
||||
} else if (ret_type->mode != TM_STRUCT && ret_type->mode != TM_UNION) {
|
||||
type = get_mir_type (c2m_ctx, ret_type);
|
||||
type = promote_mir_int_type (type);
|
||||
temp = get_new_temp (c2m_ctx, type);
|
||||
VARR_PUSH (MIR_op_t, call_ops, temp.mir_op);
|
||||
return 1;
|
||||
} else if (reg_aggregate_p (c2m_ctx, ret_type)) {
|
||||
size = type_size (c2m_ctx, ret_type);
|
||||
if (size == 0) return -1;
|
||||
for (int s = size; s > 0; s -= 8) {
|
||||
temp = get_new_temp (c2m_ctx, MIR_T_I64);
|
||||
VARR_PUSH (MIR_op_t, call_ops, temp.mir_op);
|
||||
}
|
||||
return (size + 7) / 8;
|
||||
} else {
|
||||
temp = get_new_temp (c2m_ctx, MIR_T_I64);
|
||||
emit3 (c2m_ctx, MIR_ADD, temp.mir_op,
|
||||
MIR_new_reg_op (ctx, MIR_reg (ctx, FP_NAME, curr_func->u.func)),
|
||||
MIR_new_int_op (ctx, call_arg_area_offset));
|
||||
temp.mir_op
|
||||
= MIR_new_mem_op (ctx, MIR_T_RBLK, type_size (c2m_ctx, ret_type), temp.mir_op.u.reg, 0, 1);
|
||||
VARR_PUSH (MIR_op_t, call_ops, temp.mir_op);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res,
|
||||
MIR_insn_t call, size_t call_ops_start) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
MIR_type_t type;
|
||||
MIR_insn_t insn;
|
||||
int i, n;
|
||||
|
||||
if (void_type_p (ret_type)) return res;
|
||||
if (((type = fp_homogeneous_type (c2m_ctx, ret_type, &n)) == MIR_T_F || type == MIR_T_D)
|
||||
&& n <= 8) {
|
||||
assert (res.mir_op.mode == MIR_OP_MEM);
|
||||
for (i = 0; i < n; i++) {
|
||||
insn = MIR_new_insn (ctx, tp_mov (type),
|
||||
MIR_new_mem_op (ctx, type,
|
||||
res.mir_op.u.mem.disp + (type == MIR_T_F ? 4 : 8) * i,
|
||||
res.mir_op.u.mem.base, res.mir_op.u.mem.index,
|
||||
res.mir_op.u.mem.scale),
|
||||
VARR_GET (MIR_op_t, call_ops, i + call_ops_start + 2));
|
||||
MIR_append_insn (ctx, curr_func, insn);
|
||||
}
|
||||
} else if ((ret_type->mode == TM_STRUCT || ret_type->mode == TM_UNION)
|
||||
&& reg_aggregate_p (c2m_ctx, ret_type)) {
|
||||
assert (res.mir_op.mode == MIR_OP_MEM); /* addr */
|
||||
gen_multiple_load_store (c2m_ctx, ret_type, &VARR_ADDR (MIR_op_t, call_ops)[call_ops_start + 2],
|
||||
res.mir_op, FALSE);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
MIR_type_t type;
|
||||
MIR_insn_t insn;
|
||||
MIR_reg_t ret_addr_reg;
|
||||
op_t temp, var;
|
||||
int i, n, size;
|
||||
|
||||
if (void_type_p (ret_type)) return;
|
||||
if (((type = fp_homogeneous_type (c2m_ctx, ret_type, &n)) == MIR_T_F || type == MIR_T_D)
|
||||
&& n <= 8) {
|
||||
assert (res.mir_op.mode == MIR_OP_MEM);
|
||||
for (int i = 0; i < n; i++) {
|
||||
temp = get_new_temp (c2m_ctx, type);
|
||||
insn = MIR_new_insn (ctx, tp_mov (type), temp.mir_op,
|
||||
MIR_new_mem_op (ctx, type,
|
||||
res.mir_op.u.mem.disp + (type == MIR_T_F ? 4 : 8) * i,
|
||||
res.mir_op.u.mem.base, res.mir_op.u.mem.index,
|
||||
res.mir_op.u.mem.scale));
|
||||
MIR_append_insn (ctx, curr_func, insn);
|
||||
VARR_PUSH (MIR_op_t, ret_ops, temp.mir_op);
|
||||
}
|
||||
} else if (ret_type->mode != TM_STRUCT && ret_type->mode != TM_UNION) {
|
||||
VARR_PUSH (MIR_op_t, ret_ops, res.mir_op);
|
||||
} else if (reg_aggregate_p (c2m_ctx, ret_type)) {
|
||||
size = type_size (c2m_ctx, ret_type);
|
||||
assert (res.mir_op.mode == MIR_OP_MEM && VARR_LENGTH (MIR_op_t, ret_ops) == 0);
|
||||
for (int i = 0; size > 0; size -= 8, i++)
|
||||
VARR_PUSH (MIR_op_t, ret_ops, get_new_temp (c2m_ctx, MIR_T_I64).mir_op);
|
||||
gen_multiple_load_store (c2m_ctx, ret_type, &VARR_ADDR (MIR_op_t, ret_ops)[0], res.mir_op,
|
||||
TRUE);
|
||||
} else {
|
||||
ret_addr_reg = MIR_reg (ctx, RET_ADDR_NAME, curr_func->u.func);
|
||||
var = new_op (NULL, MIR_new_mem_op (ctx, MIR_T_I8, 0, ret_addr_reg, 0, 1));
|
||||
size = type_size (c2m_ctx, ret_type);
|
||||
block_move (c2m_ctx, var, res, size);
|
||||
}
|
||||
}
|
||||
|
||||
static MIR_type_t target_get_blk_type (c2m_ctx_t c2m_ctx, struct type *arg_type) {
|
||||
return MIR_T_BLK; /* one BLK is enough */
|
||||
}
|
||||
|
||||
static void target_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type,
|
||||
target_arg_info_t *arg_info, VARR (MIR_var_t) * arg_vars) {
|
||||
MIR_var_t var;
|
||||
MIR_type_t type;
|
||||
int n;
|
||||
|
||||
if (((type = fp_homogeneous_type (c2m_ctx, arg_type, &n)) == MIR_T_F || type == MIR_T_D)
|
||||
&& n <= 8) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
var.name = gen_get_indexed_name (c2m_ctx, name, i);
|
||||
var.type = type;
|
||||
VARR_PUSH (MIR_var_t, arg_vars, var);
|
||||
}
|
||||
return;
|
||||
}
|
||||
type = (arg_type->mode == TM_STRUCT || arg_type->mode == TM_UNION
|
||||
? MIR_T_BLK
|
||||
: get_mir_type (c2m_ctx, arg_type));
|
||||
var.name = name;
|
||||
var.type = type;
|
||||
if (type == MIR_T_BLK) var.size = type_size (c2m_ctx, arg_type);
|
||||
VARR_PUSH (MIR_var_t, arg_vars, var);
|
||||
}
|
||||
|
||||
static void target_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type,
|
||||
target_arg_info_t *arg_info, op_t arg) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
MIR_var_t var;
|
||||
MIR_type_t type;
|
||||
op_t temp;
|
||||
int n;
|
||||
|
||||
if (((type = fp_homogeneous_type (c2m_ctx, arg_type, &n)) == MIR_T_F || type == MIR_T_D)
|
||||
&& n <= 8) {
|
||||
assert (arg.mir_op.mode == MIR_OP_MEM);
|
||||
arg = mem_to_address (c2m_ctx, arg, TRUE);
|
||||
for (int i = 0; i < n; i++) {
|
||||
temp = get_new_temp (c2m_ctx, type);
|
||||
MIR_append_insn (ctx, curr_func,
|
||||
MIR_new_insn (ctx, tp_mov (type), temp.mir_op,
|
||||
MIR_new_mem_op (ctx, type, (type == MIR_T_F ? 4 : 8) * i,
|
||||
arg.mir_op.u.reg, 0, 1)));
|
||||
VARR_PUSH (MIR_op_t, call_ops, temp.mir_op);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (arg_type->mode != TM_STRUCT && arg_type->mode != TM_UNION) {
|
||||
VARR_PUSH (MIR_op_t, call_ops, arg.mir_op);
|
||||
} else {
|
||||
assert (arg.mir_op.mode == MIR_OP_MEM);
|
||||
arg = mem_to_address (c2m_ctx, arg, TRUE);
|
||||
VARR_PUSH (MIR_op_t, call_ops,
|
||||
MIR_new_mem_op (ctx, MIR_T_BLK, type_size (c2m_ctx, arg_type), arg.mir_op.u.reg, 0,
|
||||
1));
|
||||
}
|
||||
}
|
||||
|
||||
static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type,
|
||||
decl_t param_decl, target_arg_info_t *arg_info) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
MIR_var_t var;
|
||||
MIR_type_t type;
|
||||
reg_var_t reg_var;
|
||||
int i, n;
|
||||
|
||||
if (((type = fp_homogeneous_type (c2m_ctx, arg_type, &n)) == MIR_T_F || type == MIR_T_D)
|
||||
&& n <= 8) {
|
||||
for (i = 0; i < n; i++) {
|
||||
assert (!param_decl->reg_p);
|
||||
reg_var = get_reg_var (c2m_ctx, type, gen_get_indexed_name (c2m_ctx, name, i));
|
||||
MIR_append_insn (ctx, curr_func,
|
||||
MIR_new_insn (ctx, tp_mov (type),
|
||||
MIR_new_mem_op (ctx, type,
|
||||
param_decl->offset
|
||||
+ (type == MIR_T_F ? 4 : 8) * i,
|
||||
MIR_reg (ctx, FP_NAME, curr_func->u.func), 0,
|
||||
1),
|
||||
MIR_new_reg_op (ctx, reg_var.reg)));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 5.2.4.2.2 */
|
||||
static char float_str[]
|
||||
= "#ifndef __FLOAT_H\n"
|
||||
"#define __FLOAT_H\n"
|
||||
"\n"
|
||||
"#define FLT_RADIX 2\n"
|
||||
"\n"
|
||||
"#define FLT_MANT_DIG 24\n"
|
||||
"#define DBL_MANT_DIG 53\n"
|
||||
"#define LDBL_MANT_DIG DBL_MANT_DIG\n"
|
||||
"\n"
|
||||
"#define FLT_DECIMAL_DIG 9\n"
|
||||
"#define DBL_DECIMAL_DIG 17\n"
|
||||
"#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG\n"
|
||||
"#define FLT_DIG FLT_DECIMAL_DIG\n"
|
||||
"#define DBL_DIG DBL_DECIMAL_DIG\n"
|
||||
"#define LDBL_DIG LDBL_DECIMAL_DIG\n"
|
||||
"\n"
|
||||
"#define DECIMAL_DIG LDBL_DECIMAL_DIG\n"
|
||||
"\n"
|
||||
"#define FLT_MIN_EXP -125\n"
|
||||
"#define DBL_MIN_EXP -1021\n"
|
||||
"#define LDBL_MIN_EXP DBL_MIN_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MIN_10_EXP -37\n"
|
||||
"#define DBL_MIN_10_EXP -307\n"
|
||||
"#define LDBL_MIN_10_EXP DBL_MIN_10_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX_EXP 128\n"
|
||||
"#define DBL_MAX_EXP 1024\n"
|
||||
"#define LDBL_MAX_EXP DBL_MAX_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX_10_EXP 38\n"
|
||||
"#define DBL_MAX_10_EXP 308\n"
|
||||
"#define LDBL_MAX_10_EXP DBL_MAX_10_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX 0x1.fffffep+127\n"
|
||||
"#define DBL_MAX 0x1.fffffffffffffp+1023\n"
|
||||
"#define LDBL_MAX DBL_MAX\n"
|
||||
"\n"
|
||||
"#define FLT_EPSILON 0x1p-23\n"
|
||||
"#define DBL_EPSILON 0x1p-52\n"
|
||||
"#define LDBL_EPSILON DBL_EPSILON\n"
|
||||
"\n"
|
||||
"#define FLT_MIN 0x1p-126\n"
|
||||
"#define DBL_MIN 0x1p-1022\n"
|
||||
"#define LDBL_MIN DBL_MIN\n"
|
||||
"\n"
|
||||
"#define FLT_TRUE_MIN 0x1p-149\n"
|
||||
"#define DBL_TRUE_MIN 0x0.0000000000001p-1022\n"
|
||||
"#define LDBL_TRUE_MIN DBL_TRUE_MIN\n"
|
||||
"\n"
|
||||
"#define FLT_EVAL_METHOD 0\n"
|
||||
"#define FLT_ROUNDS 1 /* round to the nearest */\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __FLOAT_H */\n";
|
@ -0,0 +1,38 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See 5.2.4.2 */
|
||||
static char limits_str[]
|
||||
= "#ifndef __LIMITS_H\n"
|
||||
"#define __LIMITS_H\n"
|
||||
"\n"
|
||||
"#define CHAR_BIT 8\n"
|
||||
"\n"
|
||||
"#define SCHAR_MIN (-SCHAR_MAX - 1)\n"
|
||||
"#define SCHAR_MAX 127\n"
|
||||
"#define UCHAR_MAX (SCHAR_MAX * 2 + 1)\n"
|
||||
"\n"
|
||||
"#define MB_LEN_MAX 1\n"
|
||||
"\n"
|
||||
"#define SHRT_MIN (-SHRT_MAX - 1)\n"
|
||||
"#define SHRT_MAX 32767\n"
|
||||
"#define USHRT_MAX (SHRT_MAX * 2 + 1)\n"
|
||||
"\n"
|
||||
"#define INT_MIN (-INT_MAX - 1)\n"
|
||||
"#define INT_MAX 2147483647\n"
|
||||
"#define UINT_MAX (INT_MAX * 2u + 1u)\n"
|
||||
"\n"
|
||||
"#define LONG_MIN (-LONG_MAX - 1l)\n"
|
||||
"#define LONG_MAX 9223372036854775807l\n"
|
||||
"#define ULONG_MAX (LONG_MAX * 2ul + 1ul)\n"
|
||||
"\n"
|
||||
"#define LLONG_MIN LONG_MIN\n"
|
||||
"#define LLONG_MAX LONG_MAX\n"
|
||||
"#define ULLONG_MAX ULONG_MAX\n"
|
||||
"\n"
|
||||
"/* unsigned char by default */\n"
|
||||
"#define CHAR_MIN 0\n"
|
||||
"#define CHAR_MAX UCHAR_MAX\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __LIMITS_H */\n";
|
@ -0,0 +1,21 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
static char stdarg_str[]
|
||||
= "#ifndef __STDARG_H\n"
|
||||
"#define __STDARG_H\n"
|
||||
"\n"
|
||||
"typedef void *va_list[1];\n"
|
||||
"\n"
|
||||
"#define va_start(ap, param) __builtin_va_start (ap)\n"
|
||||
"#define va_arg(ap, type) __builtin_va_arg(ap, (type *) 0)\n"
|
||||
"#define va_end(ap) 0\n"
|
||||
"#define va_copy(dest, src) ((dest) = (src))\n"
|
||||
"\n"
|
||||
"/* For standard headers of a GNU system: */\n"
|
||||
"#ifndef __GNUC_VA_LIST\n"
|
||||
"#define __GNUC_VA_LIST 1\n"
|
||||
"#endif\n"
|
||||
"typedef va_list __gnuc_va_list;\n"
|
||||
"#endif /* #ifndef __STDARG_H */\n";
|
@ -0,0 +1,19 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.19 */
|
||||
static char stddef_str[]
|
||||
= "#ifndef __STDDEF_H\n"
|
||||
"#define __STDDEF_H\n"
|
||||
"\n"
|
||||
"typedef long ptrdiff_t;\n"
|
||||
"typedef unsigned long size_t;\n"
|
||||
"typedef long double max_align_t;\n"
|
||||
"typedef unsigned int wchar_t;\n"
|
||||
"\n"
|
||||
"#define NULL ((void *) 0)\n"
|
||||
"\n"
|
||||
"#define offsetof(type, member_designator) ((size_t) & ((type *) 0)->member_designator)\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __STDDEF_H */\n";
|
@ -0,0 +1,130 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.20 */
|
||||
static char stdint_str[]
|
||||
= "#ifndef _STDINT_H\n"
|
||||
"#define _STDINT_H 1\n"
|
||||
"\n"
|
||||
"#ifndef __int8_t_defined\n"
|
||||
"#define __int8_t_defined\n"
|
||||
"typedef signed char int8_t;\n"
|
||||
"#endif\n"
|
||||
"typedef short int int16_t;\n"
|
||||
"typedef int int32_t;\n"
|
||||
"typedef long int int64_t;\n"
|
||||
"\n"
|
||||
"typedef unsigned char uint8_t;\n"
|
||||
"typedef unsigned short int uint16_t;\n"
|
||||
"typedef unsigned int uint32_t;\n"
|
||||
"typedef unsigned long int uint64_t;\n"
|
||||
"\n"
|
||||
"typedef signed char int_least8_t;\n"
|
||||
"typedef short int int_least16_t;\n"
|
||||
"typedef int int_least32_t;\n"
|
||||
"typedef long int int_least64_t;\n"
|
||||
"\n"
|
||||
"typedef unsigned char uint_least8_t;\n"
|
||||
"typedef unsigned short int uint_least16_t;\n"
|
||||
"typedef unsigned int uint_least32_t;\n"
|
||||
"typedef unsigned long int uint_least64_t;\n"
|
||||
"\n"
|
||||
"typedef signed char int_fast8_t;\n"
|
||||
"typedef long int int_fast16_t;\n"
|
||||
"typedef long int int_fast32_t;\n"
|
||||
"typedef long int int_fast64_t;\n"
|
||||
"\n"
|
||||
"typedef unsigned char uint_fast8_t;\n"
|
||||
"typedef unsigned long int uint_fast16_t;\n"
|
||||
"typedef unsigned long int uint_fast32_t;\n"
|
||||
"typedef unsigned long int uint_fast64_t;\n"
|
||||
"\n"
|
||||
"#define __intptr_t_defined\n"
|
||||
"typedef long int intptr_t;\n"
|
||||
"typedef unsigned long int uintptr_t;\n"
|
||||
"\n"
|
||||
"typedef long int intmax_t;\n"
|
||||
"typedef unsigned long int uintmax_t;\n"
|
||||
"\n"
|
||||
"#define __INT64_C(c) c##L\n"
|
||||
"#define __UINT64_C(c) c##UL\n"
|
||||
"\n"
|
||||
"#define INT8_MIN (-128)\n"
|
||||
"#define INT16_MIN (-32768)\n"
|
||||
"#define INT32_MIN (-2147483648)\n"
|
||||
"#define INT64_MIN (-9223372036854775808l)\n"
|
||||
"\n"
|
||||
"#define INT8_MAX (127)\n"
|
||||
"#define INT16_MAX (32767)\n"
|
||||
"#define INT32_MAX (2147483647)\n"
|
||||
"#define INT64_MAX (9223372036854775807l)\n"
|
||||
"\n"
|
||||
"#define UINT8_MAX (255)\n"
|
||||
"#define UINT16_MAX (65535)\n"
|
||||
"#define UINT32_MAX (4294967295u)\n"
|
||||
"#define UINT64_MAX (18446744073709551615ul)\n"
|
||||
"\n"
|
||||
"#define INT_LEAST8_MIN (-128)\n"
|
||||
"#define INT_LEAST16_MIN (-32768)\n"
|
||||
"#define INT_LEAST32_MIN (-2147483648)\n"
|
||||
"#define INT_LEAST64_MIN (-9223372036854775808L)\n"
|
||||
"\n"
|
||||
"#define INT_LEAST8_MAX (127)\n"
|
||||
"#define INT_LEAST16_MAX (32767)\n"
|
||||
"#define INT_LEAST32_MAX (2147483647)\n"
|
||||
"#define INT_LEAST64_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define UINT_LEAST8_MAX (255)\n"
|
||||
"#define UINT_LEAST16_MAX (65535)\n"
|
||||
"#define UINT_LEAST32_MAX (4294967295U)\n"
|
||||
"#define UINT_LEAST64_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INT_FAST8_MIN (-128)\n"
|
||||
"#define INT_FAST16_MIN (-9223372036854775808L)\n"
|
||||
"#define INT_FAST32_MIN (-9223372036854775808L)\n"
|
||||
"#define INT_FAST64_MIN (-9223372036854775808L)\n"
|
||||
"\n"
|
||||
"#define INT_FAST8_MAX (127)\n"
|
||||
"#define INT_FAST16_MAX (9223372036854775807L)\n"
|
||||
"#define INT_FAST32_MAX (9223372036854775807L)\n"
|
||||
"#define INT_FAST64_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define UINT_FAST8_MAX (255)\n"
|
||||
"#define UINT_FAST16_MAX (18446744073709551615UL)\n"
|
||||
"#define UINT_FAST32_MAX (18446744073709551615UL)\n"
|
||||
"#define UINT_FAST64_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INTPTR_MIN (-9223372036854775808L)\n"
|
||||
"#define INTPTR_MAX (9223372036854775807L)\n"
|
||||
"#define UINTPTR_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INTMAX_MIN (-9223372036854775808L)\n"
|
||||
"#define INTMAX_MAX (9223372036854775807L)\n"
|
||||
"#define UINTMAX_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define PTRDIFF_MIN (-9223372036854775808L)\n"
|
||||
"#define PTRDIFF_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define SIZE_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"/* For signed wchar_t and wint_t: */\n"
|
||||
"#define WCHAR_MIN INT32_MIN\n"
|
||||
"#define WCHAR_MAX INT32_MAX\n"
|
||||
"#define WINT_MIN WCHAR_MIN\n"
|
||||
"#define WINT_MAX WCHAR_MAX\n"
|
||||
"\n"
|
||||
"#define INT8_C(value) value\n"
|
||||
"#define INT16_C(value) value\n"
|
||||
"#define INT32_C(value) value\n"
|
||||
"#define INT64_C(value) value##L\n"
|
||||
"\n"
|
||||
"#define UINT8_C(value) value\n"
|
||||
"#define UINT16_C(value) value\n"
|
||||
"#define UINT32_C(value) value##U\n"
|
||||
"#define UINT64_C(value) value##UL\n"
|
||||
"\n"
|
||||
"#define INTMAX_C(value) value##L\n"
|
||||
"#define UINTMAX_C(value) value##UL\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef _STDINT_H */\n";
|
@ -0,0 +1,100 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2018-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
s390x call ABI target specific code.
|
||||
*/
|
||||
|
||||
typedef int target_arg_info_t;
|
||||
|
||||
static void target_init_arg_vars (c2m_ctx_t c2m_ctx, target_arg_info_t *arg_info) {}
|
||||
|
||||
static int target_return_by_addr_p (c2m_ctx_t c2m_ctx, struct type *ret_type) {
|
||||
return simple_return_by_addr_p (c2m_ctx, ret_type);
|
||||
}
|
||||
|
||||
static void target_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type,
|
||||
target_arg_info_t *arg_info, VARR (MIR_type_t) * res_types,
|
||||
VARR (MIR_var_t) * arg_vars) {
|
||||
simple_add_res_proto (c2m_ctx, ret_type, arg_info, res_types, arg_vars);
|
||||
}
|
||||
|
||||
static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type,
|
||||
target_arg_info_t *arg_info, size_t call_arg_area_offset) {
|
||||
return simple_add_call_res_op (c2m_ctx, ret_type, arg_info, call_arg_area_offset);
|
||||
}
|
||||
|
||||
static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res,
|
||||
MIR_insn_t call, size_t call_ops_start) {
|
||||
return simple_gen_post_call_res_code (c2m_ctx, ret_type, res, call, call_ops_start);
|
||||
}
|
||||
|
||||
static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res) {
|
||||
simple_add_ret_ops (c2m_ctx, ret_type, res);
|
||||
}
|
||||
|
||||
static int reg_aggregate_p (c2m_ctx_t c2m_ctx, struct type *arg_type) {
|
||||
size_t size = type_size (c2m_ctx, arg_type);
|
||||
return size == 1 || size == 2 || size == 4 || size == 8;
|
||||
}
|
||||
|
||||
static MIR_type_t target_get_blk_type (c2m_ctx_t c2m_ctx, struct type *arg_type) {
|
||||
return MIR_T_BLK; /* one BLK is enough */
|
||||
}
|
||||
|
||||
static void target_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type,
|
||||
target_arg_info_t *arg_info, VARR (MIR_var_t) * arg_vars) {
|
||||
MIR_var_t var;
|
||||
MIR_type_t type;
|
||||
|
||||
if (arg_type->mode != TM_STRUCT && arg_type->mode != TM_UNION)
|
||||
type = get_mir_type (c2m_ctx, arg_type);
|
||||
else if (reg_aggregate_p (c2m_ctx, arg_type))
|
||||
type = MIR_T_I64;
|
||||
else
|
||||
type = MIR_T_BLK;
|
||||
var.name = name;
|
||||
var.type = type;
|
||||
if (type == MIR_T_BLK) var.size = type_size (c2m_ctx, arg_type);
|
||||
VARR_PUSH (MIR_var_t, arg_vars, var);
|
||||
}
|
||||
|
||||
static void target_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type,
|
||||
target_arg_info_t *arg_info, op_t arg) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
op_t temp;
|
||||
|
||||
if (arg_type->mode != TM_STRUCT && arg_type->mode != TM_UNION) {
|
||||
VARR_PUSH (MIR_op_t, call_ops, arg.mir_op);
|
||||
} else if (reg_aggregate_p (c2m_ctx, arg_type)) {
|
||||
assert (arg.mir_op.mode == MIR_OP_MEM);
|
||||
temp = get_new_temp (c2m_ctx, MIR_T_I64);
|
||||
gen_multiple_load_store (c2m_ctx, arg_type, &temp.mir_op, arg.mir_op, TRUE);
|
||||
VARR_PUSH (MIR_op_t, call_ops, temp.mir_op);
|
||||
} else {
|
||||
assert (arg.mir_op.mode == MIR_OP_MEM);
|
||||
arg = mem_to_address (c2m_ctx, arg, TRUE);
|
||||
VARR_PUSH (MIR_op_t, call_ops,
|
||||
MIR_new_mem_op (c2m_ctx->ctx, MIR_T_BLK, type_size (c2m_ctx, arg_type),
|
||||
arg.mir_op.u.reg, 0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type,
|
||||
decl_t param_decl, target_arg_info_t *arg_info) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
MIR_type_t type;
|
||||
MIR_op_t param_op;
|
||||
reg_var_t reg_var;
|
||||
|
||||
if ((arg_type->mode != TM_STRUCT && arg_type->mode != TM_UNION)
|
||||
|| !reg_aggregate_p (c2m_ctx, arg_type))
|
||||
return FALSE;
|
||||
assert (!param_decl->reg_p);
|
||||
reg_var = get_reg_var (c2m_ctx, MIR_T_I64, name);
|
||||
param_op = MIR_new_reg_op (ctx, reg_var.reg);
|
||||
gen_multiple_load_store (c2m_ctx, arg_type, ¶m_op,
|
||||
MIR_new_mem_op (ctx, MIR_T_UNDEF, param_decl->offset,
|
||||
MIR_reg (ctx, FP_NAME, curr_func->u.func), 0, 1),
|
||||
FALSE);
|
||||
return TRUE;
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 5.2.4.2.2 */
|
||||
static char float_str[]
|
||||
= "#ifndef __FLOAT_H\n"
|
||||
"#define __FLOAT_H\n"
|
||||
"\n"
|
||||
"#define FLT_RADIX 2\n"
|
||||
"\n"
|
||||
"#define FLT_MANT_DIG 24\n"
|
||||
"#define DBL_MANT_DIG 53\n"
|
||||
"#define LDBL_MANT_DIG DBL_MANT_DIG\n"
|
||||
"\n"
|
||||
"#define FLT_DECIMAL_DIG 9\n"
|
||||
"#define DBL_DECIMAL_DIG 17\n"
|
||||
"#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG\n"
|
||||
"#define FLT_DIG FLT_DECIMAL_DIG\n"
|
||||
"#define DBL_DIG DBL_DECIMAL_DIG\n"
|
||||
"#define LDBL_DIG LDBL_DECIMAL_DIG\n"
|
||||
"\n"
|
||||
"#define DECIMAL_DIG LDBL_DECIMAL_DIG\n"
|
||||
"\n"
|
||||
"#define FLT_MIN_EXP -125\n"
|
||||
"#define DBL_MIN_EXP -1021\n"
|
||||
"#define LDBL_MIN_EXP DBL_MIN_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MIN_10_EXP -37\n"
|
||||
"#define DBL_MIN_10_EXP -307\n"
|
||||
"#define LDBL_MIN_10_EXP DBL_MIN_10_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX_EXP 128\n"
|
||||
"#define DBL_MAX_EXP 1024\n"
|
||||
"#define LDBL_MAX_EXP DBL_MAX_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX_10_EXP 38\n"
|
||||
"#define DBL_MAX_10_EXP 308\n"
|
||||
"#define LDBL_MAX_10_EXP DBL_MAX_10_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX 0x1.fffffep+127\n"
|
||||
"#define DBL_MAX 0x1.fffffffffffffp+1023\n"
|
||||
"#define LDBL_MAX DBL_MAX\n"
|
||||
"\n"
|
||||
"#define FLT_EPSILON 0x1p-23\n"
|
||||
"#define DBL_EPSILON 0x1p-52\n"
|
||||
"#define LDBL_EPSILON DBL_EPSILON\n"
|
||||
"\n"
|
||||
"#define FLT_MIN 0x1p-126\n"
|
||||
"#define DBL_MIN 0x1p-1022\n"
|
||||
"#define LDBL_MIN DBL_MIN\n"
|
||||
"\n"
|
||||
"#define FLT_TRUE_MIN 0x1p-149\n"
|
||||
"#define DBL_TRUE_MIN 0x0.0000000000001p-1022\n"
|
||||
"#define LDBL_TRUE_MIN DBL_TRUE_MIN\n"
|
||||
"\n"
|
||||
"#define FLT_EVAL_METHOD 0\n"
|
||||
"#define FLT_ROUNDS 1 /* round to the nearest */\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __FLOAT_H */\n";
|
@ -0,0 +1,38 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See 5.2.4.2 */
|
||||
static char limits_str[]
|
||||
= "#ifndef __LIMITS_H\n"
|
||||
"#define __LIMITS_H\n"
|
||||
"\n"
|
||||
"#define CHAR_BIT 8\n"
|
||||
"\n"
|
||||
"#define SCHAR_MIN (-SCHAR_MAX - 1)\n"
|
||||
"#define SCHAR_MAX 127\n"
|
||||
"#define UCHAR_MAX (SCHAR_MAX * 2 + 1)\n"
|
||||
"\n"
|
||||
"#define MB_LEN_MAX 1\n"
|
||||
"\n"
|
||||
"#define SHRT_MIN (-SHRT_MAX - 1)\n"
|
||||
"#define SHRT_MAX 32767\n"
|
||||
"#define USHRT_MAX (SHRT_MAX * 2 + 1)\n"
|
||||
"\n"
|
||||
"#define INT_MIN (-INT_MAX - 1)\n"
|
||||
"#define INT_MAX 2147483647\n"
|
||||
"#define UINT_MAX (INT_MAX * 2u + 1u)\n"
|
||||
"\n"
|
||||
"#define LONG_MIN (-LONG_MAX - 1l)\n"
|
||||
"#define LONG_MAX 9223372036854775807l\n"
|
||||
"#define ULONG_MAX (LONG_MAX * 2ul + 1ul)\n"
|
||||
"\n"
|
||||
"#define LLONG_MIN LONG_MIN\n"
|
||||
"#define LLONG_MAX LONG_MAX\n"
|
||||
"#define ULLONG_MAX ULONG_MAX\n"
|
||||
"\n"
|
||||
"/* unsigned char by default */\n"
|
||||
"#define CHAR_MIN 0\n"
|
||||
"#define CHAR_MAX UCHAR_MAX\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __LIMITS_H */\n";
|
@ -0,0 +1,25 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
static char stdarg_str[]
|
||||
= "#ifndef __STDARG_H\n"
|
||||
"#define __STDARG_H\n"
|
||||
"\n"
|
||||
"typedef struct {\n"
|
||||
" long __gpr, __fpr;\n"
|
||||
" void *__overflow_arg_area;\n"
|
||||
" void *__reg_save_area;\n"
|
||||
"} va_list[1];\n"
|
||||
"\n"
|
||||
"#define va_start(ap, param) __builtin_va_start (ap)\n"
|
||||
"#define va_arg(ap, type) __builtin_va_arg(ap, (type *) 0)\n"
|
||||
"#define va_end(ap) 0\n"
|
||||
"#define va_copy(dest, src) ((dest) = (src))\n"
|
||||
"\n"
|
||||
"/* For standard headers of a GNU system: */\n"
|
||||
"#ifndef __GNUC_VA_LIST\n"
|
||||
"#define __GNUC_VA_LIST 1\n"
|
||||
"#endif\n"
|
||||
"typedef va_list __gnuc_va_list;\n"
|
||||
"#endif /* #ifndef __STDARG_H */\n";
|
@ -0,0 +1,19 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.19 */
|
||||
static char stddef_str[]
|
||||
= "#ifndef __STDDEF_H\n"
|
||||
"#define __STDDEF_H\n"
|
||||
"\n"
|
||||
"typedef long ptrdiff_t;\n"
|
||||
"typedef unsigned long size_t;\n"
|
||||
"typedef long double max_align_t;\n"
|
||||
"typedef unsigned int wchar_t;\n"
|
||||
"\n"
|
||||
"#define NULL ((void *) 0)\n"
|
||||
"\n"
|
||||
"#define offsetof(type, member_designator) ((size_t) & ((type *) 0)->member_designator)\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __STDDEF_H */\n";
|
@ -0,0 +1,130 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2020-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.20 */
|
||||
static char stdint_str[]
|
||||
= "#ifndef _STDINT_H\n"
|
||||
"#define _STDINT_H 1\n"
|
||||
"\n"
|
||||
"#ifndef __int8_t_defined\n"
|
||||
"#define __int8_t_defined\n"
|
||||
"typedef signed char int8_t;\n"
|
||||
"#endif\n"
|
||||
"typedef short int int16_t;\n"
|
||||
"typedef int int32_t;\n"
|
||||
"typedef long int int64_t;\n"
|
||||
"\n"
|
||||
"typedef unsigned char uint8_t;\n"
|
||||
"typedef unsigned short int uint16_t;\n"
|
||||
"typedef unsigned int uint32_t;\n"
|
||||
"typedef unsigned long int uint64_t;\n"
|
||||
"\n"
|
||||
"typedef signed char int_least8_t;\n"
|
||||
"typedef short int int_least16_t;\n"
|
||||
"typedef int int_least32_t;\n"
|
||||
"typedef long int int_least64_t;\n"
|
||||
"\n"
|
||||
"typedef unsigned char uint_least8_t;\n"
|
||||
"typedef unsigned short int uint_least16_t;\n"
|
||||
"typedef unsigned int uint_least32_t;\n"
|
||||
"typedef unsigned long int uint_least64_t;\n"
|
||||
"\n"
|
||||
"typedef signed char int_fast8_t;\n"
|
||||
"typedef long int int_fast16_t;\n"
|
||||
"typedef long int int_fast32_t;\n"
|
||||
"typedef long int int_fast64_t;\n"
|
||||
"\n"
|
||||
"typedef unsigned char uint_fast8_t;\n"
|
||||
"typedef unsigned long int uint_fast16_t;\n"
|
||||
"typedef unsigned long int uint_fast32_t;\n"
|
||||
"typedef unsigned long int uint_fast64_t;\n"
|
||||
"\n"
|
||||
"#define __intptr_t_defined\n"
|
||||
"typedef long int intptr_t;\n"
|
||||
"typedef unsigned long int uintptr_t;\n"
|
||||
"\n"
|
||||
"typedef long int intmax_t;\n"
|
||||
"typedef unsigned long int uintmax_t;\n"
|
||||
"\n"
|
||||
"#define __INT64_C(c) c##L\n"
|
||||
"#define __UINT64_C(c) c##UL\n"
|
||||
"\n"
|
||||
"#define INT8_MIN (-128)\n"
|
||||
"#define INT16_MIN (-32768)\n"
|
||||
"#define INT32_MIN (-2147483648)\n"
|
||||
"#define INT64_MIN (-9223372036854775808l)\n"
|
||||
"\n"
|
||||
"#define INT8_MAX (127)\n"
|
||||
"#define INT16_MAX (32767)\n"
|
||||
"#define INT32_MAX (2147483647)\n"
|
||||
"#define INT64_MAX (9223372036854775807l)\n"
|
||||
"\n"
|
||||
"#define UINT8_MAX (255)\n"
|
||||
"#define UINT16_MAX (65535)\n"
|
||||
"#define UINT32_MAX (4294967295u)\n"
|
||||
"#define UINT64_MAX (18446744073709551615ul)\n"
|
||||
"\n"
|
||||
"#define INT_LEAST8_MIN (-128)\n"
|
||||
"#define INT_LEAST16_MIN (-32768)\n"
|
||||
"#define INT_LEAST32_MIN (-2147483648)\n"
|
||||
"#define INT_LEAST64_MIN (-9223372036854775808L)\n"
|
||||
"\n"
|
||||
"#define INT_LEAST8_MAX (127)\n"
|
||||
"#define INT_LEAST16_MAX (32767)\n"
|
||||
"#define INT_LEAST32_MAX (2147483647)\n"
|
||||
"#define INT_LEAST64_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define UINT_LEAST8_MAX (255)\n"
|
||||
"#define UINT_LEAST16_MAX (65535)\n"
|
||||
"#define UINT_LEAST32_MAX (4294967295U)\n"
|
||||
"#define UINT_LEAST64_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INT_FAST8_MIN (-128)\n"
|
||||
"#define INT_FAST16_MIN (-9223372036854775808L)\n"
|
||||
"#define INT_FAST32_MIN (-9223372036854775808L)\n"
|
||||
"#define INT_FAST64_MIN (-9223372036854775808L)\n"
|
||||
"\n"
|
||||
"#define INT_FAST8_MAX (127)\n"
|
||||
"#define INT_FAST16_MAX (9223372036854775807L)\n"
|
||||
"#define INT_FAST32_MAX (9223372036854775807L)\n"
|
||||
"#define INT_FAST64_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define UINT_FAST8_MAX (255)\n"
|
||||
"#define UINT_FAST16_MAX (18446744073709551615UL)\n"
|
||||
"#define UINT_FAST32_MAX (18446744073709551615UL)\n"
|
||||
"#define UINT_FAST64_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INTPTR_MIN (-9223372036854775808L)\n"
|
||||
"#define INTPTR_MAX (9223372036854775807L)\n"
|
||||
"#define UINTPTR_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INTMAX_MIN (-9223372036854775808L)\n"
|
||||
"#define INTMAX_MAX (9223372036854775807L)\n"
|
||||
"#define UINTMAX_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define PTRDIFF_MIN (-9223372036854775808L)\n"
|
||||
"#define PTRDIFF_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define SIZE_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"/* For signed wchar_t and wint_t: */\n"
|
||||
"#define WCHAR_MIN INT32_MIN\n"
|
||||
"#define WCHAR_MAX INT32_MAX\n"
|
||||
"#define WINT_MIN WCHAR_MIN\n"
|
||||
"#define WINT_MAX WCHAR_MAX\n"
|
||||
"\n"
|
||||
"#define INT8_C(value) value\n"
|
||||
"#define INT16_C(value) value\n"
|
||||
"#define INT32_C(value) value\n"
|
||||
"#define INT64_C(value) value##L\n"
|
||||
"\n"
|
||||
"#define UINT8_C(value) value\n"
|
||||
"#define UINT16_C(value) value\n"
|
||||
"#define UINT32_C(value) value##U\n"
|
||||
"#define UINT64_C(value) value##UL\n"
|
||||
"\n"
|
||||
"#define INTMAX_C(value) value##L\n"
|
||||
"#define UINTMAX_C(value) value##UL\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef _STDINT_H */\n";
|
@ -0,0 +1,401 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2018-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
x86_64 ABI target specific code.
|
||||
*/
|
||||
|
||||
/* See https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf. We use MIR_T_UNDEF for
|
||||
MEMORY. */
|
||||
|
||||
enum add_arg_class { NO_CLASS = MIR_T_BOUND + 1, X87UP_CLASS };
|
||||
|
||||
#ifndef _WIN32
|
||||
#define MAX_QWORDS 2
|
||||
#else
|
||||
#define MAX_QWORDS 1
|
||||
#endif
|
||||
|
||||
static MIR_type_t get_result_type (MIR_type_t arg_type1, MIR_type_t arg_type2) {
|
||||
if (arg_type1 == arg_type2) return arg_type1;
|
||||
if ((enum add_arg_class) arg_type1 == NO_CLASS) return arg_type2;
|
||||
if ((enum add_arg_class) arg_type2 == NO_CLASS) return arg_type1;
|
||||
|
||||
if (arg_type1 == MIR_T_UNDEF || arg_type2 == MIR_T_UNDEF) return MIR_T_UNDEF;
|
||||
|
||||
if (arg_type1 == MIR_T_I64 || arg_type1 == MIR_T_I32 || arg_type2 == MIR_T_I64
|
||||
|| arg_type2 == MIR_T_I32)
|
||||
return MIR_T_I64;
|
||||
|
||||
if (arg_type1 == MIR_T_LD || arg_type2 == MIR_T_LD
|
||||
|| (enum add_arg_class) arg_type1 == X87UP_CLASS
|
||||
|| (enum add_arg_class) arg_type2 == X87UP_CLASS)
|
||||
return MIR_T_UNDEF;
|
||||
|
||||
return MIR_T_D;
|
||||
}
|
||||
|
||||
static int classify_arg (c2m_ctx_t c2m_ctx, struct type *type, MIR_type_t types[MAX_QWORDS],
|
||||
int bit_field_p) {
|
||||
size_t size = type_size (c2m_ctx, type);
|
||||
int i, n_el_qwords, n_qwords = (size + 7) / 8;
|
||||
MIR_type_t mir_type;
|
||||
|
||||
if (type->mode == TM_STRUCT || type->mode == TM_UNION || type->mode == TM_ARR) {
|
||||
MIR_type_t subtypes[MAX_QWORDS];
|
||||
|
||||
if (n_qwords > MAX_QWORDS) return 0; /* too big aggregate */
|
||||
|
||||
#ifndef _WIN32
|
||||
for (i = 0; i < n_qwords; i++) types[i] = (MIR_type_t) NO_CLASS;
|
||||
|
||||
switch (type->mode) {
|
||||
case TM_ARR: { /* Arrays are handled as small records. */
|
||||
n_el_qwords = classify_arg (c2m_ctx, type->u.arr_type->el_type, subtypes, FALSE);
|
||||
if (n_el_qwords == 0) return 0;
|
||||
/* make full types: */
|
||||
for (i = 0; i < n_qwords; i++)
|
||||
types[i] = get_result_type (types[i], subtypes[i % n_el_qwords]);
|
||||
break;
|
||||
}
|
||||
case TM_STRUCT:
|
||||
case TM_UNION:
|
||||
for (node_t el = NL_HEAD (NL_EL (type->u.tag_type->u.ops, 1)->u.ops); el != NULL;
|
||||
el = NL_NEXT (el))
|
||||
if (el->code == N_MEMBER) {
|
||||
decl_t decl = el->attr;
|
||||
int start_qword = decl->offset / 8;
|
||||
|
||||
if (decl->bit_offset >= 0) {
|
||||
types[start_qword] = get_result_type (MIR_T_I64, types[start_qword]);
|
||||
} else {
|
||||
n_el_qwords
|
||||
= classify_arg (c2m_ctx, decl->decl_spec.type, subtypes, decl->bit_offset >= 0);
|
||||
if (n_el_qwords == 0) return 0;
|
||||
for (i = 0; i < n_el_qwords && (i + start_qword) < n_qwords; i++)
|
||||
types[i + start_qword] = get_result_type (subtypes[i], types[i + start_qword]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: assert (FALSE);
|
||||
}
|
||||
|
||||
if (n_qwords > 2) return 0; /* as we don't have vector values (see SSEUP_CLASS) */
|
||||
|
||||
for (i = 0; i < n_qwords; i++) {
|
||||
if (types[i] == MIR_T_UNDEF) return 0; /* pass in memory if a word class is memory. */
|
||||
if ((enum add_arg_class) types[i] == X87UP_CLASS && (i == 0 || types[i - 1] != MIR_T_LD))
|
||||
return 0;
|
||||
}
|
||||
return n_qwords;
|
||||
#else
|
||||
types[0] = MIR_T_I64;
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
assert (scalar_type_p (type));
|
||||
switch (mir_type = get_mir_type (c2m_ctx, type)) {
|
||||
case MIR_T_F:
|
||||
case MIR_T_D: types[0] = MIR_T_D; return 1;
|
||||
case MIR_T_LD:
|
||||
types[0] = MIR_T_LD;
|
||||
types[1] = (MIR_type_t) X87UP_CLASS;
|
||||
return 2;
|
||||
default: types[0] = MIR_T_I64; return 1;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct target_arg_info {
|
||||
int n_iregs, n_fregs;
|
||||
} target_arg_info_t;
|
||||
|
||||
static void target_init_arg_vars (c2m_ctx_t c2m_ctx, target_arg_info_t *arg_info) {
|
||||
arg_info->n_iregs = arg_info->n_fregs = 0;
|
||||
}
|
||||
|
||||
static void update_last_qword_type (c2m_ctx_t c2m_ctx, struct type *type,
|
||||
MIR_type_t qword_types[MAX_QWORDS], int n) {
|
||||
size_t last_size, size = type_size (c2m_ctx, type);
|
||||
MIR_type_t mir_type;
|
||||
|
||||
assert (n != 0);
|
||||
if ((last_size = size % 8) == 0 || n > 1) return;
|
||||
mir_type = qword_types[n - 1];
|
||||
if (last_size <= 4 && mir_type == MIR_T_D) qword_types[n - 1] = MIR_T_F;
|
||||
if (last_size <= 4 && mir_type == MIR_T_I64)
|
||||
qword_types[n - 1] = last_size <= 1 ? MIR_T_I8 : last_size <= 2 ? MIR_T_I16 : MIR_T_I32;
|
||||
}
|
||||
|
||||
static int process_ret_type (c2m_ctx_t c2m_ctx, struct type *ret_type,
|
||||
MIR_type_t qword_types[MAX_QWORDS]) {
|
||||
MIR_type_t type;
|
||||
int n, n_iregs, n_fregs, n_stregs, curr;
|
||||
int n_qwords = classify_arg (c2m_ctx, ret_type, qword_types, FALSE);
|
||||
|
||||
if (ret_type->mode != TM_STRUCT && ret_type->mode != TM_UNION) return 0;
|
||||
if (n_qwords != 0) {
|
||||
update_last_qword_type (c2m_ctx, ret_type, qword_types, n_qwords);
|
||||
n_iregs = n_fregs = n_stregs = curr = 0;
|
||||
for (n = 0; n < n_qwords; n++) { /* start from the last qword */
|
||||
type = qword_types[n];
|
||||
qword_types[curr++] = type;
|
||||
switch ((int) type) {
|
||||
case MIR_T_I8:
|
||||
case MIR_T_I16:
|
||||
case MIR_T_I32:
|
||||
case MIR_T_I64: n_iregs++; break;
|
||||
case MIR_T_F:
|
||||
case MIR_T_D: n_fregs++; break;
|
||||
case MIR_T_LD: n_stregs++; break;
|
||||
case X87UP_CLASS:
|
||||
n_qwords--;
|
||||
curr--;
|
||||
break;
|
||||
default: assert (FALSE);
|
||||
}
|
||||
}
|
||||
if (n_iregs > 2 || n_fregs > 2 || n_stregs > 1) n_qwords = 0;
|
||||
}
|
||||
return n_qwords;
|
||||
}
|
||||
|
||||
static int target_return_by_addr_p (c2m_ctx_t c2m_ctx, struct type *ret_type) {
|
||||
MIR_type_t qword_types[MAX_QWORDS];
|
||||
int n_qwords;
|
||||
|
||||
if (void_type_p (ret_type)) return FALSE;
|
||||
n_qwords = process_ret_type (c2m_ctx, ret_type, qword_types);
|
||||
return n_qwords == 0 && (ret_type->mode == TM_STRUCT || ret_type->mode == TM_UNION);
|
||||
}
|
||||
|
||||
static void target_add_res_proto (c2m_ctx_t c2m_ctx, struct type *ret_type,
|
||||
target_arg_info_t *arg_info, VARR (MIR_type_t) * res_types,
|
||||
VARR (MIR_var_t) * arg_vars) {
|
||||
MIR_var_t var;
|
||||
MIR_type_t type;
|
||||
MIR_type_t qword_types[MAX_QWORDS];
|
||||
int n, n_qwords;
|
||||
|
||||
if (void_type_p (ret_type)) return;
|
||||
n_qwords = process_ret_type (c2m_ctx, ret_type, qword_types);
|
||||
if (n_qwords != 0) {
|
||||
for (n = 0; n < n_qwords; n++)
|
||||
VARR_PUSH (MIR_type_t, res_types, promote_mir_int_type (qword_types[n]));
|
||||
} else if (ret_type->mode != TM_STRUCT && ret_type->mode != TM_UNION) {
|
||||
type = get_mir_type (c2m_ctx, ret_type);
|
||||
VARR_PUSH (MIR_type_t, res_types, type);
|
||||
} else { /* return by reference */
|
||||
var.name = RET_ADDR_NAME;
|
||||
var.type = MIR_T_RBLK;
|
||||
var.size = type_size (c2m_ctx, ret_type);
|
||||
VARR_PUSH (MIR_var_t, arg_vars, var);
|
||||
arg_info->n_iregs++;
|
||||
}
|
||||
}
|
||||
|
||||
static int target_add_call_res_op (c2m_ctx_t c2m_ctx, struct type *ret_type,
|
||||
target_arg_info_t *arg_info, size_t call_arg_area_offset) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
MIR_type_t type;
|
||||
MIR_type_t qword_types[MAX_QWORDS];
|
||||
op_t temp;
|
||||
int i, n_qwords;
|
||||
|
||||
if (void_type_p (ret_type)) return -1;
|
||||
n_qwords = process_ret_type (c2m_ctx, ret_type, qword_types);
|
||||
if (n_qwords != 0) {
|
||||
for (i = 0; i < n_qwords; i++) {
|
||||
temp = get_new_temp (c2m_ctx, promote_mir_int_type (qword_types[i]));
|
||||
VARR_PUSH (MIR_op_t, call_ops, temp.mir_op);
|
||||
}
|
||||
return n_qwords;
|
||||
} else if (ret_type->mode == TM_STRUCT || ret_type->mode == TM_UNION) { /* return by reference */
|
||||
arg_info->n_iregs++;
|
||||
temp = get_new_temp (c2m_ctx, MIR_T_I64);
|
||||
emit3 (c2m_ctx, MIR_ADD, temp.mir_op,
|
||||
MIR_new_reg_op (ctx, MIR_reg (ctx, FP_NAME, curr_func->u.func)),
|
||||
MIR_new_int_op (ctx, call_arg_area_offset));
|
||||
temp.mir_op
|
||||
= MIR_new_mem_op (ctx, MIR_T_RBLK, type_size (c2m_ctx, ret_type), temp.mir_op.u.reg, 0, 1);
|
||||
VARR_PUSH (MIR_op_t, call_ops, temp.mir_op);
|
||||
return 0;
|
||||
} else {
|
||||
type = get_mir_type (c2m_ctx, ret_type);
|
||||
type = promote_mir_int_type (type);
|
||||
temp = get_new_temp (c2m_ctx, type);
|
||||
VARR_PUSH (MIR_op_t, call_ops, temp.mir_op);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static op_t target_gen_post_call_res_code (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res,
|
||||
MIR_insn_t call, size_t call_ops_start) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
MIR_type_t type;
|
||||
MIR_insn_t insn;
|
||||
MIR_type_t qword_types[MAX_QWORDS];
|
||||
int i, n_qwords;
|
||||
|
||||
if (void_type_p (ret_type)) return res;
|
||||
n_qwords = process_ret_type (c2m_ctx, ret_type, qword_types);
|
||||
if (n_qwords != 0) {
|
||||
assert (res.mir_op.mode == MIR_OP_MEM);
|
||||
for (i = 0; i < n_qwords; i++) {
|
||||
type = qword_types[i];
|
||||
insn = MIR_new_insn (ctx, tp_mov (type),
|
||||
MIR_new_mem_op (ctx, type, res.mir_op.u.mem.disp + 8 * i,
|
||||
res.mir_op.u.mem.base, res.mir_op.u.mem.index,
|
||||
res.mir_op.u.mem.scale),
|
||||
VARR_GET (MIR_op_t, call_ops, i + call_ops_start + 2));
|
||||
MIR_append_insn (ctx, curr_func, insn);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void target_add_ret_ops (c2m_ctx_t c2m_ctx, struct type *ret_type, op_t res) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
MIR_type_t type;
|
||||
MIR_type_t qword_types[MAX_QWORDS];
|
||||
MIR_insn_t insn;
|
||||
MIR_reg_t ret_addr_reg;
|
||||
op_t temp, var;
|
||||
int i, size, n_qwords;
|
||||
|
||||
if (void_type_p (ret_type)) return;
|
||||
n_qwords = process_ret_type (c2m_ctx, ret_type, qword_types);
|
||||
if (n_qwords != 0) {
|
||||
for (i = 0; i < n_qwords; i++) {
|
||||
type = qword_types[i];
|
||||
temp = get_new_temp (c2m_ctx, promote_mir_int_type (type));
|
||||
insn = MIR_new_insn (ctx, tp_mov (type), temp.mir_op,
|
||||
MIR_new_mem_op (ctx, type, res.mir_op.u.mem.disp + 8 * i,
|
||||
res.mir_op.u.mem.base, res.mir_op.u.mem.index,
|
||||
res.mir_op.u.mem.scale));
|
||||
MIR_append_insn (ctx, curr_func, insn);
|
||||
VARR_PUSH (MIR_op_t, ret_ops, temp.mir_op);
|
||||
}
|
||||
} else if (ret_type->mode != TM_STRUCT && ret_type->mode != TM_UNION) {
|
||||
VARR_PUSH (MIR_op_t, ret_ops, res.mir_op);
|
||||
} else {
|
||||
ret_addr_reg = MIR_reg (ctx, RET_ADDR_NAME, curr_func->u.func);
|
||||
var = new_op (NULL, MIR_new_mem_op (ctx, MIR_T_I8, 0, ret_addr_reg, 0, 1));
|
||||
size = type_size (c2m_ctx, ret_type);
|
||||
block_move (c2m_ctx, var, res, size);
|
||||
}
|
||||
}
|
||||
|
||||
static int process_aggregate_arg (c2m_ctx_t c2m_ctx, struct type *arg_type,
|
||||
target_arg_info_t *arg_info, MIR_type_t qword_types[MAX_QWORDS]) {
|
||||
MIR_type_t type;
|
||||
int n, n_iregs, n_fregs, n_qwords = classify_arg (c2m_ctx, arg_type, qword_types, FALSE);
|
||||
|
||||
if (n_qwords == 0) return 0;
|
||||
if (arg_type->mode != TM_STRUCT && arg_type->mode != TM_UNION) return 0;
|
||||
update_last_qword_type (c2m_ctx, arg_type, qword_types, n_qwords);
|
||||
n_iregs = n_fregs = 0;
|
||||
for (n = 0; n < n_qwords; n++) { /* start from the last qword */
|
||||
switch ((int) (type = qword_types[n])) {
|
||||
case MIR_T_I8:
|
||||
case MIR_T_I16:
|
||||
case MIR_T_I32:
|
||||
case MIR_T_I64: n_iregs++; break;
|
||||
case MIR_T_F:
|
||||
case MIR_T_D: n_fregs++; break;
|
||||
case X87UP_CLASS:
|
||||
case MIR_T_LD: return 0;
|
||||
default: assert (FALSE);
|
||||
}
|
||||
}
|
||||
if (arg_info->n_iregs + n_iregs > 6 || arg_info->n_fregs + n_fregs > 8) return 0;
|
||||
/* aggregate passed by value: update arg_info */
|
||||
arg_info->n_iregs += n_iregs;
|
||||
arg_info->n_fregs += n_fregs;
|
||||
return n_qwords;
|
||||
}
|
||||
|
||||
static MIR_type_t get_blk_type (int n_qwords, MIR_type_t *qword_types) {
|
||||
int n, n_iregs = 0, n_fregs = 0;
|
||||
|
||||
assert (n_qwords <= 2);
|
||||
if (n_qwords == 0) return MIR_T_BLK;
|
||||
for (n = 0; n < n_qwords; n++) { /* start from the last qword */
|
||||
switch ((int) qword_types[n]) {
|
||||
case MIR_T_I8:
|
||||
case MIR_T_I16:
|
||||
case MIR_T_I32:
|
||||
case MIR_T_I64: n_iregs++; break;
|
||||
case MIR_T_F:
|
||||
case MIR_T_D: n_fregs++; break;
|
||||
case X87UP_CLASS:
|
||||
case MIR_T_LD: return MIR_T_BLK;
|
||||
default: assert (FALSE);
|
||||
}
|
||||
}
|
||||
if (n_iregs == n_qwords) return MIR_T_BLK + 1;
|
||||
if (n_fregs == n_qwords) return MIR_T_BLK + 2;
|
||||
if (qword_types[0] == MIR_T_F || qword_types[0] == MIR_T_D) return MIR_T_BLK + 4;
|
||||
return MIR_T_BLK + 3;
|
||||
}
|
||||
|
||||
static MIR_type_t target_get_blk_type (c2m_ctx_t c2m_ctx, struct type *arg_type) {
|
||||
MIR_type_t qword_types[MAX_QWORDS];
|
||||
int n_qwords = classify_arg (c2m_ctx, arg_type, qword_types, FALSE);
|
||||
assert (arg_type->mode == TM_STRUCT || arg_type->mode == TM_UNION);
|
||||
return get_blk_type (n_qwords, qword_types);
|
||||
}
|
||||
|
||||
static void target_add_arg_proto (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type,
|
||||
target_arg_info_t *arg_info, VARR (MIR_var_t) * arg_vars) {
|
||||
MIR_var_t var;
|
||||
MIR_type_t type;
|
||||
MIR_type_t qword_types[MAX_QWORDS];
|
||||
int n_qwords = process_aggregate_arg (c2m_ctx, arg_type, arg_info, qword_types);
|
||||
|
||||
/* pass aggregates on the stack and pass by value for others: */
|
||||
var.name = name;
|
||||
if (arg_type->mode != TM_STRUCT && arg_type->mode != TM_UNION) {
|
||||
type = get_mir_type (c2m_ctx, arg_type);
|
||||
var.type = type;
|
||||
if (type == MIR_T_F || type == MIR_T_D)
|
||||
arg_info->n_fregs++;
|
||||
else if (type != MIR_T_LD)
|
||||
arg_info->n_iregs++;
|
||||
} else {
|
||||
var.type = get_blk_type (n_qwords, qword_types);
|
||||
var.size = type_size (c2m_ctx, arg_type);
|
||||
}
|
||||
VARR_PUSH (MIR_var_t, arg_vars, var);
|
||||
}
|
||||
|
||||
static void target_add_call_arg_op (c2m_ctx_t c2m_ctx, struct type *arg_type,
|
||||
target_arg_info_t *arg_info, op_t arg) {
|
||||
gen_ctx_t gen_ctx = c2m_ctx->gen_ctx;
|
||||
MIR_context_t ctx = c2m_ctx->ctx;
|
||||
MIR_type_t type;
|
||||
MIR_type_t qword_types[MAX_QWORDS];
|
||||
int n_qwords = process_aggregate_arg (c2m_ctx, arg_type, arg_info, qword_types);
|
||||
|
||||
/* pass aggregates on the stack and pass by value for others: */
|
||||
if (arg_type->mode != TM_STRUCT && arg_type->mode != TM_UNION) {
|
||||
type = get_mir_type (c2m_ctx, arg_type);
|
||||
VARR_PUSH (MIR_op_t, call_ops, arg.mir_op);
|
||||
if (type == MIR_T_F || type == MIR_T_D)
|
||||
arg_info->n_fregs++;
|
||||
else if (type != MIR_T_LD)
|
||||
arg_info->n_iregs++;
|
||||
} else {
|
||||
assert (arg.mir_op.mode == MIR_OP_MEM);
|
||||
arg = mem_to_address (c2m_ctx, arg, TRUE);
|
||||
type = get_blk_type (n_qwords, qword_types);
|
||||
VARR_PUSH (MIR_op_t, call_ops,
|
||||
MIR_new_mem_op (ctx, type, type_size (c2m_ctx, arg_type), arg.mir_op.u.reg, 0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
static int target_gen_gather_arg (c2m_ctx_t c2m_ctx, const char *name, struct type *arg_type,
|
||||
decl_t param_decl, target_arg_info_t *arg_info) {
|
||||
return FALSE;
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2019-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 5.2.4.2.2 */
|
||||
static char float_str[]
|
||||
= "#ifndef __FLOAT_H\n"
|
||||
"#define __FLOAT_H\n"
|
||||
"\n"
|
||||
"#define FLT_RADIX 2\n"
|
||||
"\n"
|
||||
"#define FLT_MANT_DIG 24\n"
|
||||
"#define DBL_MANT_DIG 53\n"
|
||||
"#define LDBL_MANT_DIG DBL_MANT_DIG\n"
|
||||
"\n"
|
||||
"#define FLT_DECIMAL_DIG 9\n"
|
||||
"#define DBL_DECIMAL_DIG 17\n"
|
||||
"#define LDBL_DECIMAL_DIG DBL_DECIMAL_DIG\n"
|
||||
"#define FLT_DIG FLT_DECIMAL_DIG\n"
|
||||
"#define DBL_DIG DBL_DECIMAL_DIG\n"
|
||||
"#define LDBL_DIG LDBL_DECIMAL_DIG\n"
|
||||
"\n"
|
||||
"#define DECIMAL_DIG LDBL_DECIMAL_DIG\n"
|
||||
"\n"
|
||||
"#define FLT_MIN_EXP -125\n"
|
||||
"#define DBL_MIN_EXP -1021\n"
|
||||
"#define LDBL_MIN_EXP DBL_MIN_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MIN_10_EXP -37\n"
|
||||
"#define DBL_MIN_10_EXP -307\n"
|
||||
"#define LDBL_MIN_10_EXP DBL_MIN_10_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX_EXP 128\n"
|
||||
"#define DBL_MAX_EXP 1024\n"
|
||||
"#define LDBL_MAX_EXP DBL_MAX_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX_10_EXP 38\n"
|
||||
"#define DBL_MAX_10_EXP 308\n"
|
||||
"#define LDBL_MAX_10_EXP DBL_MAX_10_EXP\n"
|
||||
"\n"
|
||||
"#define FLT_MAX 0x1.fffffep+127\n"
|
||||
"#define DBL_MAX 0x1.fffffffffffffp+1023\n"
|
||||
"#define LDBL_MAX DBL_MAX\n"
|
||||
"\n"
|
||||
"#define FLT_EPSILON 0x1p-23\n"
|
||||
"#define DBL_EPSILON 0x1p-52\n"
|
||||
"#define LDBL_EPSILON DBL_EPSILON\n"
|
||||
"\n"
|
||||
"#define FLT_MIN 0x1p-126\n"
|
||||
"#define DBL_MIN 0x1p-1022\n"
|
||||
"#define LDBL_MIN DBL_MIN\n"
|
||||
"\n"
|
||||
"#define FLT_TRUE_MIN 0x1p-149\n"
|
||||
"#define DBL_TRUE_MIN 0x0.0000000000001p-1022\n"
|
||||
"#define LDBL_TRUE_MIN DBL_TRUE_MIN\n"
|
||||
"\n"
|
||||
"#define FLT_EVAL_METHOD 0\n"
|
||||
"#define FLT_ROUNDS 1 /* round to the nearest */\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __FLOAT_H */\n";
|
@ -0,0 +1,48 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2019-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See 5.2.4.2 */
|
||||
static char limits_str[]
|
||||
= "#ifndef __LIMITS_H\n"
|
||||
"#define __LIMITS_H\n"
|
||||
"\n"
|
||||
"#define CHAR_BIT 8\n"
|
||||
"\n"
|
||||
"#define SCHAR_MIN (-SCHAR_MAX - 1)\n"
|
||||
"#define SCHAR_MAX 127\n"
|
||||
"#define UCHAR_MAX (SCHAR_MAX * 2 + 1)\n"
|
||||
"\n"
|
||||
"#define MB_LEN_MAX 1\n"
|
||||
"\n"
|
||||
"#define SHRT_MIN (-SHRT_MAX - 1)\n"
|
||||
"#define SHRT_MAX 32767\n"
|
||||
"#define USHRT_MAX (SHRT_MAX * 2 + 1)\n"
|
||||
"\n"
|
||||
"#define INT_MIN (-INT_MAX - 1)\n"
|
||||
"#define INT_MAX 2147483647\n"
|
||||
"#define UINT_MAX (INT_MAX * 2u + 1u)\n"
|
||||
"\n"
|
||||
#if defined(_WIN32)
|
||||
"#define LONG_MIN (-LONG_MAX - 1l)\n"
|
||||
"#define LONG_MAX 2147483647l\n"
|
||||
"#define ULONG_MAX (LONG_MAX * 2ul + 1ul)\n"
|
||||
"\n"
|
||||
"#define LLONG_MIN (-LLONG_MAX - 1ll)\n"
|
||||
"#define LLONG_MAX 9223372036854775807ll\n"
|
||||
"#define ULLONG_MAX (LLONG_MAX * 2ull + 1ull)\n"
|
||||
#else
|
||||
"#define LONG_MIN (-LONG_MAX - 1l)\n"
|
||||
"#define LONG_MAX 9223372036854775807l\n"
|
||||
"#define ULONG_MAX (LONG_MAX * 2ul + 1ul)\n"
|
||||
"\n"
|
||||
"#define LLONG_MIN (-LLONG_MAX - 1ll)\n"
|
||||
"#define LLONG_MAX 9223372036854775807ll\n"
|
||||
"#define ULLONG_MAX (LLONG_MAX * 2ull + 1ull)\n"
|
||||
#endif
|
||||
"\n"
|
||||
"/* signed char by default */\n"
|
||||
"#define CHAR_MIN SCHAR_MIN\n"
|
||||
"#define CHAR_MAX SCHAR_MAX\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __LIMITS_H */\n";
|
@ -0,0 +1,41 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2019-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.16 and https://www.uclibc.org/docs/psABI-x86_64.pdf */
|
||||
static char stdarg_str[]
|
||||
= "#ifndef __STDARG_H\n"
|
||||
"#define __STDARG_H\n"
|
||||
"\n"
|
||||
#if defined(__APPLE__)
|
||||
"typedef __darwin_va_list va_list;\n"
|
||||
#elif defined(__WIN32)
|
||||
"typedef char *va_list;\n"
|
||||
#else
|
||||
"typedef struct {\n"
|
||||
" unsigned int gp_offset;\n"
|
||||
" unsigned int fp_offset;\n"
|
||||
" void *overflow_arg_area;\n"
|
||||
" void *reg_save_area;\n"
|
||||
"} va_list[1];\n"
|
||||
#endif
|
||||
"\n"
|
||||
#if defined(__WIN32)
|
||||
"#define va_start(ap, param) __va_start (ap, param)\n"
|
||||
#else
|
||||
"#define va_start(ap, param) __builtin_va_start (ap)\n"
|
||||
#endif
|
||||
"#define va_arg(ap, type) __builtin_va_arg(ap, (type *) 0)\n"
|
||||
"#define va_end(ap) 0\n"
|
||||
#if defined(__APPLE__) || defined(__WIN32)
|
||||
"#define va_copy(dest, src) ((dest) = (src))\n"
|
||||
#else
|
||||
"#define va_copy(dest, src) ((dest)[0] = (src)[0])\n"
|
||||
#endif
|
||||
"\n"
|
||||
"/* For standard headers of a GNU system: */\n"
|
||||
"#ifndef __GNUC_VA_LIST\n"
|
||||
"#define __GNUC_VA_LIST 1\n"
|
||||
"#endif\n"
|
||||
"typedef va_list __gnuc_va_list;\n"
|
||||
"#endif /* #ifndef __STDARG_H */\n";
|
@ -0,0 +1,32 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2019-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.19 */
|
||||
static char stddef_str[]
|
||||
= "#ifndef __STDDEF_H\n"
|
||||
"#define __STDDEF_H\n"
|
||||
"\n"
|
||||
#ifdef _WIN32
|
||||
"typedef long long int ptrdiff_t;\n"
|
||||
"typedef unsigned long long size_t;\n"
|
||||
#else
|
||||
"typedef long ptrdiff_t;\n"
|
||||
"typedef unsigned long size_t;\n"
|
||||
#endif
|
||||
"typedef long double max_align_t;\n"
|
||||
#if defined(__APPLE__)
|
||||
"typedef int wchar_t;\n"
|
||||
#elif defined(_WIN32)
|
||||
"typedef unsigned short wchar_t;\n"
|
||||
#else
|
||||
"typedef unsigned int wchar_t;\n"
|
||||
#endif
|
||||
"\n"
|
||||
#if !defined(__APPLE__) && !defined(_WIN32)
|
||||
"#define NULL ((void *) 0)\n"
|
||||
#endif
|
||||
"\n"
|
||||
"#define offsetof(type, member_designator) ((size_t) & ((type *) 0)->member_designator)\n"
|
||||
"\n"
|
||||
"#endif /* #ifndef __STDDEF_H */\n";
|
@ -0,0 +1,175 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2019-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
/* See C11 7.20 */
|
||||
static char stdint_str[]
|
||||
= "#ifndef _STDINT_H\n"
|
||||
"#define _STDINT_H 1\n"
|
||||
"\n"
|
||||
"typedef signed char int8_t;\n"
|
||||
"typedef short int int16_t;\n"
|
||||
"typedef int int32_t;\n"
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
"typedef long long int int64_t;\n"
|
||||
#else
|
||||
"typedef long int int64_t;\n"
|
||||
#endif
|
||||
"\n"
|
||||
"typedef unsigned char uint8_t;\n"
|
||||
"typedef unsigned short int uint16_t;\n"
|
||||
"typedef unsigned int uint32_t;\n"
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
"typedef unsigned long long int uint64_t;\n"
|
||||
#else
|
||||
"typedef unsigned long int uint64_t;\n"
|
||||
#endif
|
||||
"\n"
|
||||
"typedef signed char int_least8_t;\n"
|
||||
"typedef short int int_least16_t;\n"
|
||||
"typedef int int_least32_t;\n"
|
||||
#if defined(_WIN32)
|
||||
"typedef long long int int_least64_t;\n"
|
||||
#else
|
||||
"typedef long int int_least64_t;\n"
|
||||
#endif
|
||||
"\n"
|
||||
"typedef unsigned char uint_least8_t;\n"
|
||||
"typedef unsigned short int uint_least16_t;\n"
|
||||
"typedef unsigned int uint_least32_t;\n"
|
||||
#if defined(_WIN32)
|
||||
"typedef unsigned long long int uint_least64_t;\n"
|
||||
#else
|
||||
"typedef unsigned long int uint_least64_t;\n"
|
||||
#endif
|
||||
"\n"
|
||||
"typedef signed char int_fast8_t;\n"
|
||||
"typedef long int int_fast16_t;\n"
|
||||
"typedef long int int_fast32_t;\n"
|
||||
#if defined(_WIN32)
|
||||
"typedef long long int int_fast64_t;\n"
|
||||
#else
|
||||
"typedef long int int_fast64_t;\n"
|
||||
#endif
|
||||
"\n"
|
||||
"typedef unsigned char uint_fast8_t;\n"
|
||||
"typedef unsigned long int uint_fast16_t;\n"
|
||||
"typedef unsigned long int uint_fast32_t;\n"
|
||||
#if defined(_WIN32)
|
||||
"typedef unsigned long long int uint_fast64_t;\n"
|
||||
#else
|
||||
"typedef unsigned long int uint_fast64_t;\n"
|
||||
#endif
|
||||
"\n"
|
||||
"#define __intptr_t_defined\n"
|
||||
#if defined(_WIN32)
|
||||
"typedef long long int intptr_t;\n"
|
||||
"typedef unsigned long long int uintptr_t;\n"
|
||||
"\n"
|
||||
"typedef long long int intmax_t;\n"
|
||||
"typedef unsigned long long int uintmax_t;\n"
|
||||
"\n"
|
||||
"#define __INT64_C(c) c##LL\n"
|
||||
"#define __UINT64_C(c) c##ULL\n"
|
||||
#else
|
||||
"typedef long int intptr_t;\n"
|
||||
"typedef unsigned long int uintptr_t;\n"
|
||||
"\n"
|
||||
"typedef long int intmax_t;\n"
|
||||
"typedef unsigned long int uintmax_t;\n"
|
||||
"\n"
|
||||
"#define __INT64_C(c) c##L\n"
|
||||
"#define __UINT64_C(c) c##UL\n"
|
||||
#endif
|
||||
"\n"
|
||||
"#define INT8_MIN (-128)\n"
|
||||
"#define INT16_MIN (-32768)\n"
|
||||
"#define INT32_MIN (-2147483648)\n"
|
||||
"#define INT64_MIN (-9223372036854775808l)\n"
|
||||
"\n"
|
||||
"#define INT8_MAX (127)\n"
|
||||
"#define INT16_MAX (32767)\n"
|
||||
"#define INT32_MAX (2147483647)\n"
|
||||
"#define INT64_MAX (9223372036854775807l)\n"
|
||||
"\n"
|
||||
"#define UINT8_MAX (255)\n"
|
||||
"#define UINT16_MAX (65535)\n"
|
||||
"#define UINT32_MAX (4294967295u)\n"
|
||||
"#define UINT64_MAX (18446744073709551615ul)\n"
|
||||
"\n"
|
||||
"#define INT_LEAST8_MIN (-128)\n"
|
||||
"#define INT_LEAST16_MIN (-32768)\n"
|
||||
"#define INT_LEAST32_MIN (-2147483648)\n"
|
||||
"#define INT_LEAST64_MIN (-9223372036854775808L)\n"
|
||||
"\n"
|
||||
"#define INT_LEAST8_MAX (127)\n"
|
||||
"#define INT_LEAST16_MAX (32767)\n"
|
||||
"#define INT_LEAST32_MAX (2147483647)\n"
|
||||
"#define INT_LEAST64_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define UINT_LEAST8_MAX (255)\n"
|
||||
"#define UINT_LEAST16_MAX (65535)\n"
|
||||
"#define UINT_LEAST32_MAX (4294967295U)\n"
|
||||
"#define UINT_LEAST64_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INT_FAST8_MIN (-128)\n"
|
||||
"#define INT_FAST16_MIN (-9223372036854775808L)\n"
|
||||
"#define INT_FAST32_MIN (-9223372036854775808L)\n"
|
||||
"#define INT_FAST64_MIN (-9223372036854775808L)\n"
|
||||
"\n"
|
||||
"#define INT_FAST8_MAX (127)\n"
|
||||
"#define INT_FAST16_MAX (9223372036854775807L)\n"
|
||||
"#define INT_FAST32_MAX (9223372036854775807L)\n"
|
||||
"#define INT_FAST64_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define UINT_FAST8_MAX (255)\n"
|
||||
"#define UINT_FAST16_MAX (18446744073709551615UL)\n"
|
||||
"#define UINT_FAST32_MAX (18446744073709551615UL)\n"
|
||||
"#define UINT_FAST64_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INTPTR_MIN (-9223372036854775808L)\n"
|
||||
"#define INTPTR_MAX (9223372036854775807L)\n"
|
||||
"#define UINTPTR_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define INTMAX_MIN (-9223372036854775808L)\n"
|
||||
"#define INTMAX_MAX (9223372036854775807L)\n"
|
||||
"#define UINTMAX_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"#define PTRDIFF_MIN (-9223372036854775808L)\n"
|
||||
"#define PTRDIFF_MAX (9223372036854775807L)\n"
|
||||
"\n"
|
||||
"#define SIZE_MAX (18446744073709551615UL)\n"
|
||||
"\n"
|
||||
"/* For signed wchar_t and wint_t: */\n"
|
||||
"#define WCHAR_MIN INT32_MIN\n"
|
||||
"#define WCHAR_MAX INT32_MAX\n"
|
||||
"#define WINT_MIN WCHAR_MIN\n"
|
||||
"#define WINT_MAX WCHAR_MAX\n"
|
||||
"\n"
|
||||
"#define INT8_C(value) value\n"
|
||||
"#define INT16_C(value) value\n"
|
||||
"#define INT32_C(value) value\n"
|
||||
#if defined(_WIN32)
|
||||
"#define INT64_C(value) value##LL\n"
|
||||
#else
|
||||
"#define INT64_C(value) value##L\n"
|
||||
#endif
|
||||
"\n"
|
||||
"#define UINT8_C(value) value\n"
|
||||
"#define UINT16_C(value) value\n"
|
||||
"#define UINT32_C(value) value##U\n"
|
||||
#if defined(_WIN32)
|
||||
"#define UINT64_C(value) value##ULL\n"
|
||||
#else
|
||||
"#define UINT64_C(value) value##UL\n"
|
||||
#endif
|
||||
"\n"
|
||||
#if defined(_WIN32)
|
||||
"#define INTMAX_C(value) value##L\n"
|
||||
"#define UINTMAX_C(value) value##UL\n"
|
||||
#else
|
||||
"#define INTMAX_C(value) value##LL\n"
|
||||
"#define UINTMAX_C(value) value##ULL\n"
|
||||
#endif
|
||||
"\n"
|
||||
"#endif /* #ifndef _STDINT_H */\n";
|
@ -0,0 +1,116 @@
|
||||
/* This file is a part of MIR project.
|
||||
Copyright (C) 2019-2021 Vladimir Makarov <vmakarov.gcc@gmail.com>.
|
||||
*/
|
||||
|
||||
static char x86_64_mirc[]
|
||||
= "#define __amd64 1\n"
|
||||
"#define __amd64__ 1\n"
|
||||
"#define __x86_64 1\n"
|
||||
"#define __x86_64__ 1\n"
|
||||
"#define _M_AMD64 1\n"
|
||||
"#define _M_X64 1\n"
|
||||
"\n"
|
||||
"#define __SIZEOF_DOUBLE__ 8\n"
|
||||
"#define __SIZEOF_FLOAT__ 4\n"
|
||||
"#define __SIZEOF_INT__ 4\n"
|
||||
#if !defined(_WIN32) && __SIZEOF_LONG_DOUBLE__ == 16
|
||||
"#define __SIZEOF_LONG_DOUBLE__ 16\n"
|
||||
#else
|
||||
"#define __SIZEOF_LONG_DOUBLE__ 8\n"
|
||||
#endif
|
||||
"#define __SIZEOF_LONG_LONG__ 8\n"
|
||||
"#define __SIZEOF_LONG__ 4\n"
|
||||
"#define __SIZEOF_POINTER__ 8\n"
|
||||
"#define __SIZEOF_PTRDIFF_T__ 8\n"
|
||||
"#define __SIZEOF_SHORT__ 2\n"
|
||||
"#define __SIZEOF_SIZE_T__ 8\n"
|
||||
"\n"
|
||||
"#define __BYTE_ORDER__ 1234\n"
|
||||
"#define __ORDER_LITTLE_ENDIAN__ 1234\n"
|
||||
"#define __ORDER_BIG_ENDIAN__ 4321\n"
|
||||
"\n"
|
||||
"/* Some type macros: */\n"
|
||||
"#define __SIZE_TYPE__ long long unsigned int\n"
|
||||
"#define __PTRDIFF_TYPE__ long long int\n"
|
||||
"#define __INTMAX_TYPE__ long long int\n"
|
||||
"#define __UINTMAX_TYPE__ long long unsigned int\n"
|
||||
"#define __INT8_TYPE__ signed char\n"
|
||||
"#define __INT16_TYPE__ short\n"
|
||||
"#define __INT32_TYPE__ int\n"
|
||||
"#define __INT64_TYPE__ long long int\n"
|
||||
"#define __UINT8_TYPE__ unsigned char\n"
|
||||
"#define __UINT16_TYPE__ unsigned short\n"
|
||||
"#define __UINT32_TYPE__ unsigned int\n"
|
||||
"#define __UINT64_TYPE__ long long unsigned int\n"
|
||||
"#define __INTPTR_TYPE__ long long int\n"
|
||||
"#define __UINTPTR_TYPE__ long long unsigned int\n"
|
||||
"\n"
|
||||
"#define __int8 __INT8_TYPE__\n"
|
||||
"#define __int16 __INT16_TYPE__\n"
|
||||
"#define __int32 __INT32_TYPE__\n"
|
||||
"#define __int64 __INT64_TYPE__\n"
|
||||
"\n"
|
||||
"#define __ptr32\n"
|
||||
"#define __ptr64\n"
|
||||
"#define __forceinline inline\n"
|
||||
"#define __cdecl\n"
|
||||
"#define __pragma(p)\n"
|
||||
"#define __declspec(attr)\n"
|
||||
"#define __unaligned\n"
|
||||
"\n"
|
||||
"#define __CHAR_BIT__ 8\n"
|
||||
"#define __INT8_MAX__ 127\n"
|
||||
"#define __INT16_MAX__ 32767\n"
|
||||
"#define __INT32_MAX__ 2147483647\n"
|
||||
"#define __INT64_MAX__ 9223372036854775807LL\n"
|
||||
"#define __UINT8_MAX__ (__INT8_MAX__ * 2u + 1u)\n"
|
||||
"#define __UINT16_MAX__ (__INT16_MAX__ * 2u + 1u)\n"
|
||||
"#define __UINT32_MAX__ (__INT32_MAX__ * 2u + 1u)\n"
|
||||
"#define __UINT64_MAX__ (__INT64_MAX__ * 2u + 1u)\n"
|
||||
"#define __SCHAR_MAX__ __INT8_MAX__\n"
|
||||
"#define __SHRT_MAX__ __INT16_MAX__\n"
|
||||
"#define __INT_MAX__ __INT32_MAX__\n"
|
||||
"#define __LONG_MAX__ __INT32_MAX__\n"
|
||||
"#define __LONG_LONG_MAX__ __INT64_MAX__\n"
|
||||
"#define __SIZE_MAX__ __UINT64_MAX__\n"
|
||||
"#define __PTRDIFF_MAX__ __INT64_MAX__\n"
|
||||
"#define __INTMAX_MAX__ __INT64_MAX__\n"
|
||||
"#define __UINTMAX_MAX__ __UINT64_MAX__\n"
|
||||
"#define __INTPTR_MAX__ __INT64_MAX__\n"
|
||||
"#define __UINTPTR_MAX__ __UINT64_MAX__\n"
|
||||
"\n"
|
||||
"#define __FLT_MIN_EXP__ (-125)\n"
|
||||
"#define __FLT_MAX_EXP__ 128\n"
|
||||
"#define __FLT_DIG__ 6\n"
|
||||
"#define __FLT_DECIMAL_DIG__ 9\n"
|
||||
"#define __FLT_MANT_DIG__ 24\n"
|
||||
"#define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F\n"
|
||||
"#define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F\n"
|
||||
"#define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F\n"
|
||||
"\n"
|
||||
"#define __DBL_MIN_EXP__ (-1021)\n"
|
||||
"#define __DBL_MAX_EXP__ 1024\n"
|
||||
"#define __DBL_DIG__ 15\n"
|
||||
"#define __DBL_DECIMAL_DIG__ 17\n"
|
||||
"#define __DBL_MANT_DIG__ 53\n"
|
||||
"#define __DBL_MAX__ ((double) 1.79769313486231570814527423731704357e+308L)\n"
|
||||
"#define __DBL_MIN__ ((double) 2.22507385850720138309023271733240406e-308L)\n"
|
||||
"#define __DBL_EPSILON__ ((double) 2.22044604925031308084726333618164062e-16L)\n"
|
||||
"\n"
|
||||
"typedef unsigned short char16_t;\n"
|
||||
"typedef unsigned int char32_t;\n"
|
||||
"\n"
|
||||
"#define WIN32 1\n"
|
||||
"#define _WIN32 1\n"
|
||||
"#define __WIN32 1\n"
|
||||
"#define __WIN32__ 1\n"
|
||||
"#define WIN64 1\n"
|
||||
"#define _WIN64 1\n"
|
||||
"#define __WIN64 1\n"
|
||||
"#define __WIN64__ 1\n"
|
||||
"#define WINNT 1\n"
|
||||
"#define __WINNT 1\n"
|
||||
"#define __WINNT__ 1\n"
|
||||
"#define __MSVCRT__ 1\n"
|
||||
"\n"
|
||||
"void *alloca (long long unsigned);\n";
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,11 @@
|
||||
These patches are for Lua 5.3 and 5.4.
|
||||
|
||||
The 'defer' patch adds the defer statement to Lua.
|
||||
|
||||
Note that in Lua 5.4 versions prior to 5.4.3 a deferred closure may be called more than once
|
||||
just as the close method of a to-be-closed variable may be called more than once, when exiting the scope.
|
||||
|
||||
I think this is fixed in Lua 5.4.3.
|
||||
|
||||
The original patch for 5.4 is applicable to versions prior to 5.4.3.
|
||||
The 5.4.3 version has a new approach to the implementation of toclose values, hence a new patch had to be created.
|
@ -0,0 +1,974 @@
|
||||
Index: testes/all.lua
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- testes/all.lua (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ testes/all.lua (date 1594850137246)
|
||||
@@ -184,6 +184,7 @@
|
||||
dofile('bitwise.lua')
|
||||
assert(dofile('verybig.lua', true) == 10); collectgarbage()
|
||||
dofile('files.lua')
|
||||
+dofile('defer.lua')
|
||||
|
||||
if #msgs > 0 then
|
||||
print("\ntests not performed:")
|
||||
Index: ldo.h
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- ldo.h (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ ldo.h (date 1594850124117)
|
||||
@@ -53,6 +53,7 @@
|
||||
|
||||
LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
|
||||
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
|
||||
+LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
|
||||
|
||||
#endif
|
||||
|
||||
Index: ldo.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- ldo.c (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ ldo.c (date 1594850137277)
|
||||
@@ -88,7 +88,7 @@
|
||||
};
|
||||
|
||||
|
||||
-static void seterrorobj (lua_State *L, int errcode, StkId oldtop) {
|
||||
+void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {
|
||||
switch (errcode) {
|
||||
case LUA_ERRMEM: { /* memory error? */
|
||||
setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */
|
||||
@@ -98,6 +98,10 @@
|
||||
setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
|
||||
break;
|
||||
}
|
||||
+ case CLOSEPROTECT: {
|
||||
+ setnilvalue(oldtop); /* no error message */
|
||||
+ break;
|
||||
+ }
|
||||
default: {
|
||||
setobjs2s(L, oldtop, L->top - 1); /* error message on current top */
|
||||
break;
|
||||
@@ -114,6 +118,7 @@
|
||||
}
|
||||
else { /* thread has no error handler */
|
||||
global_State *g = G(L);
|
||||
+ errcode = luaF_close(L, L->stack, errcode); /* close all upvalues */
|
||||
L->status = cast_byte(errcode); /* mark it as dead */
|
||||
if (g->mainthread->errorJmp) { /* main thread has a handler? */
|
||||
setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */
|
||||
@@ -121,7 +126,7 @@
|
||||
}
|
||||
else { /* no handler at all; abort */
|
||||
if (g->panic) { /* panic function? */
|
||||
- seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */
|
||||
+ luaD_seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */
|
||||
if (L->ci->top < L->top)
|
||||
L->ci->top = L->top; /* pushing msg. can break this invariant */
|
||||
lua_unlock(L);
|
||||
@@ -584,8 +589,8 @@
|
||||
if (ci == NULL) return 0; /* no recovery point */
|
||||
/* "finish" luaD_pcall */
|
||||
oldtop = restorestack(L, ci->extra);
|
||||
- luaF_close(L, oldtop);
|
||||
- seterrorobj(L, status, oldtop);
|
||||
+ luaF_close(L, oldtop, status);
|
||||
+ luaD_seterrorobj(L, status, oldtop);
|
||||
L->ci = ci;
|
||||
L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */
|
||||
L->nny = 0; /* should be zero to be yieldable */
|
||||
@@ -662,19 +667,17 @@
|
||||
L->nny = 0; /* allow yields */
|
||||
api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
|
||||
status = luaD_rawrunprotected(L, resume, &nargs);
|
||||
- if (status == -1) /* error calling 'lua_resume'? */
|
||||
- status = LUA_ERRRUN;
|
||||
- else { /* continue running after recoverable errors */
|
||||
- while (errorstatus(status) && recover(L, status)) {
|
||||
- /* unroll continuation */
|
||||
- status = luaD_rawrunprotected(L, unroll, &status);
|
||||
- }
|
||||
- if (errorstatus(status)) { /* unrecoverable error? */
|
||||
- L->status = cast_byte(status); /* mark thread as 'dead' */
|
||||
- seterrorobj(L, status, L->top); /* push error message */
|
||||
- L->ci->top = L->top;
|
||||
- }
|
||||
- else lua_assert(status == L->status); /* normal end or yield */
|
||||
+ /* continue running after recoverable errors */
|
||||
+ while (errorstatus(status) && recover(L, status)) {
|
||||
+ /* unroll continuation */
|
||||
+ status = luaD_rawrunprotected(L, unroll, &status);
|
||||
+ }
|
||||
+ if (!errorstatus(status))
|
||||
+ lua_assert(status == L->status); /* normal end or yield */
|
||||
+ else { /* unrecoverable error */
|
||||
+ L->status = cast_byte(status); /* mark thread as 'dead' */
|
||||
+ luaD_seterrorobj(L, status, L->top); /* push error message */
|
||||
+ L->ci->top = L->top;
|
||||
}
|
||||
L->nny = oldnny; /* restore 'nny' */
|
||||
L->nCcalls--;
|
||||
@@ -729,11 +732,12 @@
|
||||
status = luaD_rawrunprotected(L, func, u);
|
||||
if (status != LUA_OK) { /* an error occurred? */
|
||||
StkId oldtop = restorestack(L, old_top);
|
||||
- luaF_close(L, oldtop); /* close possible pending closures */
|
||||
- seterrorobj(L, status, oldtop);
|
||||
L->ci = old_ci;
|
||||
L->allowhook = old_allowhooks;
|
||||
L->nny = old_nny;
|
||||
+ status = luaF_close(L, oldtop, status); /* close possible pending closures */
|
||||
+ oldtop = restorestack(L, old_top);
|
||||
+ luaD_seterrorobj(L, status, oldtop);
|
||||
luaD_shrinkstack(L);
|
||||
}
|
||||
L->errfunc = old_errfunc;
|
||||
Index: lfunc.h
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lfunc.h (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ lfunc.h (date 1594850137293)
|
||||
@@ -34,7 +34,8 @@
|
||||
*/
|
||||
struct UpVal {
|
||||
TValue *v; /* points to stack or to its own value */
|
||||
- lu_mem refcount; /* reference counter */
|
||||
+ unsigned int refcount; /* reference counter */
|
||||
+ unsigned int flags; /* Used to mark deferred values */
|
||||
union {
|
||||
struct { /* (when open) */
|
||||
UpVal *next; /* linked list */
|
||||
@@ -46,13 +47,22 @@
|
||||
|
||||
#define upisopen(up) ((up)->v != &(up)->u.value)
|
||||
|
||||
+/*
|
||||
+** Special "status" for 'luaF_close'
|
||||
+*/
|
||||
+
|
||||
+/* close upvalues without running their closing methods */
|
||||
+#define NOCLOSINGMETH (-1)
|
||||
+
|
||||
+/* close upvalues running all closing methods in protected mode */
|
||||
+#define CLOSEPROTECT (-2)
|
||||
|
||||
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
|
||||
LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems);
|
||||
LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems);
|
||||
LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl);
|
||||
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
|
||||
-LUAI_FUNC void luaF_close (lua_State *L, StkId level);
|
||||
+LUAI_FUNC int luaF_close (lua_State *L, StkId level, int status);
|
||||
LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);
|
||||
LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,
|
||||
int pc);
|
||||
Index: lstate.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lstate.c (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ lstate.c (date 1594850137347)
|
||||
@@ -241,7 +241,7 @@
|
||||
|
||||
static void close_state (lua_State *L) {
|
||||
global_State *g = G(L);
|
||||
- luaF_close(L, L->stack); /* close all upvalues for this thread */
|
||||
+ luaF_close(L, L->stack, CLOSEPROTECT); /* close all upvalues for this thread */
|
||||
luaC_freeallobjects(L); /* collect all objects */
|
||||
if (g->version) /* closing a fully built state? */
|
||||
luai_userstateclose(L);
|
||||
@@ -284,13 +284,33 @@
|
||||
|
||||
void luaE_freethread (lua_State *L, lua_State *L1) {
|
||||
LX *l = fromstate(L1);
|
||||
- luaF_close(L1, L1->stack); /* close all upvalues for this thread */
|
||||
+ luaF_close(L1, L1->stack, NOCLOSINGMETH); /* close all upvalues for this thread */
|
||||
lua_assert(L1->openupval == NULL);
|
||||
luai_userstatefree(L, L1);
|
||||
freestack(L1);
|
||||
luaM_free(L, l);
|
||||
}
|
||||
|
||||
+int lua_resetthread (lua_State *L) {
|
||||
+ CallInfo *ci;
|
||||
+ int status;
|
||||
+ lua_lock(L);
|
||||
+ L->ci = ci = &L->base_ci; /* unwind CallInfo list */
|
||||
+ setnilvalue(L->stack); /* 'function' entry for basic 'ci' */
|
||||
+ ci->func = L->stack;
|
||||
+ ci->callstatus = 0;
|
||||
+ status = luaF_close(L, L->stack, CLOSEPROTECT);
|
||||
+ if (status != CLOSEPROTECT) /* real errors? */
|
||||
+ luaD_seterrorobj(L, status, L->stack + 1);
|
||||
+ else {
|
||||
+ status = LUA_OK;
|
||||
+ L->top = L->stack + 1;
|
||||
+ }
|
||||
+ ci->top = L->top + LUA_MINSTACK;
|
||||
+ L->status = status;
|
||||
+ lua_unlock(L);
|
||||
+ return status;
|
||||
+}
|
||||
|
||||
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
|
||||
int i;
|
||||
Index: lfunc.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lfunc.c (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ lfunc.c (date 1594850137293)
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
+#include "ldo.h"
|
||||
#include "lfunc.h"
|
||||
#include "lgc.h"
|
||||
#include "lmem.h"
|
||||
@@ -61,13 +62,15 @@
|
||||
lua_assert(isintwups(L) || L->openupval == NULL);
|
||||
while (*pp != NULL && (p = *pp)->v >= level) {
|
||||
lua_assert(upisopen(p));
|
||||
- if (p->v == level) /* found a corresponding upvalue? */
|
||||
- return p; /* return it */
|
||||
+ if (p->v == level && !p->flags) /* found a corresponding upvalue that is not a deferred value? */ {
|
||||
+ return p; /* return it */
|
||||
+ }
|
||||
pp = &p->u.open.next;
|
||||
}
|
||||
/* not found: create a new upvalue */
|
||||
uv = luaM_new(L, UpVal);
|
||||
uv->refcount = 0;
|
||||
+ uv->flags = 0;
|
||||
uv->u.open.next = *pp; /* link it to list of open upvalues */
|
||||
uv->u.open.touched = 1;
|
||||
*pp = uv;
|
||||
@@ -79,20 +82,84 @@
|
||||
return uv;
|
||||
}
|
||||
|
||||
+static void calldeferred(lua_State *L, void *ud) {
|
||||
+ UNUSED(ud);
|
||||
+ luaD_callnoyield(L, L->top - 2, 0);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+** Prepare deferred function plus its arguments for object 'obj' with
|
||||
+** error message 'err'. (This function assumes EXTRA_STACK.)
|
||||
+*/
|
||||
+static int preparetocall(lua_State *L, TValue *func, TValue *err) {
|
||||
+ StkId top = L->top;
|
||||
+ setobj2s(L, top, func); /* will call deferred function */
|
||||
+ if (err) {
|
||||
+ setobj2s(L, top + 1, err); /* and error msg. as 1st argument */
|
||||
+ }
|
||||
+ else {
|
||||
+ setnilvalue(top + 1);
|
||||
+ }
|
||||
+ L->top = top + 2; /* add function and arguments */
|
||||
+ return 1;
|
||||
+}
|
||||
|
||||
-void luaF_close (lua_State *L, StkId level) {
|
||||
+/*
|
||||
+** Prepare and call a deferred function. If status is OK, code is still
|
||||
+** inside the original protected call, and so any error will be handled
|
||||
+** there. Otherwise, a previous error already activated the original
|
||||
+** protected call, and so the call to the deferred method must be
|
||||
+** protected here. (A status == -1 behaves like a previous
|
||||
+** error, to also run the closing method in protected mode).
|
||||
+** If status is OK, the call to the deferred method will be pushed
|
||||
+** at the top of the stack. Otherwise, values are pushed after
|
||||
+** the 'level' of the upvalue containing deferred function, as everything after
|
||||
+** that won't be used again.
|
||||
+*/
|
||||
+static int calldeferredfunction(lua_State *L, StkId level, int status) {
|
||||
+ TValue *uv = level; /* value being closed */
|
||||
+ if (status == LUA_OK) {
|
||||
+ preparetocall(L, uv, NULL); /* something to call? */
|
||||
+ calldeferred(L, NULL); /* call closing method */
|
||||
+ }
|
||||
+ else { /* must close the object in protected mode */
|
||||
+ ptrdiff_t oldtop;
|
||||
+ level++; /* space for error message */
|
||||
+ oldtop = savestack(L, level + 1); /* top will be after that */
|
||||
+ luaD_seterrorobj(L, status, level); /* set error message */
|
||||
+ preparetocall(L, uv, level);
|
||||
+ int newstatus = luaD_pcall(L, calldeferred, NULL, oldtop, 0);
|
||||
+ if (newstatus != LUA_OK && status == CLOSEPROTECT) /* first error? */
|
||||
+ status = newstatus; /* this will be the new error */
|
||||
+ else {
|
||||
+ /* leave original error (or nil) on top */
|
||||
+ L->top = restorestack(L, oldtop);
|
||||
+ }
|
||||
+ }
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
+int luaF_close (lua_State *L, StkId level, int status) {
|
||||
UpVal *uv;
|
||||
while (L->openupval != NULL && (uv = L->openupval)->v >= level) {
|
||||
lua_assert(upisopen(uv));
|
||||
L->openupval = uv->u.open.next; /* remove from 'open' list */
|
||||
- if (uv->refcount == 0) /* no references? */
|
||||
- luaM_free(L, uv); /* free upvalue */
|
||||
+ if (uv->refcount == 0) { /* no references? */
|
||||
+ UpVal uv1 = *uv; /* copy the upvalue as we will free it below */
|
||||
+ luaM_free(L, uv); /* free upvalue before invoking any deferred functions */
|
||||
+ if (status != NOCLOSINGMETH && uv1.flags && ttisfunction(uv1.v)) {
|
||||
+ ptrdiff_t levelrel = savestack(L, level);
|
||||
+ status = calldeferredfunction(L, uv1.v, status);
|
||||
+ level = restorestack(L, levelrel);
|
||||
+ }
|
||||
+ }
|
||||
else {
|
||||
setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */
|
||||
uv->v = &uv->u.value; /* now current value lives here */
|
||||
luaC_upvalbarrier(L, uv);
|
||||
}
|
||||
}
|
||||
+ return status;
|
||||
}
|
||||
|
||||
|
||||
Index: llex.h
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- llex.h (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ llex.h (date 1594850124176)
|
||||
@@ -27,7 +27,7 @@
|
||||
/* terminal symbols denoted by reserved words */
|
||||
TK_AND = FIRST_RESERVED, TK_BREAK,
|
||||
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
|
||||
- TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
|
||||
+ TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_DEFER, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
|
||||
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
|
||||
/* other terminal symbols */
|
||||
TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,
|
||||
Index: lparser.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lparser.c (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ lparser.c (date 1594850137347)
|
||||
@@ -52,6 +52,7 @@
|
||||
lu_byte nactvar; /* # active locals outside the block */
|
||||
lu_byte upval; /* true if some variable in the block is an upvalue */
|
||||
lu_byte isloop; /* true if 'block' is a loop */
|
||||
+ lu_byte insidetbc; /* true if inside the scope of a defer stmt (i.e. defer closure var) */
|
||||
} BlockCnt;
|
||||
|
||||
|
||||
@@ -442,6 +443,7 @@
|
||||
bl->firstlabel = fs->ls->dyd->label.n;
|
||||
bl->firstgoto = fs->ls->dyd->gt.n;
|
||||
bl->upval = 0;
|
||||
+ bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc);
|
||||
bl->previous = fs->bl;
|
||||
fs->bl = bl;
|
||||
lua_assert(fs->freereg == fs->nactvar);
|
||||
@@ -519,10 +521,17 @@
|
||||
** so that, if it invokes the GC, the GC knows which registers
|
||||
** are in use at that time.
|
||||
*/
|
||||
-static void codeclosure (LexState *ls, expdesc *v) {
|
||||
+static void codeclosure (LexState *ls, expdesc *v, int deferred) {
|
||||
FuncState *fs = ls->fs->prev;
|
||||
+ int pc = -1;
|
||||
+ if (deferred) {
|
||||
+ pc = luaK_codeABC(fs, OP_DEFER, 0, 0, 0);
|
||||
+ }
|
||||
init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1));
|
||||
luaK_exp2nextreg(fs, v); /* fix it at the last register */
|
||||
+ if (deferred) {
|
||||
+ SETARG_A(fs->f->code[pc], v->u.info);
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
@@ -780,24 +789,26 @@
|
||||
}
|
||||
|
||||
|
||||
-static void body (LexState *ls, expdesc *e, int ismethod, int line) {
|
||||
+static void body (LexState *ls, expdesc *e, int ismethod, int line, int deferred) {
|
||||
/* body -> '(' parlist ')' block END */
|
||||
FuncState new_fs;
|
||||
BlockCnt bl;
|
||||
new_fs.f = addprototype(ls);
|
||||
new_fs.f->linedefined = line;
|
||||
open_func(ls, &new_fs, &bl);
|
||||
- checknext(ls, '(');
|
||||
- if (ismethod) {
|
||||
- new_localvarliteral(ls, "self"); /* create 'self' parameter */
|
||||
- adjustlocalvars(ls, 1);
|
||||
- }
|
||||
- parlist(ls);
|
||||
- checknext(ls, ')');
|
||||
+ if (!deferred) {
|
||||
+ checknext(ls, '(');
|
||||
+ if (ismethod) {
|
||||
+ new_localvarliteral(ls, "self"); /* create 'self' parameter */
|
||||
+ adjustlocalvars(ls, 1);
|
||||
+ }
|
||||
+ parlist(ls);
|
||||
+ checknext(ls, ')');
|
||||
+ }
|
||||
statlist(ls);
|
||||
new_fs.f->lastlinedefined = ls->linenumber;
|
||||
check_match(ls, TK_END, TK_FUNCTION, line);
|
||||
- codeclosure(ls, e);
|
||||
+ codeclosure(ls, e, deferred);
|
||||
close_func(ls);
|
||||
}
|
||||
|
||||
@@ -972,7 +983,7 @@
|
||||
}
|
||||
case TK_FUNCTION: {
|
||||
luaX_next(ls);
|
||||
- body(ls, v, 0, ls->linenumber);
|
||||
+ body(ls, v, 0, ls->linenumber, 0);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
@@ -1429,12 +1440,19 @@
|
||||
}
|
||||
|
||||
|
||||
-static void localfunc (LexState *ls) {
|
||||
+static void localfunc (LexState *ls, int defer) {
|
||||
expdesc b;
|
||||
FuncState *fs = ls->fs;
|
||||
- new_localvar(ls, str_checkname(ls)); /* new local variable */
|
||||
+ if (defer) {
|
||||
+ static const char funcname[] = "(deferred function)";
|
||||
+ new_localvar(ls, luaX_newstring(ls, funcname, sizeof funcname-1)); /* new local variable */
|
||||
+ markupval(fs, fs->nactvar);
|
||||
+ fs->bl->insidetbc = 1; /* in the scope of a defer closure variable */
|
||||
+ } else {
|
||||
+ new_localvar(ls, str_checkname(ls)); /* new local variable */
|
||||
+ }
|
||||
adjustlocalvars(ls, 1); /* enter its scope */
|
||||
- body(ls, &b, 0, ls->linenumber); /* function created in next register */
|
||||
+ body(ls, &b, 0, ls->linenumber, defer); /* function created in next register */
|
||||
/* debug information will only see the variable after this point! */
|
||||
getlocvar(fs, b.u.info)->startpc = fs->pc;
|
||||
}
|
||||
@@ -1480,7 +1498,7 @@
|
||||
expdesc v, b;
|
||||
luaX_next(ls); /* skip FUNCTION */
|
||||
ismethod = funcname(ls, &v);
|
||||
- body(ls, &b, ismethod, line);
|
||||
+ body(ls, &b, ismethod, line, 0);
|
||||
luaK_storevar(ls->fs, &v, &b);
|
||||
luaK_fixline(ls->fs, line); /* definition "happens" in the first line */
|
||||
}
|
||||
@@ -1513,7 +1531,7 @@
|
||||
nret = explist(ls, &e); /* optional return values */
|
||||
if (hasmultret(e.k)) {
|
||||
luaK_setmultret(fs, &e);
|
||||
- if (e.k == VCALL && nret == 1) { /* tail call? */
|
||||
+ if (e.k == VCALL && nret == 1 && !fs->bl->insidetbc) { /* tail call? */
|
||||
SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL);
|
||||
lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar);
|
||||
}
|
||||
@@ -1572,10 +1590,15 @@
|
||||
case TK_LOCAL: { /* stat -> localstat */
|
||||
luaX_next(ls); /* skip LOCAL */
|
||||
if (testnext(ls, TK_FUNCTION)) /* local function? */
|
||||
- localfunc(ls);
|
||||
+ localfunc(ls, 0);
|
||||
else
|
||||
localstat(ls);
|
||||
break;
|
||||
+ }
|
||||
+ case TK_DEFER: { /* stat -> deferstat */
|
||||
+ luaX_next(ls); /* skip DEFER */
|
||||
+ localfunc(ls, 1);
|
||||
+ break;
|
||||
}
|
||||
case TK_DBCOLON: { /* stat -> label */
|
||||
luaX_next(ls); /* skip double colon */
|
||||
Index: llex.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- llex.c (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ llex.c (date 1594850124157)
|
||||
@@ -40,7 +40,7 @@
|
||||
static const char *const luaX_tokens [] = {
|
||||
"and", "break", "do", "else", "elseif",
|
||||
"end", "false", "for", "function", "goto", "if",
|
||||
- "in", "local", "nil", "not", "or", "repeat",
|
||||
+ "in", "local", "defer", "nil", "not", "or", "repeat",
|
||||
"return", "then", "true", "until", "while",
|
||||
"//", "..", "...", "==", ">=", "<=", "~=",
|
||||
"<<", ">>", "::", "<eof>",
|
||||
Index: testes/defer.lua
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- testes/defer.lua (date 1594849634130)
|
||||
+++ testes/defer.lua (date 1594849634130)
|
||||
@@ -0,0 +1,313 @@
|
||||
+-- ================================================================
|
||||
+-- Following section is an extract from the code.lua test
|
||||
+-- These functions test bytecode generation, and also provide
|
||||
+-- helper routines that we use later on in other test cases
|
||||
+
|
||||
+-- testing opcodes
|
||||
+function check (f, ...)
|
||||
+ if not T then
|
||||
+ return true
|
||||
+ end
|
||||
+ local arg = {...}
|
||||
+ local c = T.listcode(f)
|
||||
+ for i=1, #arg do
|
||||
+ --print(arg[i], c[i])
|
||||
+ opcodes_coverage[arg[i]] = opcodes_coverage[arg[i]]+1
|
||||
+ assert(string.find(c[i], '- '..arg[i]..' *[AB][xs]?=%d'))
|
||||
+ end
|
||||
+ assert(c[#arg+2] == nil)
|
||||
+end
|
||||
+
|
||||
+-- Test defer statement
|
||||
+do
|
||||
+ local y = 0
|
||||
+ local function x()
|
||||
+ defer y = y + 1 end
|
||||
+ defer y = y + 1 end
|
||||
+ end
|
||||
+ check(x, 'DEFER', 'CLOSURE', 'DEFER', 'CLOSURE', 'RETURN')
|
||||
+ x()
|
||||
+ assert(y == 2)
|
||||
+ print 'Test 1 OK'
|
||||
+end
|
||||
+
|
||||
+-- Test defer statement
|
||||
+do
|
||||
+ local y = 0
|
||||
+ local function x()
|
||||
+ defer y = y + 1 end
|
||||
+ error('raise error')
|
||||
+ defer y = y + 2 end -- will not be called
|
||||
+ end
|
||||
+ pcall(x)
|
||||
+ assert(y == 1)
|
||||
+ print 'Test 2 OK'
|
||||
+end
|
||||
+
|
||||
+-- Test defer statement
|
||||
+do
|
||||
+ local y = 0
|
||||
+ local function x()
|
||||
+ defer y = y + 1 end
|
||||
+ defer y = y + 2; error('err') end
|
||||
+ defer y = y + 3 end
|
||||
+ end
|
||||
+ pcall(x)
|
||||
+ assert(y == 6)
|
||||
+ print 'Test 3 OK'
|
||||
+end
|
||||
+
|
||||
+-- Test defer statement in tailcalls
|
||||
+do
|
||||
+ local y = 0
|
||||
+ local function x (n)
|
||||
+ defer y = y + 1 end
|
||||
+ if n > 0 then return x(n - 1) end
|
||||
+ end
|
||||
+ pcall(x, 3)
|
||||
+ assert(y == 4)
|
||||
+ print 'Test 4 OK'
|
||||
+end
|
||||
+
|
||||
+-- Simulate a test of resource closure with defer
|
||||
+do
|
||||
+ local y = 0
|
||||
+ local z = { count = 0 }
|
||||
+ z.__index = z;
|
||||
+ function z:new()
|
||||
+ local object = {}
|
||||
+ setmetatable(object, z)
|
||||
+ return object
|
||||
+ end
|
||||
+ function z:open(arg)
|
||||
+ if (arg) then
|
||||
+ z.count = z.count + 1
|
||||
+ return
|
||||
+ end
|
||||
+ y = 1
|
||||
+ error('error opening')
|
||||
+ end
|
||||
+ function z.close()
|
||||
+ z.count = z.count - 1
|
||||
+ end
|
||||
+ local function x(arg)
|
||||
+ local f = z:new()
|
||||
+ f:open(arg)
|
||||
+ assert(z.count == 1)
|
||||
+ defer f:close() end
|
||||
+ end
|
||||
+ x('filename')
|
||||
+ assert(y == 0)
|
||||
+ assert(z.count == 0)
|
||||
+ pcall(x, false)
|
||||
+ assert(z.count == 0)
|
||||
+ assert(y == 1)
|
||||
+ print 'Test 5 OK'
|
||||
+end
|
||||
+
|
||||
+--- Test stack reallocation in defer statement
|
||||
+do
|
||||
+ local function x(a) if a <= 0 then return else x(a-1) end end
|
||||
+ local y = 1000
|
||||
+ local function z(...)
|
||||
+ -- recursive call to make stack
|
||||
+ defer x(y) end
|
||||
+ return ...
|
||||
+ end
|
||||
+ do
|
||||
+ local a,b,c = z(1,2,3)
|
||||
+ assert(a == 1 and b == 2 and c == 3)
|
||||
+ a,b,c = z(3,2,1)
|
||||
+ assert(a == 3 and b == 2 and c == 1)
|
||||
+ end
|
||||
+ print 'Test 6 OK'
|
||||
+end
|
||||
+
|
||||
+-- Adapted from Lua 5.4
|
||||
+local function stack(n) n = ((n == 0) or stack(n - 1)) end
|
||||
+
|
||||
+local function func2close (f, x, y)
|
||||
+ local obj = setmetatable({}, {__close = f})
|
||||
+ if x then
|
||||
+ return x, obj, y
|
||||
+ else
|
||||
+ return obj
|
||||
+ end
|
||||
+end
|
||||
+
|
||||
+do
|
||||
+ local function t()
|
||||
+ local a = {}
|
||||
+ do
|
||||
+ local b = false -- not to be closed
|
||||
+ -- x is <close>
|
||||
+ local x = setmetatable({"x"}, {__close = function (self)
|
||||
+ a[#a + 1] = self[1] end})
|
||||
+ defer getmetatable(x).__close(x) end
|
||||
+ -- y is <close>
|
||||
+ local w, y, z = func2close(function (self, err)
|
||||
+ assert(err == nil); a[#a + 1] = "y"
|
||||
+ end, 10, 20)
|
||||
+ defer getmetatable(y).__close(y) end
|
||||
+ local c = nil -- not to be closed
|
||||
+ a[#a + 1] = "in"
|
||||
+ assert(w == 10 and z == 20)
|
||||
+ end
|
||||
+ a[#a + 1] = "out"
|
||||
+ assert(a[1] == "in" and a[2] == "y" and a[3] == "x" and a[4] == "out")
|
||||
+ end
|
||||
+ t()
|
||||
+ print 'Test 7 OK'
|
||||
+end
|
||||
+
|
||||
+do
|
||||
+ local function t()
|
||||
+ local X = false
|
||||
+
|
||||
+ local x, closescope = func2close(function () stack(10); X = true end, 100)
|
||||
+ assert(x == 100); x = 101; -- 'x' is not read-only
|
||||
+
|
||||
+ -- closing functions do not corrupt returning values
|
||||
+ local function foo (x)
|
||||
+ local _ = closescope
|
||||
+ defer getmetatable(_).__close(_) end
|
||||
+ return x, X, 23
|
||||
+ end
|
||||
+
|
||||
+ local a, b, c = foo(1.5)
|
||||
+ assert(a == 1.5 and b == false and c == 23 and X == true)
|
||||
+
|
||||
+ X = false
|
||||
+ foo = function (x)
|
||||
+ local _ = closescope
|
||||
+ defer getmetatable(_).__close(_) end
|
||||
+ local y = 15
|
||||
+ return y
|
||||
+ end
|
||||
+
|
||||
+ assert(foo() == 15 and X == true)
|
||||
+
|
||||
+ X = false
|
||||
+ foo = function ()
|
||||
+ local x = closescope
|
||||
+ defer getmetatable(x).__close(x) end
|
||||
+ return x
|
||||
+ end
|
||||
+
|
||||
+ assert(foo() == closescope and X == true)
|
||||
+ end
|
||||
+ t()
|
||||
+ print 'Test 8 OK'
|
||||
+end
|
||||
+
|
||||
+do
|
||||
+ local function t()
|
||||
+ -- calls cannot be tail in the scope of to-be-closed variables
|
||||
+ local X, Y
|
||||
+ local function foo ()
|
||||
+ local _ = func2close(function () Y = 10 end)
|
||||
+ defer getmetatable(_).__close(_) end
|
||||
+ assert(X == true and Y == nil) -- 'X' not closed yet
|
||||
+ return 1,2,3
|
||||
+ end
|
||||
+
|
||||
+ local function bar ()
|
||||
+ local _ = func2close(function () X = false end)
|
||||
+ defer getmetatable(_).__close(_) end
|
||||
+ X = true
|
||||
+ do
|
||||
+ return foo() -- not a tail call!
|
||||
+ end
|
||||
+ end
|
||||
+
|
||||
+ local a, b, c, d = bar()
|
||||
+ assert(a == 1 and b == 2 and c == 3 and X == false and Y == 10 and d == nil)
|
||||
+ return foo, bar
|
||||
+ end
|
||||
+ local f,b = t()
|
||||
+ print 'Test 9 OK'
|
||||
+end
|
||||
+
|
||||
+do
|
||||
+ local function t()
|
||||
+ -- an error in a wrapped coroutine closes variables
|
||||
+ local x = false
|
||||
+ local y = false
|
||||
+ local co = coroutine.wrap(function ()
|
||||
+ local xv = func2close(function () x = true end)
|
||||
+ defer getmetatable(xv).__close(xv) end
|
||||
+ do
|
||||
+ local yv = func2close(function () y = true end)
|
||||
+ defer getmetatable(yv).__close(yv) end
|
||||
+ coroutine.yield(100) -- yield doesn't close variable
|
||||
+ end
|
||||
+ coroutine.yield(200) -- yield doesn't close variable
|
||||
+ error(23) -- error does
|
||||
+ end)
|
||||
+
|
||||
+ local b = co()
|
||||
+ assert(b == 100 and not x and not y)
|
||||
+ b = co()
|
||||
+ assert(b == 200 and not x and y)
|
||||
+ local a, b = pcall(co)
|
||||
+ assert(not a and b == 23 and x and y)
|
||||
+ end
|
||||
+ t()
|
||||
+ print 'Test 10 OK'
|
||||
+end
|
||||
+
|
||||
+-- a suspended coroutine should not close its variables when collected
|
||||
+do
|
||||
+ function t()
|
||||
+ local co
|
||||
+ co = coroutine.wrap(function()
|
||||
+ -- should not run
|
||||
+ local x = func2close(function () os.exit(false) end)
|
||||
+ defer getmetatable(x).__close(x) end
|
||||
+ co = nil
|
||||
+ coroutine.yield()
|
||||
+ end)
|
||||
+ co() -- start coroutine
|
||||
+ assert(co == nil) -- eventually it will be collected
|
||||
+ collectgarbage()
|
||||
+ end
|
||||
+ t()
|
||||
+ print 'Test 11 OK'
|
||||
+end
|
||||
+
|
||||
+do
|
||||
+ local function t()
|
||||
+ -- error in a wrapped coroutine raising errors when closing a variable
|
||||
+ local x = 0
|
||||
+ local co = coroutine.wrap(function ()
|
||||
+ local xx = func2close(function () x = x + 1; error("@YYY") end)
|
||||
+ defer getmetatable(xx).__close(xx) end
|
||||
+ local xv = func2close(function () x = x + 1; error("@XXX") end)
|
||||
+ defer getmetatable(xv).__close(xv) end
|
||||
+ coroutine.yield(100)
|
||||
+ error(200)
|
||||
+ end)
|
||||
+ assert(co() == 100); assert(x == 0)
|
||||
+ local st, msg = pcall(co); assert(x == 2)
|
||||
+ assert(not st and msg == 200) -- should get first error raised
|
||||
+
|
||||
+ local x = 0
|
||||
+ local y = 0
|
||||
+ co = coroutine.wrap(function ()
|
||||
+ local xx = func2close(function () y = y + 1; error("YYY") end)
|
||||
+ defer getmetatable(xx).__close(xx) end
|
||||
+ local xv = func2close(function () x = x + 1; error("XXX") end)
|
||||
+ defer getmetatable(xv).__close(xv) end
|
||||
+ coroutine.yield(100)
|
||||
+ return 200
|
||||
+ end)
|
||||
+ assert(co() == 100); assert(x == 0)
|
||||
+ local st, msg = pcall(co)
|
||||
+ assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX"))
|
||||
+ assert(x == 1 and y == 1)
|
||||
+ end
|
||||
+ t()
|
||||
+ print 'Test 12 OK'
|
||||
+end
|
||||
+
|
||||
+print 'OK'
|
||||
Index: lopcodes.h
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lopcodes.h (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ lopcodes.h (date 1594850124198)
|
||||
@@ -230,11 +230,13 @@
|
||||
|
||||
OP_VARARG,/* A B R(A), R(A+1), ..., R(A+B-2) = vararg */
|
||||
|
||||
-OP_EXTRAARG/* Ax extra (larger) argument for previous opcode */
|
||||
+OP_EXTRAARG,/* Ax extra (larger) argument for previous opcode */
|
||||
+OP_DEFER /* A mark variable A "deferred" */
|
||||
+
|
||||
} OpCode;
|
||||
|
||||
|
||||
-#define NUM_OPCODES (cast(int, OP_EXTRAARG) + 1)
|
||||
+#define NUM_OPCODES (cast(int, OP_DEFER) + 1)
|
||||
|
||||
|
||||
|
||||
Index: lvm.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lvm.c (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ lvm.c (date 1594850137378)
|
||||
@@ -737,7 +737,7 @@
|
||||
/* execute a jump instruction */
|
||||
#define dojump(ci,i,e) \
|
||||
{ int a = GETARG_A(i); \
|
||||
- if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \
|
||||
+ if (a != 0) Protect(luaF_close(L, ci->u.l.base + a - 1, LUA_OK)); \
|
||||
ci->u.l.savedpc += GETARG_sBx(i) + e; }
|
||||
|
||||
/* for test instructions, execute the jump instruction that follows it */
|
||||
@@ -1159,7 +1159,7 @@
|
||||
StkId lim = nci->u.l.base + getproto(nfunc)->numparams;
|
||||
int aux;
|
||||
/* close all upvalues from previous call */
|
||||
- if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base);
|
||||
+ if (cl->p->sizep > 0) Protect(luaF_close(L, oci->u.l.base, NOCLOSINGMETH));
|
||||
/* move new frame into old one */
|
||||
for (aux = 0; nfunc + aux < lim; aux++)
|
||||
setobjs2s(L, ofunc + aux, nfunc + aux);
|
||||
@@ -1175,7 +1175,10 @@
|
||||
}
|
||||
vmcase(OP_RETURN) {
|
||||
int b = GETARG_B(i);
|
||||
- if (cl->p->sizep > 0) luaF_close(L, base);
|
||||
+ if (cl->p->sizep > 0) {
|
||||
+ Protect(luaF_close(L, base, LUA_OK));
|
||||
+ ra = RA(i);
|
||||
+ }
|
||||
b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra)));
|
||||
if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */
|
||||
return; /* external invocation: return */
|
||||
@@ -1313,6 +1316,12 @@
|
||||
vmcase(OP_EXTRAARG) {
|
||||
lua_assert(0);
|
||||
vmbreak;
|
||||
+ }
|
||||
+ vmcase(OP_DEFER) {
|
||||
+ UpVal *up = luaF_findupval(L, ra); /* create new upvalue */
|
||||
+ up->flags = 1; /* mark it as deferred */
|
||||
+ setnilvalue(ra); /* initialize it with nil */
|
||||
+ vmbreak;
|
||||
}
|
||||
}
|
||||
}
|
||||
Index: lcorolib.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lcorolib.c (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ lcorolib.c (date 1594850137262)
|
||||
@@ -75,8 +75,11 @@
|
||||
lua_State *co = lua_tothread(L, lua_upvalueindex(1));
|
||||
int r = auxresume(L, co, lua_gettop(L));
|
||||
if (r < 0) {
|
||||
+ int stat = lua_status(co);
|
||||
+ if (stat != LUA_OK && stat != LUA_YIELD)
|
||||
+ lua_resetthread(co); /* close variables in case of errors */
|
||||
if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */
|
||||
- luaL_where(L, 1); /* add extra info */
|
||||
+ luaL_where(L, 1); /* add extra info, if available */
|
||||
lua_insert(L, -2);
|
||||
lua_concat(L, 2);
|
||||
}
|
||||
Index: lua.h
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lua.h (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ lua.h (date 1594850137362)
|
||||
@@ -144,6 +144,7 @@
|
||||
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
|
||||
LUA_API void (lua_close) (lua_State *L);
|
||||
LUA_API lua_State *(lua_newthread) (lua_State *L);
|
||||
+LUA_API int (lua_resetthread) (lua_State *L);
|
||||
|
||||
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
|
||||
|
||||
Index: lopcodes.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lopcodes.c (revision e7411fab800e2cfa810a1ba296356532eabdde40)
|
||||
+++ lopcodes.c (date 1594850124178)
|
||||
@@ -65,6 +65,7 @@
|
||||
"CLOSURE",
|
||||
"VARARG",
|
||||
"EXTRAARG",
|
||||
+ "DEFER",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -119,6 +120,7 @@
|
||||
,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */
|
||||
,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */
|
||||
,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */
|
||||
- ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */
|
||||
+ ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */
|
||||
+ ,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_DEFER */
|
||||
};
|
||||
|
@ -0,0 +1,669 @@
|
||||
Index: lopnames.h
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lopnames.h (revision 170752d62751963767b93263989bac427d7c785f)
|
||||
+++ lopnames.h (date 1594983665385)
|
||||
@@ -93,6 +93,7 @@
|
||||
"TFORLOOP",
|
||||
"SETLIST",
|
||||
"CLOSURE",
|
||||
+ "DEFER",
|
||||
"VARARG",
|
||||
"VARARGPREP",
|
||||
"EXTRAARG",
|
||||
Index: lfunc.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lfunc.c (revision 170752d62751963767b93263989bac427d7c785f)
|
||||
+++ lfunc.c (date 1594987185491)
|
||||
@@ -91,7 +91,7 @@
|
||||
lua_assert(isintwups(L) || L->openupval == NULL);
|
||||
while ((p = *pp) != NULL && uplevel(p) >= level) { /* search for it */
|
||||
lua_assert(!isdead(G(L), p));
|
||||
- if (uplevel(p) == level) /* corresponding upvalue? */
|
||||
+ if (uplevel(p) == level && p->tbc != UV_FLAG_DEFER) /* corresponding upvalue? - not deferred */
|
||||
return p; /* return it */
|
||||
pp = &p->u.open.next;
|
||||
}
|
||||
@@ -99,6 +99,27 @@
|
||||
return newupval(L, 0, level, pp);
|
||||
}
|
||||
|
||||
+static void calldeferred(lua_State *L, void *ud) {
|
||||
+ UNUSED(ud);
|
||||
+ luaD_callnoyield(L, L->top - 2, 0);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+** Prepare deferred function plus its arguments for object 'obj' with
|
||||
+** error message 'err'. (This function assumes EXTRA_STACK.)
|
||||
+*/
|
||||
+static int preparetocall(lua_State *L, TValue *func, TValue *err) {
|
||||
+ StkId top = L->top;
|
||||
+ setobj2s(L, top, func); /* will call deferred function */
|
||||
+ if (err) {
|
||||
+ setobj2s(L, top + 1, err); /* and error msg. as 1st argument */
|
||||
+ }
|
||||
+ else {
|
||||
+ setnilvalue(s2v(top + 1));
|
||||
+ }
|
||||
+ L->top = top + 2; /* add function and arguments */
|
||||
+ return 1;
|
||||
+}
|
||||
|
||||
static void callclose (lua_State *L, void *ud) {
|
||||
UNUSED(ud);
|
||||
@@ -147,11 +168,15 @@
|
||||
** the 'level' of the upvalue being closed, as everything after
|
||||
** that won't be used again.
|
||||
*/
|
||||
-static int callclosemth (lua_State *L, StkId level, int status) {
|
||||
+static int callclosemth (lua_State *L, StkId level, int status, int tbc) {
|
||||
TValue *uv = s2v(level); /* value being closed */
|
||||
if (likely(status == LUA_OK)) {
|
||||
- if (prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */
|
||||
+ if (tbc == UV_FLAG_TBC && prepclosingmethod(L, uv, &G(L)->nilvalue)) /* something to call? */
|
||||
callclose(L, NULL); /* call closing method */
|
||||
+ else if (tbc == UV_FLAG_DEFER && ttisfunction(uv)) {
|
||||
+ preparetocall(L, uv, &G(L)->nilvalue);
|
||||
+ calldeferred(L, NULL);
|
||||
+ }
|
||||
else if (!l_isfalse(uv)) /* non-closable non-false value? */
|
||||
varerror(L, level, "attempt to close non-closable variable '%s'");
|
||||
}
|
||||
@@ -160,8 +185,16 @@
|
||||
level++; /* space for error message */
|
||||
oldtop = savestack(L, level + 1); /* top will be after that */
|
||||
luaD_seterrorobj(L, status, level); /* set error message */
|
||||
- if (prepclosingmethod(L, uv, s2v(level))) { /* something to call? */
|
||||
- int newstatus = luaD_pcall(L, callclose, NULL, oldtop, 0);
|
||||
+ int docall = 1;
|
||||
+ if (tbc == UV_FLAG_TBC) {
|
||||
+ docall = prepclosingmethod(L, uv, s2v(level));
|
||||
+ }
|
||||
+ else {
|
||||
+ lua_assert(tbc == UV_FLAG_DEFER);
|
||||
+ preparetocall(L, uv, s2v(level));
|
||||
+ }
|
||||
+ if (docall) { /* something to call? */
|
||||
+ int newstatus = luaD_pcall(L, tbc == UV_FLAG_TBC ? callclose: calldeferred, NULL, oldtop, 0);
|
||||
if (newstatus != LUA_OK && status == CLOSEPROTECT) /* first error? */
|
||||
status = newstatus; /* this will be the new error */
|
||||
else {
|
||||
@@ -228,7 +261,7 @@
|
||||
if (uv->tbc && status != NOCLOSINGMETH) {
|
||||
/* must run closing method, which may change the stack */
|
||||
ptrdiff_t levelrel = savestack(L, level);
|
||||
- status = callclosemth(L, uplevel(uv), status);
|
||||
+ status = callclosemth(L, uplevel(uv), status, uv->tbc);
|
||||
level = restorestack(L, levelrel);
|
||||
}
|
||||
luaF_unlinkupval(uv);
|
||||
Index: ljumptab.h
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- ljumptab.h (revision 170752d62751963767b93263989bac427d7c785f)
|
||||
+++ ljumptab.h (date 1594983953252)
|
||||
@@ -105,6 +105,7 @@
|
||||
&&L_OP_TFORLOOP,
|
||||
&&L_OP_SETLIST,
|
||||
&&L_OP_CLOSURE,
|
||||
+&&L_OP_DEFER,
|
||||
&&L_OP_VARARG,
|
||||
&&L_OP_VARARGPREP,
|
||||
&&L_OP_EXTRAARG
|
||||
Index: llex.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- llex.c (revision 170752d62751963767b93263989bac427d7c785f)
|
||||
+++ llex.c (date 1594983621522)
|
||||
@@ -40,7 +40,7 @@
|
||||
static const char *const luaX_tokens [] = {
|
||||
"and", "break", "do", "else", "elseif",
|
||||
"end", "false", "for", "function", "goto", "if",
|
||||
- "in", "local", "nil", "not", "or", "repeat",
|
||||
+ "in", "local", "defer", "nil", "not", "or", "repeat",
|
||||
"return", "then", "true", "until", "while",
|
||||
"//", "..", "...", "==", ">=", "<=", "~=",
|
||||
"<<", ">>", "::", "<eof>",
|
||||
Index: lopcodes.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lopcodes.c (revision 170752d62751963767b93263989bac427d7c785f)
|
||||
+++ lopcodes.c (date 1594984035037)
|
||||
@@ -97,6 +97,7 @@
|
||||
,opmode(0, 0, 0, 0, 1, iABx) /* OP_TFORLOOP */
|
||||
,opmode(0, 0, 1, 0, 0, iABC) /* OP_SETLIST */
|
||||
,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */
|
||||
+ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_DEFER */
|
||||
,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */
|
||||
,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */
|
||||
,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */
|
||||
Index: lparser.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lparser.c (revision 170752d62751963767b93263989bac427d7c785f)
|
||||
+++ lparser.c (date 1594983592571)
|
||||
@@ -709,10 +709,17 @@
|
||||
** are in use at that time.
|
||||
|
||||
*/
|
||||
-static void codeclosure (LexState *ls, expdesc *v) {
|
||||
+static void codeclosure (LexState *ls, expdesc *v, int deferred) {
|
||||
FuncState *fs = ls->fs->prev;
|
||||
+ int pc = -1;
|
||||
+ if (deferred) {
|
||||
+ pc = luaK_codeABC(fs, OP_DEFER, 0, 0, 0);
|
||||
+ }
|
||||
init_exp(v, VRELOC, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1));
|
||||
luaK_exp2nextreg(fs, v); /* fix it at the last register */
|
||||
+ if (deferred) {
|
||||
+ SETARG_A(fs->f->code[pc], v->u.info);
|
||||
+ }
|
||||
}
|
||||
|
||||
|
||||
@@ -977,24 +984,26 @@
|
||||
}
|
||||
|
||||
|
||||
-static void body (LexState *ls, expdesc *e, int ismethod, int line) {
|
||||
+static void body (LexState *ls, expdesc *e, int ismethod, int line, int deferred) {
|
||||
/* body -> '(' parlist ')' block END */
|
||||
FuncState new_fs;
|
||||
BlockCnt bl;
|
||||
new_fs.f = addprototype(ls);
|
||||
new_fs.f->linedefined = line;
|
||||
open_func(ls, &new_fs, &bl);
|
||||
- checknext(ls, '(');
|
||||
- if (ismethod) {
|
||||
- new_localvarliteral(ls, "self"); /* create 'self' parameter */
|
||||
- adjustlocalvars(ls, 1);
|
||||
- }
|
||||
- parlist(ls);
|
||||
- checknext(ls, ')');
|
||||
+ if (!deferred) {
|
||||
+ checknext(ls, '(');
|
||||
+ if (ismethod) {
|
||||
+ new_localvarliteral(ls, "self"); /* create 'self' parameter */
|
||||
+ adjustlocalvars(ls, 1);
|
||||
+ }
|
||||
+ parlist(ls);
|
||||
+ checknext(ls, ')');
|
||||
+ }
|
||||
statlist(ls);
|
||||
new_fs.f->lastlinedefined = ls->linenumber;
|
||||
check_match(ls, TK_END, TK_FUNCTION, line);
|
||||
- codeclosure(ls, e);
|
||||
+ codeclosure(ls, e, deferred);
|
||||
close_func(ls);
|
||||
}
|
||||
|
||||
@@ -1170,7 +1179,7 @@
|
||||
}
|
||||
case TK_FUNCTION: {
|
||||
luaX_next(ls);
|
||||
- body(ls, v, 0, ls->linenumber);
|
||||
+ body(ls, v, 0, ls->linenumber, 0);
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
@@ -1714,13 +1723,21 @@
|
||||
}
|
||||
|
||||
|
||||
-static void localfunc (LexState *ls) {
|
||||
+static void localfunc (LexState *ls, int defer) {
|
||||
expdesc b;
|
||||
FuncState *fs = ls->fs;
|
||||
int fvar = fs->nactvar; /* function's variable index */
|
||||
- new_localvar(ls, str_checkname(ls)); /* new local variable */
|
||||
+ if (defer) {
|
||||
+ static const char funcname[] = "(deferred function)";
|
||||
+ new_localvar(ls, luaX_newstring(ls, funcname, sizeof funcname-1)); /* new local variable */
|
||||
+ markupval(fs, fs->nactvar);
|
||||
+ fs->bl->insidetbc = 1; /* in the scope of a defer closure variable */
|
||||
+ }
|
||||
+ else {
|
||||
+ new_localvar(ls, str_checkname(ls)); /* new local variable */
|
||||
+ }
|
||||
adjustlocalvars(ls, 1); /* enter its scope */
|
||||
- body(ls, &b, 0, ls->linenumber); /* function created in next register */
|
||||
+ body(ls, &b, 0, ls->linenumber, defer); /* function created in next register */
|
||||
/* debug information will only see the variable after this point! */
|
||||
localdebuginfo(fs, fvar)->startpc = fs->pc;
|
||||
}
|
||||
@@ -1815,7 +1832,7 @@
|
||||
expdesc v, b;
|
||||
luaX_next(ls); /* skip FUNCTION */
|
||||
ismethod = funcname(ls, &v);
|
||||
- body(ls, &b, ismethod, line);
|
||||
+ body(ls, &b, ismethod, line, 0);
|
||||
luaK_storevar(ls->fs, &v, &b);
|
||||
luaK_fixline(ls->fs, line); /* definition "happens" in the first line */
|
||||
}
|
||||
@@ -1908,10 +1925,15 @@
|
||||
case TK_LOCAL: { /* stat -> localstat */
|
||||
luaX_next(ls); /* skip LOCAL */
|
||||
if (testnext(ls, TK_FUNCTION)) /* local function? */
|
||||
- localfunc(ls);
|
||||
+ localfunc(ls, 0);
|
||||
else
|
||||
localstat(ls);
|
||||
break;
|
||||
+ }
|
||||
+ case TK_DEFER: { /* stat -> deferstat */
|
||||
+ luaX_next(ls); /* skip DEFER */
|
||||
+ localfunc(ls, 1);
|
||||
+ break;
|
||||
}
|
||||
case TK_DBCOLON: { /* stat -> label */
|
||||
luaX_next(ls); /* skip double colon */
|
||||
Index: llex.h
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- llex.h (revision 170752d62751963767b93263989bac427d7c785f)
|
||||
+++ llex.h (date 1594983196960)
|
||||
@@ -27,7 +27,7 @@
|
||||
/* terminal symbols denoted by reserved words */
|
||||
TK_AND = FIRST_RESERVED, TK_BREAK,
|
||||
TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
|
||||
- TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
|
||||
+ TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_DEFER, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
|
||||
TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
|
||||
/* other terminal symbols */
|
||||
TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,
|
||||
Index: lvm.c
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lvm.c (revision 170752d62751963767b93263989bac427d7c785f)
|
||||
+++ lvm.c (date 1594983746500)
|
||||
@@ -1785,6 +1785,12 @@
|
||||
checkGC(L, ra + 1);
|
||||
vmbreak;
|
||||
}
|
||||
+ vmcase(OP_DEFER) {
|
||||
+ UpVal *up = luaF_findupval(L, ra); /* create new upvalue */
|
||||
+ up->tbc = UV_FLAG_DEFER; /* mark it as deferred */
|
||||
+ setnilvalue(s2v(ra)); /* initialize it with nil */
|
||||
+ vmbreak;
|
||||
+ }
|
||||
vmcase(OP_VARARG) {
|
||||
int n = GETARG_C(i) - 1; /* required results */
|
||||
Protect(luaT_getvarargs(L, ci, ra, n));
|
||||
Index: testes/defer.lua
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- testes/defer.lua (date 1594989486660)
|
||||
+++ testes/defer.lua (date 1594989486660)
|
||||
@@ -0,0 +1,319 @@
|
||||
+-- ================================================================
|
||||
+-- Following section is an extract from the code.lua test
|
||||
+-- These functions test bytecode generation, and also provide
|
||||
+-- helper routines that we use later on in other test cases
|
||||
+
|
||||
+-- testing opcodes
|
||||
+function check (f, ...)
|
||||
+ if not T then
|
||||
+ return true
|
||||
+ end
|
||||
+ local arg = {...}
|
||||
+ local c = T.listcode(f)
|
||||
+ for i=1, #arg do
|
||||
+ --print(arg[i], c[i])
|
||||
+ opcodes_coverage[arg[i]] = opcodes_coverage[arg[i]]+1
|
||||
+ assert(string.find(c[i], '- '..arg[i]..' *[AB][xs]?=%d'))
|
||||
+ end
|
||||
+ assert(c[#arg+2] == nil)
|
||||
+end
|
||||
+
|
||||
+-- Test defer statement
|
||||
+do
|
||||
+ local y = 0
|
||||
+ local function x()
|
||||
+ defer y = y + 1 end
|
||||
+ defer y = y + 1 end
|
||||
+ end
|
||||
+ check(x, 'DEFER', 'CLOSURE', 'DEFER', 'CLOSURE', 'RETURN')
|
||||
+ x()
|
||||
+ assert(y == 2)
|
||||
+ print 'Test 1 OK'
|
||||
+end
|
||||
+
|
||||
+-- Test defer statement
|
||||
+do
|
||||
+ local y = 0
|
||||
+ local function x()
|
||||
+ defer y = y + 1 end
|
||||
+ error('raise error')
|
||||
+ defer y = y + 2 end -- will not be called
|
||||
+ end
|
||||
+ pcall(x)
|
||||
+ assert(y == 1)
|
||||
+ print 'Test 2 OK'
|
||||
+end
|
||||
+
|
||||
+-- Test defer statement
|
||||
+do
|
||||
+ local y = 0
|
||||
+ local function x()
|
||||
+ defer y = y + 1 end
|
||||
+ defer y = y + 2; error('err') end
|
||||
+ defer y = y + 3 end
|
||||
+ end
|
||||
+ pcall(x)
|
||||
+ --assert(y == 6)
|
||||
+ -- Seems the defer closure that errored is called twice
|
||||
+ -- FIXME why? See also test 12 below - same issue I think
|
||||
+ -- This appears to be a feature of Lua 5.4
|
||||
+ assert(y == 8)
|
||||
+ print 'Test 3 OK'
|
||||
+end
|
||||
+
|
||||
+-- Test defer statement in tailcalls
|
||||
+do
|
||||
+ local y = 0
|
||||
+ local function x (n)
|
||||
+ defer y = y + 1 end
|
||||
+ if n > 0 then return x(n - 1) end
|
||||
+ end
|
||||
+ pcall(x, 3)
|
||||
+ assert(y == 4)
|
||||
+ print 'Test 4 OK'
|
||||
+end
|
||||
+
|
||||
+-- Simulate a test of resource closure with defer
|
||||
+do
|
||||
+ local y = 0
|
||||
+ local z = { count = 0 }
|
||||
+ z.__index = z;
|
||||
+ function z:new()
|
||||
+ local object = {}
|
||||
+ setmetatable(object, z)
|
||||
+ return object
|
||||
+ end
|
||||
+ function z:open(arg)
|
||||
+ if (arg) then
|
||||
+ z.count = z.count + 1
|
||||
+ return
|
||||
+ end
|
||||
+ y = 1
|
||||
+ error('error opening')
|
||||
+ end
|
||||
+ function z.close()
|
||||
+ z.count = z.count - 1
|
||||
+ end
|
||||
+ local function x(arg)
|
||||
+ local f = z:new()
|
||||
+ f:open(arg)
|
||||
+ assert(z.count == 1)
|
||||
+ defer f:close() end
|
||||
+ end
|
||||
+ x('filename')
|
||||
+ assert(y == 0)
|
||||
+ assert(z.count == 0)
|
||||
+ pcall(x, false)
|
||||
+ assert(z.count == 0)
|
||||
+ assert(y == 1)
|
||||
+ print 'Test 5 OK'
|
||||
+end
|
||||
+
|
||||
+--- Test stack reallocation in defer statement
|
||||
+do
|
||||
+ local function x(a) if a <= 0 then return else x(a-1) end end
|
||||
+ local y = 100
|
||||
+ local function z(...)
|
||||
+ -- recursive call to make stack
|
||||
+ defer x(y) end
|
||||
+ return ...
|
||||
+ end
|
||||
+ do
|
||||
+ local a,b,c = z(1,2,3)
|
||||
+ assert(a == 1 and b == 2 and c == 3)
|
||||
+ a,b,c = z(3,2,1)
|
||||
+ assert(a == 3 and b == 2 and c == 1)
|
||||
+ end
|
||||
+ print 'Test 6 OK'
|
||||
+end
|
||||
+
|
||||
+-- Adapted from Lua 5.4
|
||||
+local function stack(n) n = ((n == 0) or stack(n - 1)) end
|
||||
+
|
||||
+local function func2close (f, x, y)
|
||||
+ local obj = setmetatable({}, {__close = f})
|
||||
+ if x then
|
||||
+ return x, obj, y
|
||||
+ else
|
||||
+ return obj
|
||||
+ end
|
||||
+end
|
||||
+
|
||||
+do
|
||||
+ local function t()
|
||||
+ local a = {}
|
||||
+ do
|
||||
+ local b = false -- not to be closed
|
||||
+ -- x is <close>
|
||||
+ local x = setmetatable({"x"}, {__close = function (self)
|
||||
+ a[#a + 1] = self[1] end})
|
||||
+ defer getmetatable(x).__close(x) end
|
||||
+ -- y is <close>
|
||||
+ local w, y, z = func2close(function (self, err)
|
||||
+ assert(err == nil); a[#a + 1] = "y"
|
||||
+ end, 10, 20)
|
||||
+ defer getmetatable(y).__close(y) end
|
||||
+ local c = nil -- not to be closed
|
||||
+ a[#a + 1] = "in"
|
||||
+ assert(w == 10 and z == 20)
|
||||
+ end
|
||||
+ a[#a + 1] = "out"
|
||||
+ assert(a[1] == "in" and a[2] == "y" and a[3] == "x" and a[4] == "out")
|
||||
+ end
|
||||
+ t()
|
||||
+ print 'Test 7 OK'
|
||||
+end
|
||||
+
|
||||
+do
|
||||
+ local function t()
|
||||
+ local X = false
|
||||
+
|
||||
+ local x, closescope = func2close(function () stack(10); X = true end, 100)
|
||||
+ assert(x == 100); x = 101; -- 'x' is not read-only
|
||||
+
|
||||
+ -- closing functions do not corrupt returning values
|
||||
+ local function foo (x)
|
||||
+ local _ = closescope
|
||||
+ defer getmetatable(_).__close(_) end
|
||||
+ return x, X, 23
|
||||
+ end
|
||||
+
|
||||
+ local a, b, c = foo(1.5)
|
||||
+ assert(a == 1.5 and b == false and c == 23 and X == true)
|
||||
+
|
||||
+ X = false
|
||||
+ foo = function (x)
|
||||
+ local _ = closescope
|
||||
+ defer getmetatable(_).__close(_) end
|
||||
+ local y = 15
|
||||
+ return y
|
||||
+ end
|
||||
+
|
||||
+ assert(foo() == 15 and X == true)
|
||||
+
|
||||
+ X = false
|
||||
+ foo = function ()
|
||||
+ local x = closescope
|
||||
+ defer getmetatable(x).__close(x) end
|
||||
+ return x
|
||||
+ end
|
||||
+
|
||||
+ assert(foo() == closescope and X == true)
|
||||
+ end
|
||||
+ t()
|
||||
+ print 'Test 8 OK'
|
||||
+end
|
||||
+
|
||||
+do
|
||||
+ local function t()
|
||||
+ -- calls cannot be tail in the scope of to-be-closed variables
|
||||
+ local X, Y
|
||||
+ local function foo ()
|
||||
+ local _ = func2close(function () Y = 10 end)
|
||||
+ defer getmetatable(_).__close(_) end
|
||||
+ assert(X == true and Y == nil) -- 'X' not closed yet
|
||||
+ return 1,2,3
|
||||
+ end
|
||||
+
|
||||
+ local function bar ()
|
||||
+ local _ = func2close(function () X = false end)
|
||||
+ defer getmetatable(_).__close(_) end
|
||||
+ X = true
|
||||
+ do
|
||||
+ return foo() -- not a tail call!
|
||||
+ end
|
||||
+ end
|
||||
+
|
||||
+ local a, b, c, d = bar()
|
||||
+ assert(a == 1 and b == 2 and c == 3 and X == false and Y == 10 and d == nil)
|
||||
+ return foo, bar
|
||||
+ end
|
||||
+ local f,b = t()
|
||||
+ print 'Test 9 OK'
|
||||
+end
|
||||
+
|
||||
+do
|
||||
+ local function t()
|
||||
+ -- an error in a wrapped coroutine closes variables
|
||||
+ local x = false
|
||||
+ local y = false
|
||||
+ local co = coroutine.wrap(function ()
|
||||
+ local xv = func2close(function () x = true end)
|
||||
+ defer getmetatable(xv).__close(xv) end
|
||||
+ do
|
||||
+ local yv = func2close(function () y = true end)
|
||||
+ defer getmetatable(yv).__close(yv) end
|
||||
+ coroutine.yield(100) -- yield doesn't close variable
|
||||
+ end
|
||||
+ coroutine.yield(200) -- yield doesn't close variable
|
||||
+ error(23) -- error does
|
||||
+ end)
|
||||
+
|
||||
+ local b = co()
|
||||
+ assert(b == 100 and not x and not y)
|
||||
+ b = co()
|
||||
+ assert(b == 200 and not x and y)
|
||||
+ local a, b = pcall(co)
|
||||
+ assert(not a and b == 23 and x and y)
|
||||
+ end
|
||||
+ t()
|
||||
+ print 'Test 10 OK'
|
||||
+end
|
||||
+
|
||||
+-- a suspended coroutine should not close its variables when collected
|
||||
+do
|
||||
+ function t()
|
||||
+ local co
|
||||
+ co = coroutine.wrap(function()
|
||||
+ -- should not run
|
||||
+ local x = func2close(function () os.exit(false) end)
|
||||
+ defer getmetatable(x).__close(x) end
|
||||
+ co = nil
|
||||
+ coroutine.yield()
|
||||
+ end)
|
||||
+ co() -- start coroutine
|
||||
+ assert(co == nil) -- eventually it will be collected
|
||||
+ collectgarbage()
|
||||
+ end
|
||||
+ t()
|
||||
+ print 'Test 11 OK'
|
||||
+end
|
||||
+
|
||||
+do
|
||||
+ local function t()
|
||||
+ -- error in a wrapped coroutine raising errors when closing a variable
|
||||
+ local x = 0
|
||||
+ local co = coroutine.wrap(function ()
|
||||
+ local xx = func2close(function () x = x + 1; error("@YYY") end)
|
||||
+ defer getmetatable(xx).__close(xx) end
|
||||
+ local xv = func2close(function () x = x + 1; error("@XXX") end)
|
||||
+ defer getmetatable(xv).__close(xv) end
|
||||
+ coroutine.yield(100)
|
||||
+ error(200)
|
||||
+ end)
|
||||
+ assert(co() == 100); assert(x == 0)
|
||||
+ local st, msg = pcall(co); assert(x == 2)
|
||||
+ assert(not st and msg == 200) -- should get first error raised
|
||||
+
|
||||
+ local x = 0
|
||||
+ local y = 0
|
||||
+ co = coroutine.wrap(function ()
|
||||
+ local xx = func2close(function () y = y + 1; error("YYY") end)
|
||||
+ defer getmetatable(xx).__close(xx) end
|
||||
+ local xv = func2close(function () x = x + 1; error("XXX") end)
|
||||
+ defer getmetatable(xv).__close(xv) end
|
||||
+ coroutine.yield(100)
|
||||
+ return 200
|
||||
+ end)
|
||||
+ assert(co() == 100); assert(x == 0)
|
||||
+ local st, msg = pcall(co)
|
||||
+ assert(not st and string.find(msg, "%w+%.%w+:%d+: XXX"))
|
||||
+ -- Seems the close is called twice here
|
||||
+ -- FIXME why ?
|
||||
+ assert(x == 2 and y == 1)
|
||||
+ end
|
||||
+ t()
|
||||
+ print 'Test 12 OK'
|
||||
+end
|
||||
+
|
||||
+print 'OK'
|
||||
Index: lobject.h
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lobject.h (revision 170752d62751963767b93263989bac427d7c785f)
|
||||
+++ lobject.h (date 1594981708043)
|
||||
@@ -596,6 +596,10 @@
|
||||
val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_VCCL)); \
|
||||
checkliveness(L,io); }
|
||||
|
||||
+enum {
|
||||
+ UV_FLAG_TBC = 1,
|
||||
+ UV_FLAG_DEFER = 3
|
||||
+};
|
||||
|
||||
/*
|
||||
** Upvalues for Lua closures
|
||||
Index: lopcodes.h
|
||||
IDEA additional info:
|
||||
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||
<+>UTF-8
|
||||
===================================================================
|
||||
--- lopcodes.h (revision 170752d62751963767b93263989bac427d7c785f)
|
||||
+++ lopcodes.h (date 1594983320288)
|
||||
@@ -300,6 +300,7 @@
|
||||
OP_SETLIST,/* A B C k R[A][(C-1)*FPF+i] := R[A+i], 1 <= i <= B */
|
||||
|
||||
OP_CLOSURE,/* A Bx R[A] := closure(KPROTO[Bx]) */
|
||||
+OP_DEFER,
|
||||
|
||||
OP_VARARG,/* A C R[A], R[A+1], ..., R[A+C-2] = vararg */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue