mirror of
https://github.com/love2d/megasource.git
synced 2026-08-17 11:11:35 +02:00
Update LuaJIT to the latest 2.1.0 source (f3c8569)
This commit is contained in:
+1
-1
@@ -167,7 +167,7 @@ endif()
|
|||||||
|
|
||||||
set(MEGA_ZLIB_VER "1.2.11")
|
set(MEGA_ZLIB_VER "1.2.11")
|
||||||
set(MEGA_LUA51_VER "5.1.5")
|
set(MEGA_LUA51_VER "5.1.5")
|
||||||
set(MEGA_LUAJIT_VER "2.1.0-1d8b747")
|
set(MEGA_LUAJIT_VER "2.1.0-f3c8569")
|
||||||
set(MEGA_LIBOGG_VER "1.3.2")
|
set(MEGA_LIBOGG_VER "1.3.2")
|
||||||
set(MEGA_LIBVORBIS_VER "1.3.5")
|
set(MEGA_LIBVORBIS_VER "1.3.5")
|
||||||
set(MEGA_LIBTHEORA_VER "1.1.1")
|
set(MEGA_LIBTHEORA_VER "1.1.1")
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
===============================================================================
|
===============================================================================
|
||||||
LuaJIT -- a Just-In-Time Compiler for Lua. https://luajit.org/
|
LuaJIT -- a Just-In-Time Compiler for Lua. https://luajit.org/
|
||||||
|
|
||||||
Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
# For MSVC, please follow the instructions given in src/msvcbuild.bat.
|
# For MSVC, please follow the instructions given in src/msvcbuild.bat.
|
||||||
# For MinGW and Cygwin, cd to src and run make with the Makefile there.
|
# For MinGW and Cygwin, cd to src and run make with the Makefile there.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
# Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
MAJVER= 2
|
MAJVER= 2
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.
|
|||||||
|
|
||||||
Project Homepage: https://luajit.org/
|
Project Homepage: https://luajit.org/
|
||||||
|
|
||||||
LuaJIT is Copyright (C) 2005-2020 Mike Pall.
|
LuaJIT is Copyright (C) 2005-2021 Mike Pall.
|
||||||
LuaJIT is free software, released under the MIT license.
|
LuaJIT is free software, released under the MIT license.
|
||||||
See full Copyright Notice in the COPYRIGHT file or in luajit.h.
|
See full Copyright Notice in the COPYRIGHT file or in luajit.h.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2004-2020 Mike Pall.
|
/* Copyright (C) 2004-2021 Mike Pall.
|
||||||
*
|
*
|
||||||
* You are welcome to use the general ideas of this design for your own sites.
|
* You are welcome to use the general ideas of this design for your own sites.
|
||||||
* But please do not steal the stylesheet, the layout or the color scheme.
|
* But please do not steal the stylesheet, the layout or the color scheme.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2004-2020 Mike Pall.
|
/* Copyright (C) 2004-2021 Mike Pall.
|
||||||
*
|
*
|
||||||
* You are welcome to use the general ideas of this design for your own sites.
|
* You are welcome to use the general ideas of this design for your own sites.
|
||||||
* But please do not steal the stylesheet, the layout or the color scheme.
|
* But please do not steal the stylesheet, the layout or the color scheme.
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Contact</title>
|
<title>Contact</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -37,6 +37,8 @@
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -87,7 +89,7 @@ xD("fyZKB8xv\"FJytmz8.KAB0u52D")
|
|||||||
<h2>Copyright</h2>
|
<h2>Copyright</h2>
|
||||||
<p>
|
<p>
|
||||||
All documentation is
|
All documentation is
|
||||||
Copyright © 2005-2020 Mike Pall.
|
Copyright © 2005-2021 Mike Pall.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
@@ -95,7 +97,7 @@ Copyright © 2005-2020 Mike Pall.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -0,0 +1,693 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>String Buffer Library</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
|
<meta name="Language" content="en">
|
||||||
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
|
<style type="text/css">
|
||||||
|
.lib {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-left: 5px;
|
||||||
|
padding: 0 5px;
|
||||||
|
font-size: 60%;
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #c5d5ff;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="site">
|
||||||
|
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||||
|
</div>
|
||||||
|
<div id="head">
|
||||||
|
<h1>String Buffer Library</h1>
|
||||||
|
</div>
|
||||||
|
<div id="nav">
|
||||||
|
<ul><li>
|
||||||
|
<a href="luajit.html">LuaJIT</a>
|
||||||
|
<ul><li>
|
||||||
|
<a href="https://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||||
|
</li><li>
|
||||||
|
<a href="install.html">Installation</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="running.html">Running</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="extensions.html">Extensions</a>
|
||||||
|
<ul><li>
|
||||||
|
<a href="ext_ffi.html">FFI Library</a>
|
||||||
|
<ul><li>
|
||||||
|
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_api.html">ffi.* API</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a class="current" href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="ext_profiler.html">Profiler</a>
|
||||||
|
</li></ul>
|
||||||
|
</li><li>
|
||||||
|
<a href="status.html">Status</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="faq.html">FAQ</a>
|
||||||
|
</li><li>
|
||||||
|
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||||
|
</li><li>
|
||||||
|
<a href="https://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||||
|
</li></ul>
|
||||||
|
</div>
|
||||||
|
<div id="main">
|
||||||
|
<p>
|
||||||
|
The string buffer library allows <b>high-performance manipulation of
|
||||||
|
string-like data</b>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Unlike Lua strings, which are constants, string buffers are
|
||||||
|
<b>mutable</b> sequences of 8-bit (binary-transparent) characters. Data
|
||||||
|
can be stored, formatted and encoded into a string buffer and later
|
||||||
|
converted, extracted or decoded.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The convenient string buffer API simplifies common string manipulation
|
||||||
|
tasks, that would otherwise require creating many intermediate strings.
|
||||||
|
String buffers improve performance by eliminating redundant memory
|
||||||
|
copies, object creation, string interning and garbage collection
|
||||||
|
overhead. In conjunction with the FFI library, they allow zero-copy
|
||||||
|
operations.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The string buffer libary also includes a high-performance
|
||||||
|
<a href="serialize">serializer</a> for Lua objects.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="wip" style="color:#ff0000">Work in Progress</h2>
|
||||||
|
<p>
|
||||||
|
<b style="color:#ff0000">This library is a work in progress. More
|
||||||
|
functionality will be added soon.</b>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="use">Using the String Buffer Library</h2>
|
||||||
|
<p>
|
||||||
|
The string buffer library is built into LuaJIT by default, but it's not
|
||||||
|
loaded by default. Add this to the start of every Lua file that needs
|
||||||
|
one of its functions:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
local buffer = require("string.buffer")
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The convention for the syntax shown on this page is that <tt>buffer</tt>
|
||||||
|
refers to the buffer library and <tt>buf</tt> refers to an individual
|
||||||
|
buffer object.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Please note the difference between a Lua function call, e.g.
|
||||||
|
<tt>buffer.new()</tt> (with a dot) and a Lua method call, e.g.
|
||||||
|
<tt>buf:reset()</tt> (with a colon).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_object">Buffer Objects</h3>
|
||||||
|
<p>
|
||||||
|
A buffer object is a garbage-collected Lua object. After creation with
|
||||||
|
<tt>buffer.new()</tt>, it can (and should) be reused for many operations.
|
||||||
|
When the last reference to a buffer object is gone, it will eventually
|
||||||
|
be freed by the garbage collector, along with the allocated buffer
|
||||||
|
space.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Buffers operate like a FIFO (first-in first-out) data structure. Data
|
||||||
|
can be appended (written) to the end of the buffer and consumed (read)
|
||||||
|
from the front of the buffer. These operations may be freely mixed.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The buffer space that holds the characters is managed automatically
|
||||||
|
— it grows as needed and already consumed space is recycled. Use
|
||||||
|
<tt>buffer.new(size)</tt> and <tt>buf:free()</tt>, if you need more
|
||||||
|
control.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The maximum size of a single buffer is the same as the maximum size of a
|
||||||
|
Lua string, which is slightly below two gigabytes. For huge data sizes,
|
||||||
|
neither strings nor buffers are the right data structure — use the
|
||||||
|
FFI library to directly map memory or files up to the virtual memory
|
||||||
|
limit of your OS.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_overview">Buffer Method Overview</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
The <tt>buf:put*()</tt>-like methods append (write) characters to the
|
||||||
|
end of the buffer.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
The <tt>buf:get*()</tt>-like methods consume (read) characters from the
|
||||||
|
front of the buffer.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Other methods, like <tt>buf:tostring()</tt> only read the buffer
|
||||||
|
contents, but don't change the buffer.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
The <tt>buf:set()</tt> method allows zero-copy consumption of a string
|
||||||
|
or an FFI cdata object as a buffer.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
The FFI-specific methods allow zero-copy read/write-style operations or
|
||||||
|
modifying the buffer contents in-place. Please check the
|
||||||
|
<a href="#ffi_caveats">FFI caveats</a> below, too.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Methods that don't need to return anything specific, return the buffer
|
||||||
|
object itself as a convenience. This allows method chaining, e.g.:
|
||||||
|
<tt>buf:reset():encode(obj)</tt> or <tt>buf:skip(len):get()</tt>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 id="create">Buffer Creation and Management</h2>
|
||||||
|
|
||||||
|
<h3 id="buffer_new"><tt>local buf = buffer.new([size [,options]])<br>
|
||||||
|
local buf = buffer.new([options])</tt></h3>
|
||||||
|
<p>
|
||||||
|
Creates a new buffer object.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The optional <tt>size</tt> argument ensures a minimum initial buffer
|
||||||
|
size. This is strictly an optimization when the required buffer size is
|
||||||
|
known beforehand. The buffer space will grow as needed, in any case.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The optional table <tt>options</tt> sets various
|
||||||
|
<a href="#serialize_options">serialization options</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_reset"><tt>buf = buf:reset()</tt></h3>
|
||||||
|
<p>
|
||||||
|
Reset (empty) the buffer. The allocated buffer space is not freed and
|
||||||
|
may be reused.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_free"><tt>buf = buf:free()</tt></h3>
|
||||||
|
<p>
|
||||||
|
The buffer space of the buffer object is freed. The object itself
|
||||||
|
remains intact, empty and may be reused.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Note: you normally don't need to use this method. The garbage collector
|
||||||
|
automatically frees the buffer space, when the buffer object is
|
||||||
|
collected. Use this method, if you need to free the associated memory
|
||||||
|
immediately.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="write">Buffer Writers</h2>
|
||||||
|
|
||||||
|
<h3 id="buffer_put"><tt>buf = buf:put([str|num|obj] [,…])</tt></h3>
|
||||||
|
<p>
|
||||||
|
Appends a string <tt>str</tt>, a number <tt>num</tt> or any object
|
||||||
|
<tt>obj</tt> with a <tt>__tostring</tt> metamethod to the buffer.
|
||||||
|
Multiple arguments are appended in the given order.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Appending a buffer to a buffer is possible and short-circuited
|
||||||
|
internally. But it still involves a copy. Better combine the buffer
|
||||||
|
writes to use a single buffer.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_putf"><tt>buf = buf:putf(format, …)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Appends the formatted arguments to the buffer. The <tt>format</tt>
|
||||||
|
string supports the same options as <tt>string.format()</tt>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_putcdata"><tt>buf = buf:putcdata(cdata, len)</tt><span class="lib">FFI</span></h3>
|
||||||
|
<p>
|
||||||
|
Appends the given <tt>len</tt> number of bytes from the memory pointed
|
||||||
|
to by the FFI <tt>cdata</tt> object to the buffer. The object needs to
|
||||||
|
be convertible to a (constant) pointer.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_set"><tt>buf = buf:set(str)<br>
|
||||||
|
buf = buf:set(cdata, len)</tt><span class="lib">FFI</span></h3>
|
||||||
|
<p>
|
||||||
|
This method allows zero-copy consumption of a string or an FFI cdata
|
||||||
|
object as a buffer. It stores a reference to the passed string
|
||||||
|
<tt>str</tt> or the FFI <tt>cdata</tt> object in the buffer. Any buffer
|
||||||
|
space originally allocated is freed. This is <i>not</i> an append
|
||||||
|
operation, unlike the <tt>buf:put*()</tt> methods.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
After calling this method, the buffer behaves as if
|
||||||
|
<tt>buf:free():put(str)</tt> or <tt>buf:free():put(cdata, len)</tt>
|
||||||
|
had been called. However, the data is only referenced and not copied, as
|
||||||
|
long as the buffer is only consumed.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In case the buffer is written to later on, the referenced data is copied
|
||||||
|
and the object reference is removed (copy-on-write semantics).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The stored reference is an anchor for the garbage collector and keeps the
|
||||||
|
originally passed string or FFI cdata object alive.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_reserve"><tt>ptr, len = buf:reserve(size)</tt><span class="lib">FFI</span><br>
|
||||||
|
<tt>buf = buf:commit(used)</tt><span class="lib">FFI</span></h3>
|
||||||
|
<p>
|
||||||
|
The <tt>reserve</tt> method reserves at least <tt>size</tt> bytes of
|
||||||
|
write space in the buffer. It returns an <tt>uint8_t *</tt> FFI
|
||||||
|
cdata pointer <tt>ptr</tt> that points to this space.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The available length in bytes is returned in <tt>len</tt>. This is at
|
||||||
|
least <tt>size</tt> bytes, but may be more to facilitate efficient
|
||||||
|
buffer growth. You can either make use of the additional space or ignore
|
||||||
|
<tt>len</tt> and only use <tt>size</tt> bytes.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The <tt>commit</tt> method appends the <tt>used</tt> bytes of the
|
||||||
|
previously returned write space to the buffer data.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This pair of methods allows zero-copy use of C read-style APIs:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
local MIN_SIZE = 65536
|
||||||
|
repeat
|
||||||
|
local ptr, len = buf:reserve(MIN_SIZE)
|
||||||
|
local n = C.read(fd, ptr, len)
|
||||||
|
if n == 0 then break end -- EOF.
|
||||||
|
if n < 0 then error("read error") end
|
||||||
|
buf:commit(n)
|
||||||
|
until false
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
The reserved write space is <i>not</i> initialized. At least the
|
||||||
|
<tt>used</tt> bytes <b>must</b> be written to before calling the
|
||||||
|
<tt>commit</tt> method. There's no need to call the <tt>commit</tt>
|
||||||
|
method, if nothing is added to the buffer (e.g. on error).
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="read">Buffer Readers</h2>
|
||||||
|
|
||||||
|
<h3 id="buffer_length"><tt>len = #buf</tt></h3>
|
||||||
|
<p>
|
||||||
|
Returns the current length of the buffer data in bytes.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_concat"><tt>res = str|num|buf .. str|num|buf […]</tt></h3>
|
||||||
|
<p>
|
||||||
|
The Lua concatenation operator <tt>..</tt> also accepts buffers, just
|
||||||
|
like strings or numbers. It always returns a string and not a buffer.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Note that although this is supported for convenience, this thwarts one
|
||||||
|
of the main reasons to use buffers, which is to avoid string
|
||||||
|
allocations. Rewrite it with <tt>buf:put()</tt> and <tt>buf:get()</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Mixing this with unrelated objects that have a <tt>__concat</tt>
|
||||||
|
metamethod may not work, since these probably only expect strings.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_skip"><tt>buf = buf:skip(len)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Skips (consumes) <tt>len</tt> bytes from the buffer up to the current
|
||||||
|
length of the buffer data.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_get"><tt>str, … = buf:get([len|nil] [,…])</tt></h3>
|
||||||
|
<p>
|
||||||
|
Consumes the buffer data and returns one or more strings. If called
|
||||||
|
without arguments, the whole buffer data is consumed. If called with a
|
||||||
|
number, up to <tt>len</tt> bytes are consumed. A <tt>nil</tt> argument
|
||||||
|
consumes the remaining buffer space (this only makes sense as the last
|
||||||
|
argument). Multiple arguments consume the buffer data in the given
|
||||||
|
order.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Note: a zero length or no remaining buffer data returns an empty string
|
||||||
|
and not <tt>nil</tt>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_tostring"><tt>str = buf:tostring()<br>
|
||||||
|
str = tostring(buf)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Creates a string from the buffer data, but doesn't consume it. The
|
||||||
|
buffer remains unchanged.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Buffer objects also define a <tt>__tostring</tt> metamethod. This means
|
||||||
|
buffers can be passed to the global <tt>tostring()</tt> function and
|
||||||
|
many other functions that accept this in place of strings. The important
|
||||||
|
internal uses in functions like <tt>io.write()</tt> are short-circuited
|
||||||
|
to avoid the creation of an intermediate string object.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_ref"><tt>ptr, len = buf:ref()</tt><span class="lib">FFI</span></h3>
|
||||||
|
<p>
|
||||||
|
Returns an <tt>uint8_t *</tt> FFI cdata pointer <tt>ptr</tt> that
|
||||||
|
points to the buffer data. The length of the buffer data in bytes is
|
||||||
|
returned in <tt>len</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The returned pointer can be directly passed to C functions that expect a
|
||||||
|
buffer and a length. You can also do bytewise reads
|
||||||
|
(<tt>local x = ptr[i]</tt>) or writes
|
||||||
|
(<tt>ptr[i] = 0x40</tt>) of the buffer data.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In conjunction with the <tt>skip</tt> method, this allows zero-copy use
|
||||||
|
of C write-style APIs:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
repeat
|
||||||
|
local ptr, len = buf:ref()
|
||||||
|
if len == 0 then break end
|
||||||
|
local n = C.write(fd, ptr, len)
|
||||||
|
if n < 0 then error("write error") end
|
||||||
|
buf:skip(n)
|
||||||
|
until n >= len
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Unlike Lua strings, buffer data is <i>not</i> implicitly
|
||||||
|
zero-terminated. It's not safe to pass <tt>ptr</tt> to C functions that
|
||||||
|
expect zero-terminated strings. If you're not using <tt>len</tt>, then
|
||||||
|
you're doing something wrong.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="serialize">Serialization of Lua Objects</h2>
|
||||||
|
<p>
|
||||||
|
The following functions and methods allow <b>high-speed serialization</b>
|
||||||
|
(encoding) of a Lua object into a string and decoding it back to a Lua
|
||||||
|
object. This allows convenient storage and transport of <b>structured
|
||||||
|
data</b>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The encoded data is in an <a href="#serialize_format">internal binary
|
||||||
|
format</a>. The data can be stored in files, binary-transparent
|
||||||
|
databases or transmitted to other LuaJIT instances across threads,
|
||||||
|
processes or networks.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Encoding speed can reach up to 1 Gigabyte/second on a modern desktop- or
|
||||||
|
server-class system, even when serializing many small objects. Decoding
|
||||||
|
speed is mostly constrained by object creation cost.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The serializer handles most Lua types, common FFI number types and
|
||||||
|
nested structures. Functions, thread objects, other FFI cdata and full
|
||||||
|
userdata cannot be serialized (yet).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The encoder serializes nested structures as trees. Multiple references
|
||||||
|
to a single object will be stored separately and create distinct objects
|
||||||
|
after decoding. Circular references cause an error.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="serialize_methods">Serialization Functions and Methods</h3>
|
||||||
|
|
||||||
|
<h3 id="buffer_encode"><tt>str = buffer.encode(obj)<br>
|
||||||
|
buf = buf:encode(obj)</tt></h3>
|
||||||
|
<p>
|
||||||
|
Serializes (encodes) the Lua object <tt>obj</tt>. The stand-alone
|
||||||
|
function returns a string <tt>str</tt>. The buffer method appends the
|
||||||
|
encoding to the buffer.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<tt>obj</tt> can be any of the supported Lua types — it doesn't
|
||||||
|
need to be a Lua table.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This function may throw an error when attempting to serialize
|
||||||
|
unsupported object types, circular references or deeply nested tables.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="buffer_decode"><tt>obj = buffer.decode(str)<br>
|
||||||
|
obj = buf:decode()</tt></h3>
|
||||||
|
<p>
|
||||||
|
The stand-alone function de-serializes (decodes) the string
|
||||||
|
<tt>str</tt>, the buffer method de-serializes one object from the
|
||||||
|
buffer. Both return a Lua object <tt>obj</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The returned object may be any of the supported Lua types —
|
||||||
|
even <tt>nil</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This function may throw an error when fed with malformed or incomplete
|
||||||
|
encoded data. The stand-alone function throws when there's left-over
|
||||||
|
data after decoding a single top-level object. The buffer method leaves
|
||||||
|
any left-over data in the buffer.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="serialize_options">Serialization Options</h3>
|
||||||
|
<p>
|
||||||
|
The <tt>options</tt> table passed to <tt>buffer.new()</tt> may contain
|
||||||
|
the following members (all optional):
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<tt>dict</tt> is a Lua table holding a <b>dictionary of strings</b> that
|
||||||
|
commonly occur as table keys of objects you are serializing. These keys
|
||||||
|
are compactly encoded as indexes during serialization. A well chosen
|
||||||
|
dictionary saves space and improves serialization performance.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<tt>metatable</tt> is a Lua table holding a <b>dictionary of metatables</b>
|
||||||
|
for the table objects you are serializing.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
<tt>dict</tt> needs to be an array of strings and <tt>metatable</tt> needs
|
||||||
|
to be an array of tables. Both starting at index 1 and without holes (no
|
||||||
|
<tt>nil</tt> inbetween). The tables are anchored in the buffer object and
|
||||||
|
internally modified into a two-way index (don't do this yourself, just pass
|
||||||
|
a plain array). The tables must not be modified after they have been passed
|
||||||
|
to <tt>buffer.new()</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The <tt>dict</tt> and <tt>metatable</tt> tables used by the encoder and
|
||||||
|
decoder must be the same. Put the most common entries at the front. Extend
|
||||||
|
at the end to ensure backwards-compatibility — older encodings can
|
||||||
|
then still be read. You may also set some indexes to <tt>false</tt> to
|
||||||
|
explicitly drop backwards-compatibility. Old encodings that use these
|
||||||
|
indexes will throw an error when decoded.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Metatables that are not found in the <tt>metatable</tt> dictionary are
|
||||||
|
ignored when encoding. Decoding returns a table with a <tt>nil</tt>
|
||||||
|
metatable.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Note: parsing and preparation of the options table is somewhat
|
||||||
|
expensive. Create a buffer object only once and recycle it for multiple
|
||||||
|
uses. Avoid mixing encoder and decoder buffers, since the
|
||||||
|
<tt>buf:set()</tt> method frees the already allocated buffer space:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
local options = {
|
||||||
|
dict = { "commonly", "used", "string", "keys" },
|
||||||
|
}
|
||||||
|
local buf_enc = buffer.new(options)
|
||||||
|
local buf_dec = buffer.new(options)
|
||||||
|
|
||||||
|
local function encode(obj)
|
||||||
|
return buf_enc:reset():encode(obj):get()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function decode(str)
|
||||||
|
return buf_dec:set(str):decode()
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h3 id="serialize_stream">Streaming Serialization</h3>
|
||||||
|
<p>
|
||||||
|
In some contexts, it's desirable to do piecewise serialization of large
|
||||||
|
datasets, also known as <i>streaming</i>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This serialization format can be safely concatenated and supports streaming.
|
||||||
|
Multiple encodings can simply be appended to a buffer and later decoded
|
||||||
|
individually:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
local buf = buffer.new()
|
||||||
|
buf:encode(obj1)
|
||||||
|
buf:encode(obj2)
|
||||||
|
local copy1 = buf:decode()
|
||||||
|
local copy2 = buf:decode()
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Here's how to iterate over a stream:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
while #buf ~= 0 do
|
||||||
|
local obj = buf:decode()
|
||||||
|
-- Do something with obj.
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
<p>
|
||||||
|
Since the serialization format doesn't prepend a length to its encoding,
|
||||||
|
network applications may need to transmit the length, too.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="serialize_format">Serialization Format Specification</h3>
|
||||||
|
<p>
|
||||||
|
This serialization format is designed for <b>internal use</b> by LuaJIT
|
||||||
|
applications. Serialized data is upwards-compatible and portable across
|
||||||
|
all supported LuaJIT platforms.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
It's an <b>8-bit binary format</b> and not human-readable. It uses e.g.
|
||||||
|
embedded zeroes and stores embedded Lua string objects unmodified, which
|
||||||
|
are 8-bit-clean, too. Encoded data can be safely concatenated for
|
||||||
|
streaming and later decoded one top-level object at a time.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The encoding is reasonably compact, but tuned for maximum performance,
|
||||||
|
not for minimum space usage. It compresses well with any of the common
|
||||||
|
byte-oriented data compression algorithms.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Although documented here for reference, this format is explicitly
|
||||||
|
<b>not</b> intended to be a 'public standard' for structured data
|
||||||
|
interchange across computer languages (like JSON or MessagePack). Please
|
||||||
|
do not use it as such.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The specification is given below as a context-free grammar with a
|
||||||
|
top-level <tt>object</tt> as the starting point. Alternatives are
|
||||||
|
separated by the <tt>|</tt> symbol and <tt>*</tt> indicates repeats.
|
||||||
|
Grouping is implicit or indicated by <tt>{…}</tt>. Terminals are
|
||||||
|
either plain hex numbers, encoded as bytes, or have a <tt>.format</tt>
|
||||||
|
suffix.
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
object → nil | false | true
|
||||||
|
| null | lightud32 | lightud64
|
||||||
|
| int | num | tab | tab_mt
|
||||||
|
| int64 | uint64 | complex
|
||||||
|
| string
|
||||||
|
|
||||||
|
nil → 0x00
|
||||||
|
false → 0x01
|
||||||
|
true → 0x02
|
||||||
|
|
||||||
|
null → 0x03 // NULL lightuserdata
|
||||||
|
lightud32 → 0x04 data.I // 32 bit lightuserdata
|
||||||
|
lightud64 → 0x05 data.L // 64 bit lightuserdata
|
||||||
|
|
||||||
|
int → 0x06 int.I // int32_t
|
||||||
|
num → 0x07 double.L
|
||||||
|
|
||||||
|
tab → 0x08 // Empty table
|
||||||
|
| 0x09 h.U h*{object object} // Key/value hash
|
||||||
|
| 0x0a a.U a*object // 0-based array
|
||||||
|
| 0x0b a.U a*object h.U h*{object object} // Mixed
|
||||||
|
| 0x0c a.U (a-1)*object // 1-based array
|
||||||
|
| 0x0d a.U (a-1)*object h.U h*{object object} // Mixed
|
||||||
|
tab_mt → 0x0e (index-1).U tab // Metatable dict entry
|
||||||
|
|
||||||
|
int64 → 0x10 int.L // FFI int64_t
|
||||||
|
uint64 → 0x11 uint.L // FFI uint64_t
|
||||||
|
complex → 0x12 re.L im.L // FFI complex
|
||||||
|
|
||||||
|
string → (0x20+len).U len*char.B
|
||||||
|
| 0x0f (index-1).U // String dict entry
|
||||||
|
|
||||||
|
.B = 8 bit
|
||||||
|
.I = 32 bit little-endian
|
||||||
|
.L = 64 bit little-endian
|
||||||
|
.U = prefix-encoded 32 bit unsigned number n:
|
||||||
|
0x00..0xdf → n.B
|
||||||
|
0xe0..0x1fdf → (0xe0|(((n-0xe0)>>8)&0x1f)).B ((n-0xe0)&0xff).B
|
||||||
|
0x1fe0.. → 0xff n.I
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="error">Error handling</h2>
|
||||||
|
<p>
|
||||||
|
Many of the buffer methods can throw an error. Out-of-memory or usage
|
||||||
|
errors are best caught with an outer wrapper for larger parts of code.
|
||||||
|
There's not much one can do after that, anyway.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
OTOH you may want to catch some errors individually. Buffer methods need
|
||||||
|
to receive the buffer object as the first argument. The Lua colon-syntax
|
||||||
|
<tt>obj:method()</tt> does that implicitly. But to wrap a method with
|
||||||
|
<tt>pcall()</tt>, the arguments need to be passed like this:
|
||||||
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
local ok, err = pcall(buf.encode, buf, obj)
|
||||||
|
if not ok then
|
||||||
|
-- Handle error in err.
|
||||||
|
end
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="ffi_caveats">FFI caveats</h2>
|
||||||
|
<p>
|
||||||
|
The string buffer library has been designed to work well together with
|
||||||
|
the FFI library. But due to the low-level nature of the FFI library,
|
||||||
|
some care needs to be taken:
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
First, please remember that FFI pointers are zero-indexed. The space
|
||||||
|
returned by <tt>buf:reserve()</tt> and <tt>buf:ref()</tt> starts at the
|
||||||
|
returned pointer and ends before <tt>len</tt> bytes after that.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
I.e. the first valid index is <tt>ptr[0]</tt> and the last valid index
|
||||||
|
is <tt>ptr[len-1]</tt>. If the returned length is zero, there's no valid
|
||||||
|
index at all. The returned pointer may even be <tt>NULL</tt>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The space pointed to by the returned pointer is only valid as long as
|
||||||
|
the buffer is not modified in any way (neither append, nor consume, nor
|
||||||
|
reset, etc.). The pointer is also not a GC anchor for the buffer object
|
||||||
|
itself.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Buffer data is only guaranteed to be byte-aligned. Casting the returned
|
||||||
|
pointer to a data type with higher alignment may cause unaligned
|
||||||
|
accesses. It depends on the CPU architecture whether this is allowed or
|
||||||
|
not (it's always OK on x86/x64 and mostly OK on other modern
|
||||||
|
architectures).
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
FFI pointers or references do not count as GC anchors for an underlying
|
||||||
|
object. E.g. an <tt>array</tt> allocated with <tt>ffi.new()</tt> is
|
||||||
|
anchored by <tt>buf:set(array, len)</tt>, but not by
|
||||||
|
<tt>buf:set(array+offset, len)</tt>. The addition of the offset
|
||||||
|
creates a new pointer, even when the offset is zero. In this case, you
|
||||||
|
need to make sure there's still a reference to the original array as
|
||||||
|
long as its contents are in use by the buffer.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Even though each LuaJIT VM instance is single-threaded (but you can
|
||||||
|
create multiple VMs), FFI data structures can be accessed concurrently.
|
||||||
|
Be careful when reading/writing FFI cdata from/to buffers to avoid
|
||||||
|
concurrent accesses or modifications. In particular, the memory
|
||||||
|
referenced by <tt>buf:set(cdata, len)</tt> must not be modified
|
||||||
|
while buffer readers are working on it. Shared, but read-only memory
|
||||||
|
mappings of files are OK, but only if the file does not change.
|
||||||
|
</p>
|
||||||
|
<br class="flush">
|
||||||
|
</div>
|
||||||
|
<div id="foot">
|
||||||
|
<hr class="hide">
|
||||||
|
Copyright © 2005-2021
|
||||||
|
<span class="noprint">
|
||||||
|
·
|
||||||
|
<a href="contact.html">Contact</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Lua/C API Extensions</title>
|
<title>Lua/C API Extensions</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -37,6 +37,8 @@
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a class="current" href="ext_c_api.html">Lua/C API</a>
|
<a class="current" href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -173,7 +175,7 @@ Also note that this mechanism is not without overhead.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>FFI Library</title>
|
<title>FFI Library</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -37,6 +37,8 @@
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -316,7 +318,7 @@ without undue conversion penalties.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>ffi.* API Functions</title>
|
<title>ffi.* API Functions</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -42,6 +42,8 @@ td.abiparam { font-weight: bold; width: 6em; }
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -556,7 +558,7 @@ named <tt>i</tt>.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>FFI Semantics</title>
|
<title>FFI Semantics</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -42,6 +42,8 @@ td.convop { font-style: italic; width: 40%; }
|
|||||||
<a class="current" href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a class="current" href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -1246,7 +1248,7 @@ compiled.</li>
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>FFI Tutorial</title>
|
<title>FFI Tutorial</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -44,6 +44,8 @@ td.idiomlua b { font-weight: normal; color: #2142bf; }
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -587,7 +589,7 @@ it to a local variable in the function scope is unnecessary.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>jit.* Library</title>
|
<title>jit.* Library</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -37,6 +37,8 @@
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a class="current" href="ext_jit.html">jit.* Library</a>
|
<a class="current" href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -147,7 +149,7 @@ Contains the target OS name:
|
|||||||
<h3 id="jit_arch"><tt>jit.arch</tt></h3>
|
<h3 id="jit_arch"><tt>jit.arch</tt></h3>
|
||||||
<p>
|
<p>
|
||||||
Contains the target architecture name:
|
Contains the target architecture name:
|
||||||
"x86", "x64", "arm", "arm64", "ppc", "mips" or "mips64".
|
"x86", "x64", "arm", "arm64", "arm64be", "ppc", "mips", "mipsel", "mips64", "mips64el", "mips64r6", "mips64r6el".
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="jit_opt"><tt>jit.opt.*</tt> — JIT compiler optimization control</h2>
|
<h2 id="jit_opt"><tt>jit.opt.*</tt> — JIT compiler optimization control</h2>
|
||||||
@@ -185,7 +187,7 @@ if you want to know more.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Profiler</title>
|
<title>Profiler</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -37,6 +37,8 @@
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -349,7 +351,7 @@ use.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Extensions</title>
|
<title>Extensions</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -54,6 +54,8 @@ td.excinterop {
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -392,29 +394,19 @@ the toolchain used to compile LuaJIT:
|
|||||||
<td class="excinterop">Interoperability</td>
|
<td class="excinterop">Interoperability</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="odd separate">
|
<tr class="odd separate">
|
||||||
<td class="excplatform">POSIX/x64, DWARF2 unwinding</td>
|
<td class="excplatform">External frame unwinding</td>
|
||||||
<td class="exccompiler">GCC 4.3+, Clang</td>
|
<td class="exccompiler">GCC, Clang, MSVC</td>
|
||||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="even">
|
<tr class="even">
|
||||||
<td class="excplatform">ARM <tt>-DLUAJIT_UNWIND_EXTERNAL</tt></td>
|
<td class="excplatform">Internal frame unwinding + DWARF2</td>
|
||||||
<td class="exccompiler">GCC, Clang</td>
|
|
||||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd">
|
|
||||||
<td class="excplatform">Other platforms, DWARF2 unwinding</td>
|
|
||||||
<td class="exccompiler">GCC, Clang</td>
|
<td class="exccompiler">GCC, Clang</td>
|
||||||
<td class="excinterop"><b style="color: #c06000;">Limited</b></td>
|
<td class="excinterop"><b style="color: #c06000;">Limited</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="even">
|
|
||||||
<td class="excplatform">Windows/x64</td>
|
|
||||||
<td class="exccompiler">MSVC</td>
|
|
||||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
|
||||||
</tr>
|
|
||||||
<tr class="odd">
|
<tr class="odd">
|
||||||
<td class="excplatform">Windows/x86</td>
|
<td class="excplatform">Windows 64 bit</td>
|
||||||
<td class="exccompiler">Any</td>
|
<td class="exccompiler">non-MSVC</td>
|
||||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
<td class="excinterop"><b style="color: #c06000;">Limited</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="even">
|
<tr class="even">
|
||||||
<td class="excplatform">Other platforms</td>
|
<td class="excplatform">Other platforms</td>
|
||||||
@@ -435,7 +427,9 @@ the toolchain used to compile LuaJIT:
|
|||||||
on the C stack. The contents of the C++ exception object
|
on the C stack. The contents of the C++ exception object
|
||||||
pass through unmodified.</li>
|
pass through unmodified.</li>
|
||||||
<li>Lua errors can be caught on the C++ side with <tt>catch(...)</tt>.
|
<li>Lua errors can be caught on the C++ side with <tt>catch(...)</tt>.
|
||||||
The corresponding Lua error message can be retrieved from the Lua stack.</li>
|
The corresponding Lua error message can be retrieved from the Lua stack.<br>
|
||||||
|
For MSVC for Windows 64 bit this requires compilation of your C++ code
|
||||||
|
with <tt>/EHa</tt>.</li>
|
||||||
<li>Throwing Lua errors across C++ frames is safe. C++ destructors
|
<li>Throwing Lua errors across C++ frames is safe. C++ destructors
|
||||||
will be called.</li>
|
will be called.</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -470,7 +464,7 @@ C++ destructors.</li>
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
+42
-47
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Frequently Asked Questions (FAQ)</title>
|
<title>Frequently Asked Questions (FAQ)</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -40,6 +40,8 @@ dd { margin-left: 1.5em; }
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -74,22 +76,20 @@ about LuaJIT.</li>
|
|||||||
and links to books and papers about Lua.</li>
|
and links to books and papers about Lua.</li>
|
||||||
<li>The community-managed <a href="http://lua-users.org/wiki/"><span class="ext">»</span> Lua Wiki</a>
|
<li>The community-managed <a href="http://lua-users.org/wiki/"><span class="ext">»</span> Lua Wiki</a>
|
||||||
has information about diverse topics.</li>
|
has information about diverse topics.</li>
|
||||||
</ul>
|
</ul></dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl id="tech">
|
<dl id="tech">
|
||||||
<dt>Q: Where can I learn more about the compiler technology used by LuaJIT?</dt>
|
<dt>Q: Where can I learn more about the compiler technology used by LuaJIT?</dt>
|
||||||
<dd>
|
<dd>
|
||||||
I'm planning to write more documentation about the internals of LuaJIT.
|
Please use the following Google Scholar searches to find relevant papers:<br>
|
||||||
In the meantime, please use the following Google Scholar searches
|
|
||||||
to find relevant papers:<br>
|
|
||||||
Search for: <a href="https://scholar.google.com/scholar?q=Trace+Compiler"><span class="ext">»</span> Trace Compiler</a><br>
|
Search for: <a href="https://scholar.google.com/scholar?q=Trace+Compiler"><span class="ext">»</span> Trace Compiler</a><br>
|
||||||
Search for: <a href="https://scholar.google.com/scholar?q=JIT+Compiler"><span class="ext">»</span> JIT Compiler</a><br>
|
Search for: <a href="https://scholar.google.com/scholar?q=JIT+Compiler"><span class="ext">»</span> JIT Compiler</a><br>
|
||||||
Search for: <a href="https://scholar.google.com/scholar?q=Dynamic+Language+Optimizations"><span class="ext">»</span> Dynamic Language Optimizations</a><br>
|
Search for: <a href="https://scholar.google.com/scholar?q=Dynamic+Language+Optimizations"><span class="ext">»</span> Dynamic Language Optimizations</a><br>
|
||||||
Search for: <a href="https://scholar.google.com/scholar?q=SSA+Form"><span class="ext">»</span> SSA Form</a><br>
|
Search for: <a href="https://scholar.google.com/scholar?q=SSA+Form"><span class="ext">»</span> SSA Form</a><br>
|
||||||
Search for: <a href="https://scholar.google.com/scholar?q=Linear+Scan+Register+Allocation"><span class="ext">»</span> Linear Scan Register Allocation</a><br>
|
Search for: <a href="https://scholar.google.com/scholar?q=Linear+Scan+Register+Allocation"><span class="ext">»</span> Linear Scan Register Allocation</a><br>
|
||||||
Here is a list of the <a href="http://lua-users.org/lists/lua-l/2009-11/msg00089.html"><span class="ext">»</span> innovative features in LuaJIT</a>.<br>
|
Here is a list of the <a href="http://lua-users.org/lists/lua-l/2009-11/msg00089.html"><span class="ext">»</span> innovative features in LuaJIT</a>.<br>
|
||||||
And, you know, reading the source is of course the only way to enlightenment. :-)
|
And, you know, reading the source is of course the only way to enlightenment.
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
@@ -121,19 +121,30 @@ Consider testing your application with older versions, too.<br>
|
|||||||
|
|
||||||
Similarly, the Borland/Delphi runtime modifies the FPU control word and
|
Similarly, the Borland/Delphi runtime modifies the FPU control word and
|
||||||
enables FP exceptions. Of course this violates the Windows ABI, too.
|
enables FP exceptions. Of course this violates the Windows ABI, too.
|
||||||
Please check the Delphi docs for the Set8087CW method.
|
Please check the Delphi docs for the Set8087CW method.</dd>
|
||||||
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl id="ctrlc">
|
<dl id="ctrlc">
|
||||||
<dt>Q: Sometimes Ctrl-C fails to stop my Lua program. Why?</dt>
|
<dt>Q: Sometimes Ctrl-C fails to stop my Lua program. Why?</dt>
|
||||||
<dd>The interrupt signal handler sets a Lua debug hook. But this is
|
<dd>The interrupt signal handler sets a Lua debug hook. But this is
|
||||||
currently ignored by compiled code (this will eventually be fixed). If
|
ignored by compiled code. If your program is running in a tight loop
|
||||||
your program is running in a tight loop and never falls back to the
|
and never falls back to the interpreter, the debug hook never runs and
|
||||||
interpreter, the debug hook never runs and can't throw the
|
can't throw the "interrupted!" error.<br>
|
||||||
"interrupted!" error.<br> In the meantime you have to press Ctrl-C
|
You have to press Ctrl-C twice to get stop your program. That's similar
|
||||||
twice to get stop your program. That's similar to when it's stuck
|
to when it's stuck running inside a C function under the Lua interpreter.</dd>
|
||||||
running inside a C function under the Lua interpreter.</dd>
|
</dl>
|
||||||
|
|
||||||
|
<dl id="order">
|
||||||
|
<dt>Q: Table iteration with <tt>pairs()</tt> does not result in the same order?</dt>
|
||||||
|
<dd>The order of table iteration is explicitly <b>undefined</b> by
|
||||||
|
the Lua language standard.<br>
|
||||||
|
Different Lua implementations or versions may use different orders for
|
||||||
|
otherwise identical tables. Different ways of constructing a table may
|
||||||
|
result in different orders, too.<br>
|
||||||
|
Due to improved VM security, LuaJIT 2.1 may even use a different order
|
||||||
|
on separate VM invocations or when string keys are newly interned.<br><br>
|
||||||
|
If your program relies on a deterministic order, it has a bug. Rewrite it,
|
||||||
|
so it doesn't rely on the key order. Or sort the table keys, if you must.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl id="sandbox">
|
<dl id="sandbox">
|
||||||
@@ -147,30 +158,20 @@ it's very hard to get this right even for the Lua core libraries. Of course,
|
|||||||
you'll need to inspect any extension library, too. And there are libraries
|
you'll need to inspect any extension library, too. And there are libraries
|
||||||
that are inherently unsafe, e.g. the <a href="ext_ffi.html">FFI library</a>.<br>
|
that are inherently unsafe, e.g. the <a href="ext_ffi.html">FFI library</a>.<br>
|
||||||
|
|
||||||
Relatedly, <b>loading untrusted bytecode is not safe!</b> It's trivial
|
More reading material at the <a href="http://lua-users.org/wiki/SandBoxes"><span class="ext">»</span> Lua Wiki</a> and <a href="https://en.wikipedia.org/wiki/Sandbox_(computer_security)"><span class="ext">»</span> Wikipedia</a>.<br><br>
|
||||||
to crash the Lua or LuaJIT VM with maliciously crafted bytecode. This is
|
|
||||||
well known and there's no bytecode verification on purpose, so please
|
Relatedly, <b>loading untrusted bytecode is not safe!</b><br>
|
||||||
|
|
||||||
|
It's trivial to crash the Lua or LuaJIT VM with maliciously crafted bytecode.
|
||||||
|
This is well known and there's no bytecode verification on purpose, so please
|
||||||
don't report a bug about it. Check the <tt>mode</tt> parameter for the
|
don't report a bug about it. Check the <tt>mode</tt> parameter for the
|
||||||
<tt>load*()</tt> functions to disable loading of bytecode.<br>
|
<tt>load*()</tt> functions to disable loading of bytecode.<br><br>
|
||||||
|
|
||||||
In general, the only promising approach is to sandbox Lua code at the
|
<b>In general, the only promising approach is to sandbox Lua code at the
|
||||||
process level and not the VM level.<br>
|
process level and not the VM level.</b>
|
||||||
|
|
||||||
More reading material at the <a href="http://lua-users.org/wiki/SandBoxes"><span class="ext">»</span> Lua Wiki</a> and <a href="https://en.wikipedia.org/wiki/Sandbox_(computer_security)"><span class="ext">»</span> Wikipedia</a>.
|
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl id="patches">
|
|
||||||
<dt>Q: Why doesn't my favorite power-patch for Lua apply against LuaJIT?</dt>
|
|
||||||
<dd>Because it's a completely redesigned VM and has very little code
|
|
||||||
in common with Lua anymore. Also, if the patch introduces changes to
|
|
||||||
the Lua semantics, these would need to be reflected everywhere in the
|
|
||||||
VM, from the interpreter up to all stages of the compiler.<br> Please
|
|
||||||
use only standard Lua language constructs. For many common needs you
|
|
||||||
can use source transformations or use wrapper or proxy functions.
|
|
||||||
The compiler will happily optimize away such indirections.</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
<dl id="arch">
|
<dl id="arch">
|
||||||
<dt>Q: Lua runs everywhere. Why doesn't LuaJIT support my CPU?</dt>
|
<dt>Q: Lua runs everywhere. Why doesn't LuaJIT support my CPU?</dt>
|
||||||
<dd>Because it's a compiler — it needs to generate native
|
<dd>Because it's a compiler — it needs to generate native
|
||||||
@@ -178,23 +179,17 @@ machine code. This means the code generator must be ported to each
|
|||||||
architecture. And the fast interpreter is written in assembler and
|
architecture. And the fast interpreter is written in assembler and
|
||||||
must be ported, too. This is quite an undertaking.<br>
|
must be ported, too. This is quite an undertaking.<br>
|
||||||
The <a href="install.html">install documentation</a> shows the supported
|
The <a href="install.html">install documentation</a> shows the supported
|
||||||
architectures. Other architectures will follow based on sufficient user
|
architectures.<br>
|
||||||
demand and/or sponsoring.</dd>
|
Other architectures may follow based on sufficient user demand and
|
||||||
</dl>
|
market-relevance of the architecture. Sponsoring is required to develop
|
||||||
|
the port itself, to integrate it and to continuously maintain it in the
|
||||||
<dl id="when">
|
actively developed branches.</dd>
|
||||||
<dt>Q: When will feature X be added? When will the next version be released?</dt>
|
|
||||||
<dd>When it's ready.<br>
|
|
||||||
C'mon, it's open source — I'm doing it on my own time and you're
|
|
||||||
getting it for free. You can either contribute a patch or sponsor
|
|
||||||
the development of certain features, if they are important to you.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
<br class="flush">
|
<br class="flush">
|
||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Installation</title>
|
<title>Installation</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -65,6 +65,8 @@ td.compatno {
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -103,8 +105,8 @@ operating systems, CPUs and compilers:
|
|||||||
<td class="compatcpu">CPU / OS</td>
|
<td class="compatcpu">CPU / OS</td>
|
||||||
<td class="compatos"><a href="#posix">Linux</a> or<br><a href="#android">Android</a></td>
|
<td class="compatos"><a href="#posix">Linux</a> or<br><a href="#android">Android</a></td>
|
||||||
<td class="compatos"><a href="#posix">*BSD, Other</a></td>
|
<td class="compatos"><a href="#posix">*BSD, Other</a></td>
|
||||||
<td class="compatos"><a href="#posix">OSX 10.4+</a> or<br><a href="#ios">iOS 3.0+</a></td>
|
<td class="compatos"><a href="#posix">macOS 10.4+</a> or<br><a href="#ios">iOS 3.0+</a></td>
|
||||||
<td class="compatos"><a href="#windows">Windows<br>XP/Vista/7</a></td>
|
<td class="compatos"><a href="#windows">Windows 7<br>or later</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="odd separate">
|
<tr class="odd separate">
|
||||||
<td class="compatcpu">x86 (32 bit)</td>
|
<td class="compatcpu">x86 (32 bit)</td>
|
||||||
@@ -128,7 +130,7 @@ operating systems, CPUs and compilers:
|
|||||||
<td class="compatos compatno"> </td>
|
<td class="compatos compatno"> </td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="even">
|
<tr class="even">
|
||||||
<td class="compatcpu"><a href="#cross2">ARM64</a></td>
|
<td class="compatcpu"><a href="#cross2">ARM64<br>ARM64be</a></td>
|
||||||
<td class="compatos">GCC 4.8+</td>
|
<td class="compatos">GCC 4.8+</td>
|
||||||
<td class="compatos compatno"> </td>
|
<td class="compatos compatno"> </td>
|
||||||
<td class="compatos">XCode 6.0+<br>Clang 3.5+</td>
|
<td class="compatos">XCode 6.0+<br>Clang 3.5+</td>
|
||||||
@@ -142,7 +144,7 @@ operating systems, CPUs and compilers:
|
|||||||
<td class="compatos">XEDK (<a href="#xbox360">Xbox 360</a>)</td>
|
<td class="compatos">XEDK (<a href="#xbox360">Xbox 360</a>)</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="even">
|
<tr class="even">
|
||||||
<td class="compatcpu"><a href="#cross2">MIPS32<br>MIPS64</a></td>
|
<td class="compatcpu"><a href="#cross2">MIPS32<br>MIPS64<br>MIPS64r6</a></td>
|
||||||
<td class="compatos">GCC 4.3+</td>
|
<td class="compatos">GCC 4.3+</td>
|
||||||
<td class="compatos">GCC 4.3+</td>
|
<td class="compatos">GCC 4.3+</td>
|
||||||
<td class="compatos compatno"> </td>
|
<td class="compatos compatno"> </td>
|
||||||
@@ -177,7 +179,7 @@ Please check the note about the
|
|||||||
<a href="extensions.html#string_dump">bytecode format</a> differences, too.
|
<a href="extensions.html#string_dump">bytecode format</a> differences, too.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2 id="posix">POSIX Systems (Linux, OSX, *BSD etc.)</h2>
|
<h2 id="posix">POSIX Systems (Linux, macOS, *BSD etc.)</h2>
|
||||||
<h3>Prerequisites</h3>
|
<h3>Prerequisites</h3>
|
||||||
<p>
|
<p>
|
||||||
Depending on your distribution, you may need to install a package for
|
Depending on your distribution, you may need to install a package for
|
||||||
@@ -185,14 +187,19 @@ GCC, the development headers and/or a complete SDK. E.g. on a current
|
|||||||
Debian/Ubuntu, install <tt>libc6-dev</tt> with the package manager.
|
Debian/Ubuntu, install <tt>libc6-dev</tt> with the package manager.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Download the current source package of LuaJIT (pick the .tar.gz),
|
The recommended way to fetch the latest version is to do a pull from
|
||||||
if you haven't already done so. Move it to a directory of your choice,
|
the git repository.
|
||||||
open a terminal window and change to this directory. Now unpack the archive
|
</p>
|
||||||
and change to the newly created directory:
|
<p>
|
||||||
|
Alternatively download the latest source package of LuaJIT (pick the .tar.gz).
|
||||||
|
Move it to a directory of your choice, open a terminal window and change
|
||||||
|
to this directory. Now unpack the archive and change to the newly created
|
||||||
|
directory (replace XX.YY.ZZ with the version you downloaded):
|
||||||
</p>
|
</p>
|
||||||
<pre class="code">
|
<pre class="code">
|
||||||
tar zxf LuaJIT-2.0.5.tar.gz
|
tar zxf LuaJIT-XX.YY.ZZ.tar.gz
|
||||||
cd LuaJIT-2.0.5</pre>
|
cd LuaJIT-XX.YY.ZZ
|
||||||
|
</pre>
|
||||||
<h3>Building LuaJIT</h3>
|
<h3>Building LuaJIT</h3>
|
||||||
<p>
|
<p>
|
||||||
The supplied Makefiles try to auto-detect the settings needed for your
|
The supplied Makefiles try to auto-detect the settings needed for your
|
||||||
@@ -216,9 +223,12 @@ You can add an extra prefix to the search paths by appending the
|
|||||||
make PREFIX=/home/myself/lj2
|
make PREFIX=/home/myself/lj2
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
Note for OSX: you must set the <tt>MACOSX_DEPLOYMENT_TARGET</tt>
|
Note for macOS: you <b>must</b> set the <tt>MACOSX_DEPLOYMENT_TARGET</tt>
|
||||||
environment variable to a value supported by your toolchain.
|
environment variable to a value supported by your toolchain:
|
||||||
</p>
|
</p>
|
||||||
|
<pre class="code">
|
||||||
|
MACOSX_DEPLOYMENT_TARGET=XX.YY make
|
||||||
|
</pre>
|
||||||
<h3>Installing LuaJIT</h3>
|
<h3>Installing LuaJIT</h3>
|
||||||
<p>
|
<p>
|
||||||
The top-level Makefile installs LuaJIT by default under
|
The top-level Makefile installs LuaJIT by default under
|
||||||
@@ -250,8 +260,9 @@ GCC plus the required development headers.
|
|||||||
Or install Microsoft's Visual Studio (MSVC).
|
Or install Microsoft's Visual Studio (MSVC).
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Next, download the source package and unpack it using an archive manager
|
Next, pull from the git repository or download the source package and
|
||||||
(e.g. the Windows Explorer) to a directory of your choice.
|
unpack it using an archive manager (e.g. the Windows Explorer) to
|
||||||
|
a directory of your choice.
|
||||||
</p>
|
</p>
|
||||||
<h3>Building with MSVC</h3>
|
<h3>Building with MSVC</h3>
|
||||||
<p>
|
<p>
|
||||||
@@ -269,8 +280,8 @@ Then follow the installation instructions below.
|
|||||||
<h3>Building with MinGW or Cygwin</h3>
|
<h3>Building with MinGW or Cygwin</h3>
|
||||||
<p>
|
<p>
|
||||||
Open a command prompt window and make sure the MinGW or Cygwin programs
|
Open a command prompt window and make sure the MinGW or Cygwin programs
|
||||||
are in your path. Then <tt>cd</tt> to the directory where
|
are in your path. Then <tt>cd</tt> to the directory of the git repository
|
||||||
you've unpacked the sources and run this command for MinGW:
|
or where you've unpacked the sources. Then run this command for MinGW:
|
||||||
</p>
|
</p>
|
||||||
<pre class="code">
|
<pre class="code">
|
||||||
mingw32-make
|
mingw32-make
|
||||||
@@ -325,7 +336,7 @@ You need to specify <tt>TARGET_SYS</tt> whenever the host OS and the
|
|||||||
target OS differ, or you'll get assembler or linker errors:
|
target OS differ, or you'll get assembler or linker errors:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>E.g. if you're compiling on a Windows or OSX host for embedded Linux or Android, you need to add <tt>TARGET_SYS=Linux</tt> to the examples below.</li>
|
<li>E.g. if you're compiling on a Windows or macOS host for embedded Linux or Android, you need to add <tt>TARGET_SYS=Linux</tt> to the examples below.</li>
|
||||||
<li>For a minimal target OS, you may need to disable the built-in allocator in <tt>src/Makefile</tt> and use <tt>TARGET_SYS=Other</tt>.</li>
|
<li>For a minimal target OS, you may need to disable the built-in allocator in <tt>src/Makefile</tt> and use <tt>TARGET_SYS=Other</tt>.</li>
|
||||||
<li>Don't forget to specify the same <tt>TARGET_SYS</tt> for the install step, too.</li>
|
<li>Don't forget to specify the same <tt>TARGET_SYS</tt> for the install step, too.</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -400,7 +411,8 @@ NDKCROSS=$NDKBIN/aarch64-linux-android-
|
|||||||
NDKCC=$NDKBIN/aarch64-linux-android21-clang
|
NDKCC=$NDKBIN/aarch64-linux-android21-clang
|
||||||
make CROSS=$NDKCROSS \
|
make CROSS=$NDKCROSS \
|
||||||
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
|
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
|
||||||
TARGET_LD=$NDKCC
|
TARGET_LD=$NDKCC TARGET_AR=$NDKBIN/llvm-ar
|
||||||
|
TARGET_STRIP=$NDKBIN/llvm-strip
|
||||||
|
|
||||||
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.1+ (JB)
|
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.1+ (JB)
|
||||||
NDKDIR=/opt/android/ndk
|
NDKDIR=/opt/android/ndk
|
||||||
@@ -409,7 +421,8 @@ NDKCROSS=$NDKBIN/arm-linux-androideabi-
|
|||||||
NDKCC=$NDKBIN/armv7a-linux-androideabi16-clang
|
NDKCC=$NDKBIN/armv7a-linux-androideabi16-clang
|
||||||
make HOST_CC="gcc -m32" CROSS=$NDKCROSS \
|
make HOST_CC="gcc -m32" CROSS=$NDKCROSS \
|
||||||
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
|
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
|
||||||
TARGET_LD=$NDKCC
|
TARGET_LD=$NDKCC TARGET_AR=$NDKBIN/llvm-ar
|
||||||
|
TARGET_STRIP=$NDKBIN/llvm-strip
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
You can cross-compile for <b id="ios">iOS 3.0+</b> (iPhone/iPad) using the <a href="https://developer.apple.com/ios/"><span class="ext">»</span> iOS SDK</a>:
|
You can cross-compile for <b id="ios">iOS 3.0+</b> (iPhone/iPad) using the <a href="https://developer.apple.com/ios/"><span class="ext">»</span> iOS SDK</a>:
|
||||||
@@ -522,14 +535,6 @@ the DLL). You may link LuaJIT statically on Windows only if you don't
|
|||||||
intend to load Lua/C modules at runtime.
|
intend to load Lua/C modules at runtime.
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
If you're building a 64 bit application on OSX which links directly or
|
|
||||||
indirectly against LuaJIT which is not built for <tt>LJ_GC64</tt> mode,
|
|
||||||
you need to link your main executable with these flags:
|
|
||||||
<pre class="code">
|
|
||||||
-pagezero_size 10000 -image_base 100000000
|
|
||||||
</pre>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<p>Additional hints for initializing LuaJIT using the C API functions:</p>
|
<p>Additional hints for initializing LuaJIT using the C API functions:</p>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -538,7 +543,7 @@ you need to link your main executable with these flags:
|
|||||||
for embedding Lua or LuaJIT into your application.</li>
|
for embedding Lua or LuaJIT into your application.</li>
|
||||||
<li>Make sure you use <tt>luaL_newstate</tt>. Avoid using
|
<li>Make sure you use <tt>luaL_newstate</tt>. Avoid using
|
||||||
<tt>lua_newstate</tt>, since this uses the (slower) default memory
|
<tt>lua_newstate</tt>, since this uses the (slower) default memory
|
||||||
allocator from your system (no support for this on x64).</li>
|
allocator from your system (no support for this on 64 bit architectures).</li>
|
||||||
<li>Make sure you use <tt>luaL_openlibs</tt> and not the old Lua 5.0 style
|
<li>Make sure you use <tt>luaL_openlibs</tt> and not the old Lua 5.0 style
|
||||||
of calling <tt>luaopen_base</tt> etc. directly.</li>
|
of calling <tt>luaopen_base</tt> etc. directly.</li>
|
||||||
<li>To change or extend the list of standard libraries to load, copy
|
<li>To change or extend the list of standard libraries to load, copy
|
||||||
@@ -614,7 +619,7 @@ to me (the upstream) and not you (the package maintainer), anyway.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>LuaJIT</title>
|
<title>LuaJIT</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -122,6 +122,8 @@ table.feature small {
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -146,7 +148,7 @@ Lua is a powerful, dynamic and light-weight programming language.
|
|||||||
It may be embedded or used as a general-purpose, stand-alone language.
|
It may be embedded or used as a general-purpose, stand-alone language.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
LuaJIT is Copyright © 2005-2020 Mike Pall, released under the
|
LuaJIT is Copyright © 2005-2021 Mike Pall, released under the
|
||||||
<a href="https://www.opensource.org/licenses/mit-license.php"><span class="ext">»</span> MIT open source license</a>.
|
<a href="https://www.opensource.org/licenses/mit-license.php"><span class="ext">»</span> MIT open source license</a>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -154,7 +156,7 @@ LuaJIT is Copyright © 2005-2020 Mike Pall, released under the
|
|||||||
|
|
||||||
<h2>Compatibility</h2>
|
<h2>Compatibility</h2>
|
||||||
<table class="feature os os1">
|
<table class="feature os os1">
|
||||||
<tr><td>Windows</td><td>Linux</td><td>BSD</td><td>OSX</td><td>POSIX</td></tr>
|
<tr><td>Windows</td><td>Linux</td><td>BSD</td><td>macOS</td><td>POSIX</td></tr>
|
||||||
</table>
|
</table>
|
||||||
<table class="feature os os2">
|
<table class="feature os os2">
|
||||||
<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td></tr>
|
<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td></tr>
|
||||||
@@ -220,7 +222,7 @@ Please select a sub-topic in the navigation bar to learn more about LuaJIT.
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Running LuaJIT</title>
|
<title>Running LuaJIT</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -59,6 +59,8 @@ td.param_default {
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -183,8 +185,8 @@ itself. For a description of their options and output format, please
|
|||||||
read the comment block at the start of their source.
|
read the comment block at the start of their source.
|
||||||
They can be found in the <tt>lib</tt> directory of the source
|
They can be found in the <tt>lib</tt> directory of the source
|
||||||
distribution or installed under the <tt>jit</tt> directory. By default
|
distribution or installed under the <tt>jit</tt> directory. By default
|
||||||
this is <tt>/usr/local/share/luajit-2.0.5/jit</tt> on POSIX
|
this is <tt>/usr/local/share/luajit-XX.YY.ZZ>/jit</tt> on POSIX
|
||||||
systems.
|
systems (replace XX.YY.ZZ by the installed version).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3 id="opt_O"><tt>-O[level]</tt><br>
|
<h3 id="opt_O"><tt>-O[level]</tt><br>
|
||||||
@@ -293,7 +295,7 @@ Here are the parameters and their default settings:
|
|||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
+15
-14
@@ -1,9 +1,9 @@
|
|||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Status</title>
|
<title>Status</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
<meta charset="utf-8">
|
||||||
<meta name="Copyright" content="Copyright (C) 2005-2020">
|
<meta name="Copyright" content="Copyright (C) 2005-2021">
|
||||||
<meta name="Language" content="en">
|
<meta name="Language" content="en">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
|
||||||
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
|
||||||
@@ -40,6 +40,8 @@ ul li { padding-bottom: 0.3em; }
|
|||||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||||
</li></ul>
|
</li></ul>
|
||||||
</li><li>
|
</li><li>
|
||||||
|
<a href="ext_buffer.html">String Buffers</a>
|
||||||
|
</li><li>
|
||||||
<a href="ext_jit.html">jit.* Library</a>
|
<a href="ext_jit.html">jit.* Library</a>
|
||||||
</li><li>
|
</li><li>
|
||||||
<a href="ext_c_api.html">Lua/C API</a>
|
<a href="ext_c_api.html">Lua/C API</a>
|
||||||
@@ -58,9 +60,15 @@ ul li { padding-bottom: 0.3em; }
|
|||||||
</div>
|
</div>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
<p>
|
<p>
|
||||||
<span style="color: #0000c0;">LuaJIT 2.0</span> is the current
|
This documentation is for LuaJIT 2.1.0-beta3. Please check the <tt>doc</tt>
|
||||||
<span style="color: #0000c0;">stable branch</span>. This branch is in
|
directory in each git branch for the version-specific documentation.
|
||||||
feature-freeze — new features will only be added to LuaJIT 2.1.
|
</p>
|
||||||
|
<p>
|
||||||
|
The currently developed branches are LuaJIT 2.1 and LuaJIT 2.0.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
LuaJIT 2.0 is in feature-freeze — new features will only
|
||||||
|
be added to LuaJIT 2.1.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Current Status</h2>
|
<h2>Current Status</h2>
|
||||||
@@ -84,19 +92,12 @@ The Lua <b>debug API</b> is missing a couple of features (return
|
|||||||
hooks for non-Lua functions) and shows slightly different behavior
|
hooks for non-Lua functions) and shows slightly different behavior
|
||||||
in LuaJIT (no per-coroutine hooks, no tail call counting).
|
in LuaJIT (no per-coroutine hooks, no tail call counting).
|
||||||
</li>
|
</li>
|
||||||
<li>
|
|
||||||
Currently some <b>out-of-memory</b> errors from <b>on-trace code</b> are not
|
|
||||||
handled correctly. The error may fall through an on-trace
|
|
||||||
<tt>pcall</tt> or it may be passed on to the function set with
|
|
||||||
<tt>lua_atpanic</tt> on x64. This issue will be fixed with the new
|
|
||||||
garbage collector.
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<br class="flush">
|
<br class="flush">
|
||||||
</div>
|
</div>
|
||||||
<div id="foot">
|
<div id="foot">
|
||||||
<hr class="hide">
|
<hr class="hide">
|
||||||
Copyright © 2005-2020
|
Copyright © 2005-2021
|
||||||
<span class="noprint">
|
<span class="noprint">
|
||||||
·
|
·
|
||||||
<a href="contact.html">Contact</a>
|
<a href="contact.html">Contact</a>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM ARM encoding engine.
|
** DynASM ARM encoding engine.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -294,7 +294,7 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||||||
|
|
||||||
{ /* Handle globals not defined in this translation unit. */
|
{ /* Handle globals not defined in this translation unit. */
|
||||||
int idx;
|
int idx;
|
||||||
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
|
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
|
||||||
int n = D->lglabels[idx];
|
int n = D->lglabels[idx];
|
||||||
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
||||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
||||||
@@ -371,7 +371,10 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||||||
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
|
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
|
||||||
break;
|
break;
|
||||||
case DASM_REL_LG:
|
case DASM_REL_LG:
|
||||||
CK(n >= 0, UNDEF_LG);
|
if (n < 0) {
|
||||||
|
n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp - 4);
|
||||||
|
goto patchrel;
|
||||||
|
}
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case DASM_REL_PC:
|
case DASM_REL_PC:
|
||||||
CK(n >= 0, UNDEF_PC);
|
CK(n >= 0, UNDEF_PC);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM ARM module.
|
-- DynASM ARM module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
local _info = {
|
local _info = {
|
||||||
arch = "arm",
|
arch = "arm",
|
||||||
description = "DynASM ARM module",
|
description = "DynASM ARM module",
|
||||||
version = "1.4.0",
|
version = "1.5.0",
|
||||||
vernum = 10400,
|
vernum = 10500,
|
||||||
release = "2015-10-18",
|
release = "2021-05-02",
|
||||||
author = "Mike Pall",
|
author = "Mike Pall",
|
||||||
license = "MIT",
|
license = "MIT",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM ARM64 encoding engine.
|
** DynASM ARM64 encoding engine.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -21,8 +21,9 @@ enum {
|
|||||||
/* The following actions need a buffer position. */
|
/* The following actions need a buffer position. */
|
||||||
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
|
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
|
||||||
/* The following actions also have an argument. */
|
/* The following actions also have an argument. */
|
||||||
DASM_REL_PC, DASM_LABEL_PC,
|
DASM_REL_PC, DASM_LABEL_PC, DASM_REL_A,
|
||||||
DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
|
DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
|
||||||
|
DASM_IMMV, DASM_VREG,
|
||||||
DASM__MAX
|
DASM__MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ enum {
|
|||||||
#define DASM_S_RANGE_LG 0x13000000
|
#define DASM_S_RANGE_LG 0x13000000
|
||||||
#define DASM_S_RANGE_PC 0x14000000
|
#define DASM_S_RANGE_PC 0x14000000
|
||||||
#define DASM_S_RANGE_REL 0x15000000
|
#define DASM_S_RANGE_REL 0x15000000
|
||||||
|
#define DASM_S_RANGE_VREG 0x16000000
|
||||||
#define DASM_S_UNDEF_LG 0x21000000
|
#define DASM_S_UNDEF_LG 0x21000000
|
||||||
#define DASM_S_UNDEF_PC 0x22000000
|
#define DASM_S_UNDEF_PC 0x22000000
|
||||||
|
|
||||||
@@ -247,7 +249,7 @@ void dasm_put(Dst_DECL, int start, ...)
|
|||||||
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
|
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
|
||||||
D->section = &D->sections[n]; goto stop;
|
D->section = &D->sections[n]; goto stop;
|
||||||
case DASM_ESC: p++; ofs += 4; break;
|
case DASM_ESC: p++; ofs += 4; break;
|
||||||
case DASM_REL_EXT: break;
|
case DASM_REL_EXT: if ((ins & 0x8000)) ofs += 8; break;
|
||||||
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
|
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
|
||||||
case DASM_REL_LG:
|
case DASM_REL_LG:
|
||||||
n = (ins & 2047) - 10; pl = D->lglabels + n;
|
n = (ins & 2047) - 10; pl = D->lglabels + n;
|
||||||
@@ -268,6 +270,11 @@ void dasm_put(Dst_DECL, int start, ...)
|
|||||||
*pl = pos;
|
*pl = pos;
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
|
if ((ins & 0x8000)) ofs += 8;
|
||||||
|
break;
|
||||||
|
case DASM_REL_A:
|
||||||
|
b[pos++] = n;
|
||||||
|
b[pos++] = va_arg(ap, int);
|
||||||
break;
|
break;
|
||||||
case DASM_LABEL_LG:
|
case DASM_LABEL_LG:
|
||||||
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
|
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
|
||||||
@@ -312,13 +319,21 @@ void dasm_put(Dst_DECL, int start, ...)
|
|||||||
}
|
}
|
||||||
case DASM_IMML: {
|
case DASM_IMML: {
|
||||||
#ifdef DASM_CHECKS
|
#ifdef DASM_CHECKS
|
||||||
int scale = (p[-2] >> 30);
|
int scale = (ins & 3);
|
||||||
CK((!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ||
|
CK((!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ||
|
||||||
(unsigned int)(n+256) < 512, RANGE_I);
|
(unsigned int)(n+256) < 512, RANGE_I);
|
||||||
#endif
|
#endif
|
||||||
b[pos++] = n;
|
b[pos++] = n;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DASM_IMMV:
|
||||||
|
ofs += 4;
|
||||||
|
b[pos++] = n;
|
||||||
|
break;
|
||||||
|
case DASM_VREG:
|
||||||
|
CK(n < 32, RANGE_VREG);
|
||||||
|
b[pos++] = n;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,7 +363,7 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||||||
|
|
||||||
{ /* Handle globals not defined in this translation unit. */
|
{ /* Handle globals not defined in this translation unit. */
|
||||||
int idx;
|
int idx;
|
||||||
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
|
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
|
||||||
int n = D->lglabels[idx];
|
int n = D->lglabels[idx];
|
||||||
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
||||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
||||||
@@ -375,8 +390,8 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||||||
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
|
case DASM_REL_LG: case DASM_REL_PC: pos++; break;
|
||||||
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
|
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
|
||||||
case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
|
case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
|
||||||
case DASM_IMML: pos++; break;
|
case DASM_IMML: case DASM_IMMV: case DASM_VREG: pos++; break;
|
||||||
case DASM_IMM13X: pos += 2; break;
|
case DASM_IMM13X: case DASM_REL_A: pos += 2; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stop: (void)0;
|
stop: (void)0;
|
||||||
@@ -426,7 +441,12 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||||||
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
|
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
|
||||||
break;
|
break;
|
||||||
case DASM_REL_LG:
|
case DASM_REL_LG:
|
||||||
CK(n >= 0, UNDEF_LG);
|
if (n < 0) {
|
||||||
|
ptrdiff_t na = (ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp + 4;
|
||||||
|
n = (int)na;
|
||||||
|
CK((ptrdiff_t)n == na, RANGE_REL);
|
||||||
|
goto patchrel;
|
||||||
|
}
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case DASM_REL_PC:
|
case DASM_REL_PC:
|
||||||
CK(n >= 0, UNDEF_PC);
|
CK(n >= 0, UNDEF_PC);
|
||||||
@@ -446,8 +466,24 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||||||
} else if ((ins & 0x1000)) { /* TBZ, TBNZ */
|
} else if ((ins & 0x1000)) { /* TBZ, TBNZ */
|
||||||
CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL);
|
CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL);
|
||||||
cp[-1] |= ((n << 3) & 0x0007ffe0);
|
cp[-1] |= ((n << 3) & 0x0007ffe0);
|
||||||
|
} else if ((ins & 0x8000)) { /* absolute */
|
||||||
|
cp[0] = (unsigned int)((ptrdiff_t)cp - 4 + n);
|
||||||
|
cp[1] = (unsigned int)(((ptrdiff_t)cp - 4 + n) >> 32);
|
||||||
|
cp += 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DASM_REL_A: {
|
||||||
|
ptrdiff_t na = (((ptrdiff_t)(*b++) << 32) | (unsigned int)n);
|
||||||
|
if ((ins & 0x3000) == 0x3000) { /* ADRP */
|
||||||
|
ins &= ~0x1000;
|
||||||
|
na = (na >> 12) - (((ptrdiff_t)cp - 4) >> 12);
|
||||||
|
} else {
|
||||||
|
na = na - (ptrdiff_t)cp + 4;
|
||||||
|
}
|
||||||
|
n = (int)na;
|
||||||
|
CK((ptrdiff_t)n == na, RANGE_REL);
|
||||||
|
goto patchrel;
|
||||||
|
}
|
||||||
case DASM_LABEL_LG:
|
case DASM_LABEL_LG:
|
||||||
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
|
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
|
||||||
break;
|
break;
|
||||||
@@ -468,11 +504,17 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||||||
cp[-1] |= (dasm_imm13(n, *b++) << 10);
|
cp[-1] |= (dasm_imm13(n, *b++) << 10);
|
||||||
break;
|
break;
|
||||||
case DASM_IMML: {
|
case DASM_IMML: {
|
||||||
int scale = (p[-2] >> 30);
|
int scale = (ins & 3);
|
||||||
cp[-1] |= (!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ?
|
cp[-1] |= (!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ?
|
||||||
((n << (10-scale)) | 0x01000000) : ((n & 511) << 12);
|
((n << (10-scale)) | 0x01000000) : ((n & 511) << 12);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DASM_IMMV:
|
||||||
|
*cp++ = n;
|
||||||
|
break;
|
||||||
|
case DASM_VREG:
|
||||||
|
cp[-1] |= (n & 0x1f) << (ins & 0x1f);
|
||||||
|
break;
|
||||||
default: *cp++ = ins; break;
|
default: *cp++ = ins; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM ARM64 module.
|
-- DynASM ARM64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
local _info = {
|
local _info = {
|
||||||
arch = "arm",
|
arch = "arm",
|
||||||
description = "DynASM ARM64 module",
|
description = "DynASM ARM64 module",
|
||||||
version = "1.4.0",
|
version = "1.5.0",
|
||||||
vernum = 10400,
|
vernum = 10500,
|
||||||
release = "2015-10-18",
|
release = "2021-05-02",
|
||||||
author = "Mike Pall",
|
author = "Mike Pall",
|
||||||
license = "MIT",
|
license = "MIT",
|
||||||
}
|
}
|
||||||
@@ -23,12 +23,12 @@ local _M = { _info = _info }
|
|||||||
local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
|
local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
|
||||||
local assert, setmetatable, rawget = assert, setmetatable, rawget
|
local assert, setmetatable, rawget = assert, setmetatable, rawget
|
||||||
local _s = string
|
local _s = string
|
||||||
local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
|
local format, byte, char = _s.format, _s.byte, _s.char
|
||||||
local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
|
local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
|
||||||
local concat, sort, insert = table.concat, table.sort, table.insert
|
local concat, sort, insert = table.concat, table.sort, table.insert
|
||||||
local bit = bit or require("bit")
|
local bit = bit or require("bit")
|
||||||
local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
|
local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
|
||||||
local ror, tohex = bit.ror, bit.tohex
|
local ror, tohex, tobit = bit.ror, bit.tohex, bit.tobit
|
||||||
|
|
||||||
-- Inherited tables and callbacks.
|
-- Inherited tables and callbacks.
|
||||||
local g_opt, g_arch
|
local g_opt, g_arch
|
||||||
@@ -39,7 +39,9 @@ local wline, werror, wfatal, wwarn
|
|||||||
local action_names = {
|
local action_names = {
|
||||||
"STOP", "SECTION", "ESC", "REL_EXT",
|
"STOP", "SECTION", "ESC", "REL_EXT",
|
||||||
"ALIGN", "REL_LG", "LABEL_LG",
|
"ALIGN", "REL_LG", "LABEL_LG",
|
||||||
"REL_PC", "LABEL_PC", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML",
|
"REL_PC", "LABEL_PC", "REL_A",
|
||||||
|
"IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", "IMMV",
|
||||||
|
"VREG",
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Maximum number of section buffer positions for dasm_put().
|
-- Maximum number of section buffer positions for dasm_put().
|
||||||
@@ -246,9 +248,12 @@ local map_cond = {
|
|||||||
|
|
||||||
local parse_reg_type
|
local parse_reg_type
|
||||||
|
|
||||||
local function parse_reg(expr)
|
local function parse_reg(expr, shift)
|
||||||
if not expr then werror("expected register name") end
|
if not expr then werror("expected register name") end
|
||||||
local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$")
|
local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$")
|
||||||
|
if not tname then
|
||||||
|
tname, ovreg = match(expr, "^([%w_]+):(R[xwqdshb]%b())$")
|
||||||
|
end
|
||||||
local tp = map_type[tname or expr]
|
local tp = map_type[tname or expr]
|
||||||
if tp then
|
if tp then
|
||||||
local reg = ovreg or tp.reg
|
local reg = ovreg or tp.reg
|
||||||
@@ -266,18 +271,28 @@ local function parse_reg(expr)
|
|||||||
elseif parse_reg_type ~= rt then
|
elseif parse_reg_type ~= rt then
|
||||||
werror("register size mismatch")
|
werror("register size mismatch")
|
||||||
end
|
end
|
||||||
return r, tp
|
return shl(r, shift), tp
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
local vrt, vreg = match(expr, "^R([xwqdshb])(%b())$")
|
||||||
|
if vreg then
|
||||||
|
if not parse_reg_type then
|
||||||
|
parse_reg_type = vrt
|
||||||
|
elseif parse_reg_type ~= vrt then
|
||||||
|
werror("register size mismatch")
|
||||||
|
end
|
||||||
|
if shift then waction("VREG", shift, vreg) end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
werror("bad register name `"..expr.."'")
|
werror("bad register name `"..expr.."'")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function parse_reg_base(expr)
|
local function parse_reg_base(expr)
|
||||||
if expr == "sp" then return 0x3e0 end
|
if expr == "sp" then return 0x3e0 end
|
||||||
local base, tp = parse_reg(expr)
|
local base, tp = parse_reg(expr, 5)
|
||||||
if parse_reg_type ~= "x" then werror("bad register type") end
|
if parse_reg_type ~= "x" then werror("bad register type") end
|
||||||
parse_reg_type = false
|
parse_reg_type = false
|
||||||
return shl(base, 5), tp
|
return base, tp
|
||||||
end
|
end
|
||||||
|
|
||||||
local parse_ctx = {}
|
local parse_ctx = {}
|
||||||
@@ -297,7 +312,7 @@ local function parse_number(n)
|
|||||||
local code = loadenv("return "..n)
|
local code = loadenv("return "..n)
|
||||||
if code then
|
if code then
|
||||||
local ok, y = pcall(code)
|
local ok, y = pcall(code)
|
||||||
if ok then return y end
|
if ok and type(y) == "number" then return y end
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -403,7 +418,7 @@ local function parse_imm_load(imm, scale)
|
|||||||
end
|
end
|
||||||
werror("out of range immediate `"..imm.."'")
|
werror("out of range immediate `"..imm.."'")
|
||||||
else
|
else
|
||||||
waction("IMML", 0, imm)
|
waction("IMML", scale, imm)
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -462,6 +477,7 @@ end
|
|||||||
|
|
||||||
local function parse_load(params, nparams, n, op)
|
local function parse_load(params, nparams, n, op)
|
||||||
if params[n+2] then werror("too many operands") end
|
if params[n+2] then werror("too many operands") end
|
||||||
|
local scale = shr(op, 30)
|
||||||
local pn, p2 = params[n], params[n+1]
|
local pn, p2 = params[n], params[n+1]
|
||||||
local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
|
local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
|
||||||
if not p1 then
|
if not p1 then
|
||||||
@@ -470,14 +486,13 @@ local function parse_load(params, nparams, n, op)
|
|||||||
if reg and tailr ~= "" then
|
if reg and tailr ~= "" then
|
||||||
local base, tp = parse_reg_base(reg)
|
local base, tp = parse_reg_base(reg)
|
||||||
if tp then
|
if tp then
|
||||||
waction("IMML", 0, format(tp.ctypefmt, tailr))
|
waction("IMML", scale, format(tp.ctypefmt, tailr))
|
||||||
return op + base
|
return op + base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
werror("expected address operand")
|
werror("expected address operand")
|
||||||
end
|
end
|
||||||
local scale = shr(op, 30)
|
|
||||||
if p2 then
|
if p2 then
|
||||||
if wb == "!" then werror("bad use of '!'") end
|
if wb == "!" then werror("bad use of '!'") end
|
||||||
op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400
|
op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400
|
||||||
@@ -494,7 +509,7 @@ local function parse_load(params, nparams, n, op)
|
|||||||
op = op + parse_imm_load(imm, scale)
|
op = op + parse_imm_load(imm, scale)
|
||||||
else
|
else
|
||||||
local p2b, p3b, p3s = match(p2a, "^,%s*([^,%s]*)%s*,?%s*(%S*)%s*(.*)$")
|
local p2b, p3b, p3s = match(p2a, "^,%s*([^,%s]*)%s*,?%s*(%S*)%s*(.*)$")
|
||||||
op = op + shl(parse_reg(p2b), 16) + 0x00200800
|
op = op + parse_reg(p2b, 16) + 0x00200800
|
||||||
if parse_reg_type ~= "x" and parse_reg_type ~= "w" then
|
if parse_reg_type ~= "x" and parse_reg_type ~= "w" then
|
||||||
werror("bad index register type")
|
werror("bad index register type")
|
||||||
end
|
end
|
||||||
@@ -561,14 +576,14 @@ local function parse_load_pair(params, nparams, n, op)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function parse_label(label, def)
|
local function parse_label(label, def)
|
||||||
local prefix = sub(label, 1, 2)
|
local prefix = label:sub(1, 2)
|
||||||
-- =>label (pc label reference)
|
-- =>label (pc label reference)
|
||||||
if prefix == "=>" then
|
if prefix == "=>" then
|
||||||
return "PC", 0, sub(label, 3)
|
return "PC", 0, label:sub(3)
|
||||||
end
|
end
|
||||||
-- ->name (global label reference)
|
-- ->name (global label reference)
|
||||||
if prefix == "->" then
|
if prefix == "->" then
|
||||||
return "LG", map_global[sub(label, 3)]
|
return "LG", map_global[label:sub(3)]
|
||||||
end
|
end
|
||||||
if def then
|
if def then
|
||||||
-- [1-9] (local label definition)
|
-- [1-9] (local label definition)
|
||||||
@@ -586,8 +601,11 @@ local function parse_label(label, def)
|
|||||||
if extname then
|
if extname then
|
||||||
return "EXT", map_extern[extname]
|
return "EXT", map_extern[extname]
|
||||||
end
|
end
|
||||||
|
-- &expr (pointer)
|
||||||
|
if label:sub(1, 1) == "&" then
|
||||||
|
return "A", 0, format("(ptrdiff_t)(%s)", label:sub(2))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
werror("bad label `"..label.."'")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function branch_type(op)
|
local function branch_type(op)
|
||||||
@@ -620,24 +638,24 @@ local function alias_bfx(p)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function alias_bfiz(p)
|
local function alias_bfiz(p)
|
||||||
parse_reg(p[1])
|
parse_reg(p[1], 0)
|
||||||
if parse_reg_type == "w" then
|
if parse_reg_type == "w" then
|
||||||
p[3] = "#-("..p[3]:sub(2)..")%32"
|
p[3] = "#(32-("..p[3]:sub(2).."))%32"
|
||||||
p[4] = "#("..p[4]:sub(2)..")-1"
|
p[4] = "#("..p[4]:sub(2)..")-1"
|
||||||
else
|
else
|
||||||
p[3] = "#-("..p[3]:sub(2)..")%64"
|
p[3] = "#(64-("..p[3]:sub(2).."))%64"
|
||||||
p[4] = "#("..p[4]:sub(2)..")-1"
|
p[4] = "#("..p[4]:sub(2)..")-1"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local alias_lslimm = op_alias("ubfm_4", function(p)
|
local alias_lslimm = op_alias("ubfm_4", function(p)
|
||||||
parse_reg(p[1])
|
parse_reg(p[1], 0)
|
||||||
local sh = p[3]:sub(2)
|
local sh = p[3]:sub(2)
|
||||||
if parse_reg_type == "w" then
|
if parse_reg_type == "w" then
|
||||||
p[3] = "#-("..sh..")%32"
|
p[3] = "#(32-("..sh.."))%32"
|
||||||
p[4] = "#31-("..sh..")"
|
p[4] = "#31-("..sh..")"
|
||||||
else
|
else
|
||||||
p[3] = "#-("..sh..")%64"
|
p[3] = "#(64-("..sh.."))%64"
|
||||||
p[4] = "#63-("..sh..")"
|
p[4] = "#63-("..sh..")"
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
@@ -881,25 +899,25 @@ end
|
|||||||
|
|
||||||
-- Handle opcodes defined with template strings.
|
-- Handle opcodes defined with template strings.
|
||||||
local function parse_template(params, template, nparams, pos)
|
local function parse_template(params, template, nparams, pos)
|
||||||
local op = tonumber(sub(template, 1, 8), 16)
|
local op = tonumber(template:sub(1, 8), 16)
|
||||||
local n = 1
|
local n = 1
|
||||||
local rtt = {}
|
local rtt = {}
|
||||||
|
|
||||||
parse_reg_type = false
|
parse_reg_type = false
|
||||||
|
|
||||||
-- Process each character.
|
-- Process each character.
|
||||||
for p in gmatch(sub(template, 9), ".") do
|
for p in gmatch(template:sub(9), ".") do
|
||||||
local q = params[n]
|
local q = params[n]
|
||||||
if p == "D" then
|
if p == "D" then
|
||||||
op = op + parse_reg(q); n = n + 1
|
op = op + parse_reg(q, 0); n = n + 1
|
||||||
elseif p == "N" then
|
elseif p == "N" then
|
||||||
op = op + shl(parse_reg(q), 5); n = n + 1
|
op = op + parse_reg(q, 5); n = n + 1
|
||||||
elseif p == "M" then
|
elseif p == "M" then
|
||||||
op = op + shl(parse_reg(q), 16); n = n + 1
|
op = op + parse_reg(q, 16); n = n + 1
|
||||||
elseif p == "A" then
|
elseif p == "A" then
|
||||||
op = op + shl(parse_reg(q), 10); n = n + 1
|
op = op + parse_reg(q, 10); n = n + 1
|
||||||
elseif p == "m" then
|
elseif p == "m" then
|
||||||
op = op + shl(parse_reg(params[n-1]), 16)
|
op = op + parse_reg(params[n-1], 16)
|
||||||
|
|
||||||
elseif p == "p" then
|
elseif p == "p" then
|
||||||
if q == "sp" then params[n] = "@x31" end
|
if q == "sp" then params[n] = "@x31" end
|
||||||
@@ -930,8 +948,14 @@ local function parse_template(params, template, nparams, pos)
|
|||||||
|
|
||||||
elseif p == "B" then
|
elseif p == "B" then
|
||||||
local mode, v, s = parse_label(q, false); n = n + 1
|
local mode, v, s = parse_label(q, false); n = n + 1
|
||||||
|
if not mode then werror("bad label `"..q.."'") end
|
||||||
local m = branch_type(op)
|
local m = branch_type(op)
|
||||||
waction("REL_"..mode, v+m, s, 1)
|
if mode == "A" then
|
||||||
|
waction("REL_"..mode, v+m, format("(unsigned int)(%s)", s))
|
||||||
|
actargs[#actargs+1] = format("(unsigned int)((%s)>>32)", s)
|
||||||
|
else
|
||||||
|
waction("REL_"..mode, v+m, s, 1)
|
||||||
|
end
|
||||||
|
|
||||||
elseif p == "I" then
|
elseif p == "I" then
|
||||||
op = op + parse_imm12(q); n = n + 1
|
op = op + parse_imm12(q); n = n + 1
|
||||||
@@ -977,8 +1001,8 @@ function op_template(params, template, nparams)
|
|||||||
if not params then return template:gsub("%x%x%x%x%x%x%x%x", "") end
|
if not params then return template:gsub("%x%x%x%x%x%x%x%x", "") end
|
||||||
|
|
||||||
-- Limit number of section buffer positions used by a single dasm_put().
|
-- Limit number of section buffer positions used by a single dasm_put().
|
||||||
-- A single opcode needs a maximum of 3 positions.
|
-- A single opcode needs a maximum of 4 positions.
|
||||||
if secpos+3 > maxsecpos then wflush() end
|
if secpos+4 > maxsecpos then wflush() end
|
||||||
local pos = wpos()
|
local pos = wpos()
|
||||||
local lpos, apos, spos = #actlist, #actargs, secpos
|
local lpos, apos, spos = #actlist, #actargs, secpos
|
||||||
|
|
||||||
@@ -990,9 +1014,11 @@ function op_template(params, template, nparams)
|
|||||||
actlist[lpos+1] = nil
|
actlist[lpos+1] = nil
|
||||||
actlist[lpos+2] = nil
|
actlist[lpos+2] = nil
|
||||||
actlist[lpos+3] = nil
|
actlist[lpos+3] = nil
|
||||||
|
actlist[lpos+4] = nil
|
||||||
actargs[apos+1] = nil
|
actargs[apos+1] = nil
|
||||||
actargs[apos+2] = nil
|
actargs[apos+2] = nil
|
||||||
actargs[apos+3] = nil
|
actargs[apos+3] = nil
|
||||||
|
actargs[apos+4] = nil
|
||||||
end
|
end
|
||||||
error(err, 0)
|
error(err, 0)
|
||||||
end
|
end
|
||||||
@@ -1036,23 +1062,50 @@ map_op[".label_1"] = function(params)
|
|||||||
if not params then return "[1-9] | ->global | =>pcexpr" end
|
if not params then return "[1-9] | ->global | =>pcexpr" end
|
||||||
if secpos+1 > maxsecpos then wflush() end
|
if secpos+1 > maxsecpos then wflush() end
|
||||||
local mode, n, s = parse_label(params[1], true)
|
local mode, n, s = parse_label(params[1], true)
|
||||||
if mode == "EXT" then werror("bad label definition") end
|
if not mode or mode == "EXT" then werror("bad label definition") end
|
||||||
waction("LABEL_"..mode, n, s, 1)
|
waction("LABEL_"..mode, n, s, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- Pseudo-opcodes for data storage.
|
-- Pseudo-opcodes for data storage.
|
||||||
map_op[".long_*"] = function(params)
|
local function op_data(params)
|
||||||
if not params then return "imm..." end
|
if not params then return "imm..." end
|
||||||
|
local sz = params.op == ".long" and 4 or 8
|
||||||
for _,p in ipairs(params) do
|
for _,p in ipairs(params) do
|
||||||
local n = tonumber(p)
|
local imm = parse_number(p)
|
||||||
if not n then werror("bad immediate `"..p.."'") end
|
if imm then
|
||||||
if n < 0 then n = n + 2^32 end
|
local n = tobit(imm)
|
||||||
wputw(n)
|
if n == imm or (n < 0 and n + 2^32 == imm) then
|
||||||
|
wputw(n < 0 and n + 2^32 or n)
|
||||||
|
if sz == 8 then
|
||||||
|
wputw(imm < 0 and 0xffffffff or 0)
|
||||||
|
end
|
||||||
|
elseif sz == 4 then
|
||||||
|
werror("bad immediate `"..p.."'")
|
||||||
|
else
|
||||||
|
imm = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not imm then
|
||||||
|
local mode, v, s = parse_label(p, false)
|
||||||
|
if sz == 4 then
|
||||||
|
if mode then werror("label does not fit into .long") end
|
||||||
|
waction("IMMV", 0, p)
|
||||||
|
elseif mode and mode ~= "A" then
|
||||||
|
waction("REL_"..mode, v+0x8000, s, 1)
|
||||||
|
else
|
||||||
|
if mode == "A" then p = s end
|
||||||
|
waction("IMMV", 0, format("(unsigned int)(%s)", p))
|
||||||
|
waction("IMMV", 0, format("(unsigned int)((unsigned long long)(%s)>>32)", p))
|
||||||
|
end
|
||||||
|
end
|
||||||
if secpos+2 > maxsecpos then wflush() end
|
if secpos+2 > maxsecpos then wflush() end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
map_op[".long_*"] = op_data
|
||||||
|
map_op[".quad_*"] = op_data
|
||||||
|
map_op[".addr_*"] = op_data
|
||||||
|
|
||||||
-- Alignment pseudo-opcode.
|
-- Alignment pseudo-opcode.
|
||||||
map_op[".align_1"] = function(params)
|
map_op[".align_1"] = function(params)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM MIPS encoding engine.
|
** DynASM MIPS encoding engine.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -273,7 +273,7 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||||||
|
|
||||||
{ /* Handle globals not defined in this translation unit. */
|
{ /* Handle globals not defined in this translation unit. */
|
||||||
int idx;
|
int idx;
|
||||||
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
|
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
|
||||||
int n = D->lglabels[idx];
|
int n = D->lglabels[idx];
|
||||||
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
||||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
||||||
@@ -349,7 +349,10 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||||||
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
|
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
|
||||||
break;
|
break;
|
||||||
case DASM_REL_LG:
|
case DASM_REL_LG:
|
||||||
CK(n >= 0, UNDEF_LG);
|
if (n < 0) {
|
||||||
|
n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp);
|
||||||
|
goto patchrel;
|
||||||
|
}
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case DASM_REL_PC:
|
case DASM_REL_PC:
|
||||||
CK(n >= 0, UNDEF_PC);
|
CK(n >= 0, UNDEF_PC);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM MIPS32/MIPS64 module.
|
-- DynASM MIPS32/MIPS64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -12,9 +12,9 @@ local mipsr6 = _map_def.MIPSR6
|
|||||||
local _info = {
|
local _info = {
|
||||||
arch = mips64 and "mips64" or "mips",
|
arch = mips64 and "mips64" or "mips",
|
||||||
description = "DynASM MIPS32/MIPS64 module",
|
description = "DynASM MIPS32/MIPS64 module",
|
||||||
version = "1.4.0",
|
version = "1.5.0",
|
||||||
vernum = 10400,
|
vernum = 10500,
|
||||||
release = "2020-01-20",
|
release = "2021-05-02",
|
||||||
author = "Mike Pall",
|
author = "Mike Pall",
|
||||||
license = "MIT",
|
license = "MIT",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM MIPS64 module.
|
-- DynASM MIPS64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
|
-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM PPC/PPC64 encoding engine.
|
** DynASM PPC/PPC64 encoding engine.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||||||
|
|
||||||
{ /* Handle globals not defined in this translation unit. */
|
{ /* Handle globals not defined in this translation unit. */
|
||||||
int idx;
|
int idx;
|
||||||
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
|
for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
|
||||||
int n = D->lglabels[idx];
|
int n = D->lglabels[idx];
|
||||||
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
||||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
||||||
@@ -353,7 +353,10 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||||||
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
|
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
|
||||||
break;
|
break;
|
||||||
case DASM_REL_LG:
|
case DASM_REL_LG:
|
||||||
CK(n >= 0, UNDEF_LG);
|
if (n < 0) {
|
||||||
|
n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp);
|
||||||
|
goto patchrel;
|
||||||
|
}
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case DASM_REL_PC:
|
case DASM_REL_PC:
|
||||||
CK(n >= 0, UNDEF_PC);
|
CK(n >= 0, UNDEF_PC);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM PPC/PPC64 module.
|
-- DynASM PPC/PPC64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
--
|
--
|
||||||
-- Support for various extensions contributed by Caio Souza Oliveira.
|
-- Support for various extensions contributed by Caio Souza Oliveira.
|
||||||
@@ -11,9 +11,9 @@
|
|||||||
local _info = {
|
local _info = {
|
||||||
arch = "ppc",
|
arch = "ppc",
|
||||||
description = "DynASM PPC module",
|
description = "DynASM PPC module",
|
||||||
version = "1.4.0",
|
version = "1.5.0",
|
||||||
vernum = 10400,
|
vernum = 10500,
|
||||||
release = "2015-10-18",
|
release = "2021-05-02",
|
||||||
author = "Mike Pall",
|
author = "Mike Pall",
|
||||||
license = "MIT",
|
license = "MIT",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM encoding engine prototypes.
|
** DynASM encoding engine prototypes.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#define DASM_IDENT "DynASM 1.4.0"
|
#define DASM_IDENT "DynASM 1.5.0"
|
||||||
#define DASM_VERSION 10400 /* 1.4.0 */
|
#define DASM_VERSION 10500 /* 1.5.0 */
|
||||||
|
|
||||||
#ifndef Dst_DECL
|
#ifndef Dst_DECL
|
||||||
#define Dst_DECL dasm_State **Dst
|
#define Dst_DECL dasm_State **Dst
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM x64 module.
|
-- DynASM x64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- This module just sets 64 bit mode for the combined x86/x64 module.
|
-- This module just sets 64 bit mode for the combined x86/x64 module.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** DynASM x86 encoding engine.
|
** DynASM x86 encoding engine.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -239,8 +239,11 @@ void dasm_put(Dst_DECL, int start, ...)
|
|||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
ofs += 4; /* Maximum offset needed. */
|
ofs += 4; /* Maximum offset needed. */
|
||||||
if (action == DASM_REL_LG || action == DASM_REL_PC)
|
if (action == DASM_REL_LG || action == DASM_REL_PC) {
|
||||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||||
|
} else if (sizeof(ptrdiff_t) == 8) {
|
||||||
|
ofs += 4;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel;
|
case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel;
|
||||||
case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
|
case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
|
||||||
@@ -365,10 +368,22 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||||||
do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0)
|
do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0)
|
||||||
#define dasmd(x) \
|
#define dasmd(x) \
|
||||||
do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0)
|
do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0)
|
||||||
|
#define dasmq(x) \
|
||||||
|
do { *((unsigned long long *)cp) = (unsigned long long)(x); cp+=8; } while (0)
|
||||||
#else
|
#else
|
||||||
#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0)
|
#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0)
|
||||||
#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0)
|
#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0)
|
||||||
|
#define dasmq(x) do { dasmd(x); dasmd((x)>>32); } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
static unsigned char *dasma_(unsigned char *cp, ptrdiff_t x)
|
||||||
|
{
|
||||||
|
if (sizeof(ptrdiff_t) == 8)
|
||||||
|
dasmq((unsigned long long)x);
|
||||||
|
else
|
||||||
|
dasmd((unsigned int)x);
|
||||||
|
return cp;
|
||||||
|
}
|
||||||
|
#define dasma(x) (cp = dasma_(cp, (x)))
|
||||||
|
|
||||||
/* Pass 3: Encode sections. */
|
/* Pass 3: Encode sections. */
|
||||||
int dasm_encode(Dst_DECL, void *buffer)
|
int dasm_encode(Dst_DECL, void *buffer)
|
||||||
@@ -443,12 +458,13 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||||||
goto wb;
|
goto wb;
|
||||||
}
|
}
|
||||||
case DASM_IMM_LG:
|
case DASM_IMM_LG:
|
||||||
p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; }
|
p++;
|
||||||
|
if (n < 0) { dasma((ptrdiff_t)D->globals[-n]); break; }
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case DASM_IMM_PC: {
|
case DASM_IMM_PC: {
|
||||||
int *pb = DASM_POS2PTR(D, n);
|
int *pb = DASM_POS2PTR(D, n);
|
||||||
n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base);
|
dasma(*pb < 0 ? (ptrdiff_t)pb[1] : (*pb + (ptrdiff_t)base));
|
||||||
goto wd;
|
break;
|
||||||
}
|
}
|
||||||
case DASM_LABEL_LG: {
|
case DASM_LABEL_LG: {
|
||||||
int idx = *p++;
|
int idx = *p++;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
-- DynASM x86/x64 module.
|
-- DynASM x86/x64 module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- See dynasm.lua for full copyright notice.
|
-- See dynasm.lua for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -11,9 +11,9 @@ local x64 = x64
|
|||||||
local _info = {
|
local _info = {
|
||||||
arch = x64 and "x64" or "x86",
|
arch = x64 and "x64" or "x86",
|
||||||
description = "DynASM x86/x64 module",
|
description = "DynASM x86/x64 module",
|
||||||
version = "1.4.0",
|
version = "1.5.0",
|
||||||
vernum = 10400,
|
vernum = 10500,
|
||||||
release = "2015-10-18",
|
release = "2021-05-02",
|
||||||
author = "Mike Pall",
|
author = "Mike Pall",
|
||||||
license = "MIT",
|
license = "MIT",
|
||||||
}
|
}
|
||||||
@@ -484,6 +484,22 @@ local function wputdarg(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Put signed or unsigned qword or arg.
|
||||||
|
local function wputqarg(n)
|
||||||
|
local tn = type(n)
|
||||||
|
if tn == "number" then -- This is only used for numbers from -2^31..2^32-1.
|
||||||
|
wputb(band(n, 255))
|
||||||
|
wputb(band(shr(n, 8), 255))
|
||||||
|
wputb(band(shr(n, 16), 255))
|
||||||
|
wputb(shr(n, 24))
|
||||||
|
local sign = n < 0 and 255 or 0
|
||||||
|
wputb(sign); wputb(sign); wputb(sign); wputb(sign)
|
||||||
|
else
|
||||||
|
waction("IMM_D", format("(unsigned int)(%s)", n))
|
||||||
|
waction("IMM_D", format("(unsigned int)((unsigned long long)(%s)>>32)", n))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Put operand-size dependent number or arg (defaults to dword).
|
-- Put operand-size dependent number or arg (defaults to dword).
|
||||||
local function wputszarg(sz, n)
|
local function wputszarg(sz, n)
|
||||||
if not sz or sz == "d" or sz == "q" then wputdarg(n)
|
if not sz or sz == "d" or sz == "q" then wputdarg(n)
|
||||||
@@ -663,10 +679,16 @@ local function opmodestr(op, args)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Convert number to valid integer or nil.
|
-- Convert number to valid integer or nil.
|
||||||
local function toint(expr)
|
local function toint(expr, isqword)
|
||||||
local n = tonumber(expr)
|
local n = tonumber(expr)
|
||||||
if n then
|
if n then
|
||||||
if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then
|
if n % 1 ~= 0 then
|
||||||
|
werror("not an integer number `"..expr.."'")
|
||||||
|
elseif isqword then
|
||||||
|
if n < -2147483648 or n > 2147483647 then
|
||||||
|
n = nil -- Handle it as an expression to avoid precision loss.
|
||||||
|
end
|
||||||
|
elseif n < -2147483648 or n > 4294967295 then
|
||||||
werror("bad integer number `"..expr.."'")
|
werror("bad integer number `"..expr.."'")
|
||||||
end
|
end
|
||||||
return n
|
return n
|
||||||
@@ -749,7 +771,7 @@ local function rtexpr(expr)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }.
|
-- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }.
|
||||||
local function parseoperand(param)
|
local function parseoperand(param, isqword)
|
||||||
local t = {}
|
local t = {}
|
||||||
|
|
||||||
local expr = param
|
local expr = param
|
||||||
@@ -810,7 +832,7 @@ local function parseoperand(param)
|
|||||||
if t.disp then break end
|
if t.disp then break end
|
||||||
|
|
||||||
-- [reg+xreg...]
|
-- [reg+xreg...]
|
||||||
local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$")
|
local xreg, tailx = match(tailr, "^%+%s*([@%w_:]+)%s*(.*)$")
|
||||||
xreg, t.xreg, tp = rtexpr(xreg)
|
xreg, t.xreg, tp = rtexpr(xreg)
|
||||||
if not t.xreg then
|
if not t.xreg then
|
||||||
-- [reg+-expr]
|
-- [reg+-expr]
|
||||||
@@ -837,7 +859,7 @@ local function parseoperand(param)
|
|||||||
t.disp = dispexpr(tailx)
|
t.disp = dispexpr(tailx)
|
||||||
else
|
else
|
||||||
-- imm or opsize*imm
|
-- imm or opsize*imm
|
||||||
local imm = toint(expr)
|
local imm = toint(expr, isqword)
|
||||||
if not imm and sub(expr, 1, 1) == "*" and t.opsize then
|
if not imm and sub(expr, 1, 1) == "*" and t.opsize then
|
||||||
imm = toint(sub(expr, 2))
|
imm = toint(sub(expr, 2))
|
||||||
if imm then
|
if imm then
|
||||||
@@ -1952,7 +1974,7 @@ local function dopattern(pat, args, sz, op, needrex)
|
|||||||
local a = args[narg]
|
local a = args[narg]
|
||||||
narg = narg + 1
|
narg = narg + 1
|
||||||
local mode, imm = a.mode, a.imm
|
local mode, imm = a.mode, a.imm
|
||||||
if mode == "iJ" and not match("iIJ", c) then
|
if mode == "iJ" and not match(x64 and "J" or "iIJ", c) then
|
||||||
werror("bad operand size for label")
|
werror("bad operand size for label")
|
||||||
end
|
end
|
||||||
if c == "S" then
|
if c == "S" then
|
||||||
@@ -2144,14 +2166,16 @@ end
|
|||||||
local function op_data(params)
|
local function op_data(params)
|
||||||
if not params then return "imm..." end
|
if not params then return "imm..." end
|
||||||
local sz = sub(params.op, 2, 2)
|
local sz = sub(params.op, 2, 2)
|
||||||
if sz == "a" then sz = addrsize end
|
if sz == "l" then sz = "d" elseif sz == "a" then sz = addrsize end
|
||||||
for _,p in ipairs(params) do
|
for _,p in ipairs(params) do
|
||||||
local a = parseoperand(p)
|
local a = parseoperand(p, sz == "q")
|
||||||
if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then
|
if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then
|
||||||
werror("bad mode or size in `"..p.."'")
|
werror("bad mode or size in `"..p.."'")
|
||||||
end
|
end
|
||||||
if a.mode == "iJ" then
|
if a.mode == "iJ" then
|
||||||
wputlabel("IMM_", a.imm, 1)
|
wputlabel("IMM_", a.imm, 1)
|
||||||
|
elseif sz == "q" then
|
||||||
|
wputqarg(a.imm)
|
||||||
else
|
else
|
||||||
wputszarg(sz, a.imm)
|
wputszarg(sz, a.imm)
|
||||||
end
|
end
|
||||||
@@ -2163,7 +2187,11 @@ map_op[".byte_*"] = op_data
|
|||||||
map_op[".sbyte_*"] = op_data
|
map_op[".sbyte_*"] = op_data
|
||||||
map_op[".word_*"] = op_data
|
map_op[".word_*"] = op_data
|
||||||
map_op[".dword_*"] = op_data
|
map_op[".dword_*"] = op_data
|
||||||
|
map_op[".qword_*"] = op_data
|
||||||
map_op[".aword_*"] = op_data
|
map_op[".aword_*"] = op_data
|
||||||
|
map_op[".long_*"] = op_data
|
||||||
|
map_op[".quad_*"] = op_data
|
||||||
|
map_op[".addr_*"] = op_data
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
-- DynASM. A dynamic assembler for code generation engines.
|
-- DynASM. A dynamic assembler for code generation engines.
|
||||||
-- Originally designed and implemented for LuaJIT.
|
-- Originally designed and implemented for LuaJIT.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- See below for full copyright notice.
|
-- See below for full copyright notice.
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -10,14 +10,14 @@
|
|||||||
local _info = {
|
local _info = {
|
||||||
name = "DynASM",
|
name = "DynASM",
|
||||||
description = "A dynamic assembler for code generation engines",
|
description = "A dynamic assembler for code generation engines",
|
||||||
version = "1.4.0",
|
version = "1.5.0",
|
||||||
vernum = 10400,
|
vernum = 10500,
|
||||||
release = "2015-10-18",
|
release = "2021-05-02",
|
||||||
author = "Mike Pall",
|
author = "Mike Pall",
|
||||||
url = "https://luajit.org/dynasm.html",
|
url = "https://luajit.org/dynasm.html",
|
||||||
license = "MIT",
|
license = "MIT",
|
||||||
copyright = [[
|
copyright = [[
|
||||||
Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ luajit \-jv \-e "for i=1,10 do for j=1,10 do for k=1,100 do end end end"
|
|||||||
Runs some nested loops and shows the resulting traces.
|
Runs some nested loops and shows the resulting traces.
|
||||||
.SH COPYRIGHT
|
.SH COPYRIGHT
|
||||||
.PP
|
.PP
|
||||||
\fBLuaJIT\fR is Copyright \(co 2005-2020 Mike Pall.
|
\fBLuaJIT\fR is Copyright \(co 2005-2021 Mike Pall.
|
||||||
.br
|
.br
|
||||||
\fBLuaJIT\fR is open source software, released under the MIT license.
|
\fBLuaJIT\fR is open source software, released under the MIT license.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
# Also works with MinGW and Cygwin on Windows.
|
# Also works with MinGW and Cygwin on Windows.
|
||||||
# Please check msvcbuild.bat for building with MSVC on Windows.
|
# Please check msvcbuild.bat for building with MSVC on Windows.
|
||||||
#
|
#
|
||||||
# Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
# Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
MAJVER= 2
|
MAJVER= 2
|
||||||
@@ -211,7 +211,7 @@ TARGET_CC= $(STATIC_CC)
|
|||||||
TARGET_STCC= $(STATIC_CC)
|
TARGET_STCC= $(STATIC_CC)
|
||||||
TARGET_DYNCC= $(DYNAMIC_CC)
|
TARGET_DYNCC= $(DYNAMIC_CC)
|
||||||
TARGET_LD= $(CROSS)$(CC)
|
TARGET_LD= $(CROSS)$(CC)
|
||||||
TARGET_AR= $(CROSS)ar rcus 2>/dev/null
|
TARGET_AR= $(CROSS)ar rcus
|
||||||
TARGET_STRIP= $(CROSS)strip
|
TARGET_STRIP= $(CROSS)strip
|
||||||
|
|
||||||
TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib)
|
TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib)
|
||||||
@@ -311,6 +311,7 @@ ifeq (Windows,$(TARGET_SYS))
|
|||||||
TARGET_XSHLDFLAGS= -shared -Wl,--out-implib,$(TARGET_DLLDOTANAME)
|
TARGET_XSHLDFLAGS= -shared -Wl,--out-implib,$(TARGET_DLLDOTANAME)
|
||||||
TARGET_DYNXLDOPTS=
|
TARGET_DYNXLDOPTS=
|
||||||
else
|
else
|
||||||
|
TARGET_AR+= 2>/dev/null
|
||||||
ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1))
|
ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1))
|
||||||
TARGET_XCFLAGS+= -fno-stack-protector
|
TARGET_XCFLAGS+= -fno-stack-protector
|
||||||
endif
|
endif
|
||||||
@@ -319,13 +320,10 @@ ifeq (Darwin,$(TARGET_SYS))
|
|||||||
$(error missing: export MACOSX_DEPLOYMENT_TARGET=XX.YY)
|
$(error missing: export MACOSX_DEPLOYMENT_TARGET=XX.YY)
|
||||||
endif
|
endif
|
||||||
TARGET_STRIP+= -x
|
TARGET_STRIP+= -x
|
||||||
|
TARGET_XCFLAGS+= -DLUAJIT_UNWIND_EXTERNAL
|
||||||
TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC
|
TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC
|
||||||
TARGET_DYNXLDOPTS=
|
TARGET_DYNXLDOPTS=
|
||||||
TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER)
|
TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER)
|
||||||
ifeq (x64,$(TARGET_LJARCH))
|
|
||||||
TARGET_XLDFLAGS+= -pagezero_size 10000 -image_base 100000000
|
|
||||||
TARGET_XSHLDFLAGS+= -image_base 7fff04c4a000
|
|
||||||
endif
|
|
||||||
else
|
else
|
||||||
ifeq (iOS,$(TARGET_SYS))
|
ifeq (iOS,$(TARGET_SYS))
|
||||||
TARGET_STRIP+= -x
|
TARGET_STRIP+= -x
|
||||||
@@ -336,6 +334,13 @@ ifeq (iOS,$(TARGET_SYS))
|
|||||||
TARGET_XCFLAGS+= -fno-omit-frame-pointer
|
TARGET_XCFLAGS+= -fno-omit-frame-pointer
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
|
ifeq (,$(findstring LJ_NO_UNWIND 1,$(TARGET_TESTARCH)))
|
||||||
|
# Find out whether the target toolchain always generates unwind tables.
|
||||||
|
TARGET_TESTUNWIND=$(shell exec 2>/dev/null; echo 'extern void b(void);int a(void){b();return 0;}' | $(TARGET_CC) -c -x c - -o tmpunwind.o && { grep -qa -e eh_frame -e __unwind_info tmpunwind.o || grep -qU -e eh_frame -e __unwind_info tmpunwind.o; } && echo E; rm -f tmpunwind.o)
|
||||||
|
ifneq (,$(findstring E,$(TARGET_TESTUNWIND)))
|
||||||
|
TARGET_XCFLAGS+= -DLUAJIT_UNWIND_EXTERNAL
|
||||||
|
endif
|
||||||
|
endif
|
||||||
ifneq (SunOS,$(TARGET_SYS))
|
ifneq (SunOS,$(TARGET_SYS))
|
||||||
ifneq (PS3,$(TARGET_SYS))
|
ifneq (PS3,$(TARGET_SYS))
|
||||||
TARGET_XLDFLAGS+= -Wl,-E
|
TARGET_XLDFLAGS+= -Wl,-E
|
||||||
@@ -479,13 +484,15 @@ LJVM_BOUT= $(LJVM_S)
|
|||||||
LJVM_MODE= elfasm
|
LJVM_MODE= elfasm
|
||||||
|
|
||||||
LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \
|
LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \
|
||||||
lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o
|
lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o \
|
||||||
|
lib_buffer.o
|
||||||
LJLIB_C= $(LJLIB_O:.o=.c)
|
LJLIB_C= $(LJLIB_O:.o=.c)
|
||||||
|
|
||||||
LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \
|
LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \
|
||||||
lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \
|
lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \
|
||||||
lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \
|
lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \
|
||||||
lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \
|
lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_serialize.o \
|
||||||
|
lj_api.o lj_profile.o \
|
||||||
lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \
|
lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \
|
||||||
lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \
|
lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \
|
||||||
lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
|
lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
|
||||||
|
|||||||
@@ -2,14 +2,18 @@ lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
|
|||||||
lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \
|
lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \
|
||||||
lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h
|
lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h
|
||||||
lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
|
lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
|
||||||
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \
|
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h \
|
||||||
lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \
|
lj_str.h lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h \
|
||||||
lj_ff.h lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \
|
lj_cconv.h lj_ff.h lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h \
|
||||||
lj_strfmt.h lj_lib.h lj_libdef.h
|
lj_strscan.h lj_strfmt.h lj_lib.h lj_libdef.h
|
||||||
lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
|
lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
|
||||||
lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_strscan.h \
|
lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_strscan.h \
|
||||||
lj_strfmt.h lj_ctype.h lj_cdata.h lj_cconv.h lj_carith.h lj_ff.h \
|
lj_strfmt.h lj_ctype.h lj_cdata.h lj_cconv.h lj_carith.h lj_ff.h \
|
||||||
lj_ffdef.h lj_lib.h lj_libdef.h
|
lj_ffdef.h lj_lib.h lj_libdef.h
|
||||||
|
lib_buffer.o: lib_buffer.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
|
||||||
|
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \
|
||||||
|
lj_tab.h lj_udata.h lj_meta.h lj_ctype.h lj_cdata.h lj_cconv.h \
|
||||||
|
lj_strfmt.h lj_serialize.h lj_lib.h lj_libdef.h
|
||||||
lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
|
lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
|
||||||
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \
|
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \
|
||||||
lj_libdef.h
|
lj_libdef.h
|
||||||
@@ -48,10 +52,10 @@ lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
|||||||
lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \
|
lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \
|
||||||
lj_dispatch.h lj_traceerr.h lj_vm.h lj_strscan.h lj_strfmt.h
|
lj_dispatch.h lj_traceerr.h lj_vm.h lj_strscan.h lj_strfmt.h
|
||||||
lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||||
lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h \
|
lj_buf.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h \
|
||||||
lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h lj_traceerr.h \
|
lj_jit.h lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h \
|
||||||
lj_snap.h lj_asm.h lj_vm.h lj_target.h lj_target_*.h lj_emit_*.h \
|
lj_traceerr.h lj_snap.h lj_asm.h lj_vm.h lj_target.h lj_target_*.h \
|
||||||
lj_asm_*.h
|
lj_emit_*.h lj_asm_*.h
|
||||||
lj_assert.o: lj_assert.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h
|
lj_assert.o: lj_assert.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h
|
||||||
lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \
|
lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \
|
||||||
lj_bcdef.h
|
lj_bcdef.h
|
||||||
@@ -77,8 +81,8 @@ lj_ccallback.o: lj_ccallback.c lj_obj.h lua.h luaconf.h lj_def.h \
|
|||||||
lj_target_*.h lj_mcode.h lj_jit.h lj_ir.h lj_trace.h lj_dispatch.h \
|
lj_target_*.h lj_mcode.h lj_jit.h lj_ir.h lj_trace.h lj_dispatch.h \
|
||||||
lj_traceerr.h lj_vm.h
|
lj_traceerr.h lj_vm.h
|
||||||
lj_cconv.o: lj_cconv.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_cconv.o: lj_cconv.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_gc.h lj_cdata.h lj_cconv.h \
|
lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h lj_ctype.h \
|
||||||
lj_ccallback.h
|
lj_cdata.h lj_cconv.h lj_ccallback.h
|
||||||
lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_cconv.h lj_cdata.h
|
lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_cconv.h lj_cdata.h
|
||||||
lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h
|
lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h
|
||||||
@@ -110,10 +114,10 @@ lj_err.o: lj_err.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_err.h \
|
|||||||
lj_ff.h lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
|
lj_ff.h lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
|
||||||
lj_traceerr.h lj_vm.h lj_strfmt.h
|
lj_traceerr.h lj_vm.h lj_strfmt.h
|
||||||
lj_ffrecord.o: lj_ffrecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_ffrecord.o: lj_ffrecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ff.h \
|
lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h lj_frame.h \
|
||||||
lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \
|
lj_bc.h lj_ff.h lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \
|
||||||
lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h lj_crecord.h \
|
lj_trace.h lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h \
|
||||||
lj_vm.h lj_strscan.h lj_strfmt.h lj_recdef.h
|
lj_crecord.h lj_vm.h lj_strscan.h lj_strfmt.h lj_serialize.h lj_recdef.h
|
||||||
lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||||
lj_func.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \
|
lj_func.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \
|
||||||
lj_traceerr.h lj_vm.h
|
lj_traceerr.h lj_vm.h
|
||||||
@@ -127,15 +131,15 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
|||||||
lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||||
lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \
|
lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \
|
||||||
lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \
|
lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \
|
||||||
lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_prng.h
|
lj_carith.h lj_vm.h lj_strscan.h lj_serialize.h lj_strfmt.h lj_prng.h
|
||||||
lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||||
lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \
|
lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \
|
||||||
lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \
|
lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \
|
||||||
lj_strfmt.h
|
lj_strfmt.h
|
||||||
lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \
|
lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \
|
||||||
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \
|
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \
|
||||||
lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lex.h \
|
lj_dispatch.h lj_jit.h lj_ir.h lj_ctype.h lj_vm.h lj_strscan.h \
|
||||||
lj_bcdump.h lj_lib.h
|
lj_strfmt.h lj_lex.h lj_bcdump.h lj_lib.h
|
||||||
lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
|
lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
|
||||||
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_func.h \
|
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_func.h \
|
||||||
lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h
|
lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h
|
||||||
@@ -170,15 +174,18 @@ lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
|||||||
lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_str.h lj_tab.h \
|
lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_str.h lj_tab.h \
|
||||||
lj_func.h lj_state.h lj_bc.h lj_ctype.h lj_strfmt.h lj_lex.h lj_parse.h \
|
lj_func.h lj_state.h lj_bc.h lj_ctype.h lj_strfmt.h lj_lex.h lj_parse.h \
|
||||||
lj_vm.h lj_vmevent.h
|
lj_vm.h lj_vmevent.h
|
||||||
|
lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h
|
||||||
lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \
|
lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \
|
||||||
lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h
|
lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h
|
||||||
lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h
|
|
||||||
lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \
|
lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \
|
||||||
lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \
|
lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \
|
||||||
lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \
|
lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \
|
||||||
lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h
|
lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h
|
||||||
|
lj_serialize.o: lj_serialize.c lj_obj.h lua.h luaconf.h lj_def.h \
|
||||||
|
lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \
|
||||||
|
lj_udata.h lj_ctype.h lj_cdata.h lj_ir.h lj_serialize.h
|
||||||
lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||||
lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \
|
lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \
|
||||||
lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \
|
lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \
|
||||||
@@ -189,9 +196,10 @@ lj_state.o: lj_state.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
|||||||
lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \
|
lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \
|
||||||
lj_alloc.h luajit.h
|
lj_alloc.h luajit.h
|
||||||
lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||||
lj_err.h lj_errmsg.h lj_str.h lj_char.h
|
lj_err.h lj_errmsg.h lj_str.h lj_char.h lj_prng.h
|
||||||
lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
lj_buf.h lj_gc.h lj_str.h lj_state.h lj_char.h lj_strfmt.h
|
lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_meta.h lj_state.h \
|
||||||
|
lj_char.h lj_strfmt.h lj_ctype.h lj_lib.h
|
||||||
lj_strfmt_num.o: lj_strfmt_num.c lj_obj.h lua.h luaconf.h lj_def.h \
|
lj_strfmt_num.o: lj_strfmt_num.c lj_obj.h lua.h luaconf.h lj_def.h \
|
||||||
lj_arch.h lj_buf.h lj_gc.h lj_str.h lj_strfmt.h
|
lj_arch.h lj_buf.h lj_gc.h lj_str.h lj_strfmt.h
|
||||||
lj_strscan.o: lj_strscan.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_strscan.o: lj_strscan.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
@@ -204,7 +212,7 @@ lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
|||||||
lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \
|
lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \
|
||||||
lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h
|
lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h
|
||||||
lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
lj_gc.h lj_udata.h
|
lj_gc.h lj_err.h lj_errmsg.h lj_udata.h
|
||||||
lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||||
lj_str.h lj_tab.h lj_state.h lj_dispatch.h lj_bc.h lj_jit.h lj_ir.h \
|
lj_str.h lj_tab.h lj_state.h lj_dispatch.h lj_bc.h lj_jit.h lj_ir.h \
|
||||||
lj_vm.h lj_vmevent.h
|
lj_vm.h lj_vmevent.h
|
||||||
@@ -216,23 +224,23 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_assert.c lj_obj.h \
|
|||||||
lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
|
lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
|
||||||
lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \
|
lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \
|
||||||
lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \
|
lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \
|
||||||
lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \
|
lj_prng.h lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h \
|
||||||
lj_prng.c lj_prng.h lj_state.c lj_lex.h lj_alloc.h luajit.h \
|
lj_debug.c lj_prng.c lj_state.c lj_lex.h lj_alloc.h luajit.h \
|
||||||
lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \
|
lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \
|
||||||
lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_api.c \
|
lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_serialize.c \
|
||||||
lj_profile.c lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c \
|
lj_serialize.h lj_api.c lj_profile.c lj_lex.c lualib.h lj_parse.h \
|
||||||
lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h \
|
lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c \
|
||||||
lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h \
|
lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c \
|
||||||
lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h \
|
lj_target.h lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c \
|
||||||
lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h lj_iropt.h \
|
lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h \
|
||||||
lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \
|
lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c \
|
||||||
lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \
|
lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c \
|
||||||
lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
|
lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
|
||||||
lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \
|
lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \
|
||||||
lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \
|
lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \
|
||||||
lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \
|
lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \
|
||||||
lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \
|
lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \
|
||||||
lib_init.c
|
lib_buffer.c lib_init.c
|
||||||
luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
|
luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
|
||||||
host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \
|
host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \
|
||||||
lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \
|
lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder.
|
** LuaJIT VM builder.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** This is a tool to build the hand-tuned assembler code required for
|
** This is a tool to build the hand-tuned assembler code required for
|
||||||
** LuaJIT's bytecode interpreter. It supports a variety of output formats
|
** LuaJIT's bytecode interpreter. It supports a variety of output formats
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder.
|
** LuaJIT VM builder.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _BUILDVM_H
|
#ifndef _BUILDVM_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder: Assembler source code emitter.
|
** LuaJIT VM builder: Assembler source code emitter.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "buildvm.h"
|
#include "buildvm.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder: IR folding hash table generator.
|
** LuaJIT VM builder: IR folding hash table generator.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "buildvm.h"
|
#include "buildvm.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder: library definition compiler.
|
** LuaJIT VM builder: library definition compiler.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "buildvm.h"
|
#include "buildvm.h"
|
||||||
@@ -385,6 +385,8 @@ void emit_lib(BuildCtx *ctx)
|
|||||||
ok = LJ_HASJIT;
|
ok = LJ_HASJIT;
|
||||||
else if (!strcmp(buf, "#if LJ_HASFFI\n"))
|
else if (!strcmp(buf, "#if LJ_HASFFI\n"))
|
||||||
ok = LJ_HASFFI;
|
ok = LJ_HASFFI;
|
||||||
|
else if (!strcmp(buf, "#if LJ_HASBUFFER\n"))
|
||||||
|
ok = LJ_HASBUFFER;
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
int lvl = 1;
|
int lvl = 1;
|
||||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** LuaJIT VM builder: PE object emitter.
|
** LuaJIT VM builder: PE object emitter.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Only used for building on Windows, since we cannot assume the presence
|
** Only used for building on Windows, since we cannot assume the presence
|
||||||
** of a suitable assembler. The host and target byte order must match.
|
** of a suitable assembler. The host and target byte order must match.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
-- Lua script to dump the bytecode of the library functions written in Lua.
|
-- Lua script to dump the bytecode of the library functions written in Lua.
|
||||||
-- The resulting 'buildvm_libbc.h' is used for the build process of LuaJIT.
|
-- The resulting 'buildvm_libbc.h' is used for the build process of LuaJIT.
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
-- Lua script to generate a customized, minified version of Lua.
|
-- Lua script to generate a customized, minified version of Lua.
|
||||||
-- The resulting 'minilua' is used for the build process of LuaJIT.
|
-- The resulting 'minilua' is used for the build process of LuaJIT.
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -1134,7 +1134,7 @@ if(!cl->isC){
|
|||||||
CallInfo*ci;
|
CallInfo*ci;
|
||||||
StkId st,base;
|
StkId st,base;
|
||||||
Proto*p=cl->p;
|
Proto*p=cl->p;
|
||||||
luaD_checkstack(L,p->maxstacksize);
|
luaD_checkstack(L,p->maxstacksize+p->numparams);
|
||||||
func=restorestack(L,funcr);
|
func=restorestack(L,funcr);
|
||||||
if(!p->is_vararg){
|
if(!p->is_vararg){
|
||||||
base=func+1;
|
base=func+1;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT bytecode listing module.
|
-- LuaJIT bytecode listing module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT module to save/list bytecode.
|
-- LuaJIT module to save/list bytecode.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT ARM disassembler module.
|
-- LuaJIT ARM disassembler module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT ARM64 disassembler module.
|
-- LuaJIT ARM64 disassembler module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
--
|
--
|
||||||
-- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
|
-- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
|
||||||
@@ -1089,7 +1089,7 @@ local function disass_ins(ctx)
|
|||||||
last = "#"..(sf+32 - immr)
|
last = "#"..(sf+32 - immr)
|
||||||
operands[#operands] = last
|
operands[#operands] = last
|
||||||
x = x + 1
|
x = x + 1
|
||||||
elseif x >= immr then
|
else
|
||||||
name = a2
|
name = a2
|
||||||
x = x - immr + 1
|
x = x - immr + 1
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT ARM64BE disassembler wrapper module.
|
-- LuaJIT ARM64BE disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- ARM64 instructions are always little-endian. So just forward to the
|
-- ARM64 instructions are always little-endian. So just forward to the
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT MIPS disassembler module.
|
-- LuaJIT MIPS disassembler module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT/X license. See Copyright Notice in luajit.h
|
-- Released under the MIT/X license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT MIPS64 disassembler wrapper module.
|
-- LuaJIT MIPS64 disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This module just exports the big-endian functions from the
|
-- This module just exports the big-endian functions from the
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT MIPS64EL disassembler wrapper module.
|
-- LuaJIT MIPS64EL disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This module just exports the little-endian functions from the
|
-- This module just exports the little-endian functions from the
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT MIPS64R6 disassembler wrapper module.
|
-- LuaJIT MIPS64R6 disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This module just exports the r6 big-endian functions from the
|
-- This module just exports the r6 big-endian functions from the
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT MIPS64R6EL disassembler wrapper module.
|
-- LuaJIT MIPS64R6EL disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This module just exports the r6 little-endian functions from the
|
-- This module just exports the r6 little-endian functions from the
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT MIPSEL disassembler wrapper module.
|
-- LuaJIT MIPSEL disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This module just exports the little-endian functions from the
|
-- This module just exports the little-endian functions from the
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT PPC disassembler module.
|
-- LuaJIT PPC disassembler module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT/X license. See Copyright Notice in luajit.h
|
-- Released under the MIT/X license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT x64 disassembler wrapper module.
|
-- LuaJIT x64 disassembler wrapper module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This module just exports the 64 bit functions from the combined
|
-- This module just exports the 64 bit functions from the combined
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT x86/x64 disassembler module.
|
-- LuaJIT x86/x64 disassembler module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT compiler dump module.
|
-- LuaJIT compiler dump module.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
@@ -102,10 +102,12 @@ end
|
|||||||
local function fillsymtab(tr, nexit)
|
local function fillsymtab(tr, nexit)
|
||||||
local t = symtab
|
local t = symtab
|
||||||
if nexitsym == 0 then
|
if nexitsym == 0 then
|
||||||
|
local maskaddr = jit.arch == "arm" and -2
|
||||||
local ircall = vmdef.ircall
|
local ircall = vmdef.ircall
|
||||||
for i=0,#ircall do
|
for i=0,#ircall do
|
||||||
local addr = ircalladdr(i)
|
local addr = ircalladdr(i)
|
||||||
if addr ~= 0 then
|
if addr ~= 0 then
|
||||||
|
if maskaddr then addr = band(addr, maskaddr) end
|
||||||
if addr < 0 then addr = addr + 2^32 end
|
if addr < 0 then addr = addr + 2^32 end
|
||||||
t[addr] = ircall[i]
|
t[addr] = ircall[i]
|
||||||
end
|
end
|
||||||
@@ -217,8 +219,10 @@ local function colorize_text(s)
|
|||||||
return s
|
return s
|
||||||
end
|
end
|
||||||
|
|
||||||
local function colorize_ansi(s, t)
|
local function colorize_ansi(s, t, extra)
|
||||||
return format(colortype_ansi[t], s)
|
local out = format(colortype_ansi[t], s)
|
||||||
|
if extra then out = "\027[3m"..out end
|
||||||
|
return out
|
||||||
end
|
end
|
||||||
|
|
||||||
local irtype_ansi = setmetatable({},
|
local irtype_ansi = setmetatable({},
|
||||||
@@ -227,9 +231,10 @@ local irtype_ansi = setmetatable({},
|
|||||||
|
|
||||||
local html_escape = { ["<"] = "<", [">"] = ">", ["&"] = "&", }
|
local html_escape = { ["<"] = "<", [">"] = ">", ["&"] = "&", }
|
||||||
|
|
||||||
local function colorize_html(s, t)
|
local function colorize_html(s, t, extra)
|
||||||
s = gsub(s, "[<>&]", html_escape)
|
s = gsub(s, "[<>&]", html_escape)
|
||||||
return format('<span class="irt_%s">%s</span>', irtype_text[t], s)
|
return format('<span class="irt_%s%s">%s</span>',
|
||||||
|
irtype_text[t], extra and " irt_extra" or "", s)
|
||||||
end
|
end
|
||||||
|
|
||||||
local irtype_html = setmetatable({},
|
local irtype_html = setmetatable({},
|
||||||
@@ -254,6 +259,7 @@ span.irt_tab { color: #c00000; }
|
|||||||
span.irt_udt, span.irt_lud { color: #00c0c0; }
|
span.irt_udt, span.irt_lud { color: #00c0c0; }
|
||||||
span.irt_num { color: #4040c0; }
|
span.irt_num { color: #4040c0; }
|
||||||
span.irt_int, span.irt_i8, span.irt_u8, span.irt_i16, span.irt_u16 { color: #b040b0; }
|
span.irt_int, span.irt_i8, span.irt_u8, span.irt_i16, span.irt_u16 { color: #b040b0; }
|
||||||
|
span.irt_extra { font-style: italic; }
|
||||||
</style>
|
</style>
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -269,6 +275,7 @@ local litname = {
|
|||||||
if band(mode, 8) ~= 0 then s = s.."C" end
|
if band(mode, 8) ~= 0 then s = s.."C" end
|
||||||
if band(mode, 16) ~= 0 then s = s.."R" end
|
if band(mode, 16) ~= 0 then s = s.."R" end
|
||||||
if band(mode, 32) ~= 0 then s = s.."I" end
|
if band(mode, 32) ~= 0 then s = s.."I" end
|
||||||
|
if band(mode, 64) ~= 0 then s = s.."K" end
|
||||||
t[mode] = s
|
t[mode] = s
|
||||||
return s
|
return s
|
||||||
end}),
|
end}),
|
||||||
@@ -277,15 +284,18 @@ local litname = {
|
|||||||
local s = irtype[band(mode, 31)]
|
local s = irtype[band(mode, 31)]
|
||||||
s = irtype[band(shr(mode, 5), 31)].."."..s
|
s = irtype[band(shr(mode, 5), 31)].."."..s
|
||||||
if band(mode, 0x800) ~= 0 then s = s.." sext" end
|
if band(mode, 0x800) ~= 0 then s = s.." sext" end
|
||||||
local c = shr(mode, 14)
|
local c = shr(mode, 12)
|
||||||
if c == 2 then s = s.." index" elseif c == 3 then s = s.." check" end
|
if c == 1 then s = s.." none"
|
||||||
|
elseif c == 2 then s = s.." index"
|
||||||
|
elseif c == 3 then s = s.." check" end
|
||||||
t[mode] = s
|
t[mode] = s
|
||||||
return s
|
return s
|
||||||
end}),
|
end}),
|
||||||
["FLOAD "] = vmdef.irfield,
|
["FLOAD "] = vmdef.irfield,
|
||||||
["FREF "] = vmdef.irfield,
|
["FREF "] = vmdef.irfield,
|
||||||
["FPMATH"] = vmdef.irfpm,
|
["FPMATH"] = vmdef.irfpm,
|
||||||
["BUFHDR"] = { [0] = "RESET", "APPEND" },
|
["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" },
|
||||||
|
["BUFHDR"] = { [0] = "RESET", "APPEND", "WRITE" },
|
||||||
["TOSTR "] = { [0] = "INT", "NUM", "CHAR" },
|
["TOSTR "] = { [0] = "INT", "NUM", "CHAR" },
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +355,7 @@ local function formatk(tr, idx, sn)
|
|||||||
else
|
else
|
||||||
s = tostring(k) -- For primitives.
|
s = tostring(k) -- For primitives.
|
||||||
end
|
end
|
||||||
s = colorize(format("%-4s", s), t)
|
s = colorize(format("%-4s", s), t, band(sn or 0, 0x100000) ~= 0)
|
||||||
if slot then
|
if slot then
|
||||||
s = format("%s @%d", s, slot)
|
s = format("%s @%d", s, slot)
|
||||||
end
|
end
|
||||||
@@ -365,7 +375,7 @@ local function printsnap(tr, snap)
|
|||||||
out:write(colorize(format("%04d/%04d", ref, ref+1), 14))
|
out:write(colorize(format("%04d/%04d", ref, ref+1), 14))
|
||||||
else
|
else
|
||||||
local m, ot, op1, op2 = traceir(tr, ref)
|
local m, ot, op1, op2 = traceir(tr, ref)
|
||||||
out:write(colorize(format("%04d", ref), band(ot, 31)))
|
out:write(colorize(format("%04d", ref), band(ot, 31), band(sn, 0x100000) ~= 0))
|
||||||
end
|
end
|
||||||
out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME
|
out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME
|
||||||
else
|
else
|
||||||
@@ -584,7 +594,7 @@ local function dump_trace(what, tr, func, pc, otr, oex)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Dump recorded bytecode.
|
-- Dump recorded bytecode.
|
||||||
local function dump_record(tr, func, pc, depth, callee)
|
local function dump_record(tr, func, pc, depth)
|
||||||
if depth ~= recdepth then
|
if depth ~= recdepth then
|
||||||
recdepth = depth
|
recdepth = depth
|
||||||
recprefix = rep(" .", depth)
|
recprefix = rep(" .", depth)
|
||||||
@@ -595,7 +605,6 @@ local function dump_record(tr, func, pc, depth, callee)
|
|||||||
if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end
|
if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end
|
||||||
else
|
else
|
||||||
line = "0000 "..recprefix.." FUNCC \n"
|
line = "0000 "..recprefix.." FUNCC \n"
|
||||||
callee = func
|
|
||||||
end
|
end
|
||||||
if pc <= 0 then
|
if pc <= 0 then
|
||||||
out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n")
|
out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n")
|
||||||
@@ -609,12 +618,15 @@ end
|
|||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local gpr64 = jit.arch:match("64")
|
||||||
|
local fprmips32 = jit.arch == "mips" or jit.arch == "mipsel"
|
||||||
|
|
||||||
-- Dump taken trace exits.
|
-- Dump taken trace exits.
|
||||||
local function dump_texit(tr, ex, ngpr, nfpr, ...)
|
local function dump_texit(tr, ex, ngpr, nfpr, ...)
|
||||||
out:write("---- TRACE ", tr, " exit ", ex, "\n")
|
out:write("---- TRACE ", tr, " exit ", ex, "\n")
|
||||||
if dumpmode.X then
|
if dumpmode.X then
|
||||||
local regs = {...}
|
local regs = {...}
|
||||||
if jit.arch:sub(-2) == "64" then
|
if gpr64 then
|
||||||
for i=1,ngpr do
|
for i=1,ngpr do
|
||||||
out:write(format(" %016x", regs[i]))
|
out:write(format(" %016x", regs[i]))
|
||||||
if i % 4 == 0 then out:write("\n") end
|
if i % 4 == 0 then out:write("\n") end
|
||||||
@@ -625,7 +637,7 @@ local function dump_texit(tr, ex, ngpr, nfpr, ...)
|
|||||||
if i % 8 == 0 then out:write("\n") end
|
if i % 8 == 0 then out:write("\n") end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if jit.arch == "mips" or jit.arch == "mipsel" then
|
if fprmips32 then
|
||||||
for i=1,nfpr,2 do
|
for i=1,nfpr,2 do
|
||||||
out:write(format(" %+17.14g", regs[ngpr+i]))
|
out:write(format(" %+17.14g", regs[ngpr+i]))
|
||||||
if i % 8 == 7 then out:write("\n") end
|
if i % 8 == 7 then out:write("\n") end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT profiler.
|
-- LuaJIT profiler.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
@@ -238,6 +238,7 @@ local function prof_finish()
|
|||||||
prof_count1 = nil
|
prof_count1 = nil
|
||||||
prof_count2 = nil
|
prof_count2 = nil
|
||||||
prof_ud = nil
|
prof_ud = nil
|
||||||
|
if out ~= stdout then out:close() end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- Verbose mode of the LuaJIT compiler.
|
-- Verbose mode of the LuaJIT compiler.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
-- LuaJIT profiler zones.
|
-- LuaJIT profiler zones.
|
||||||
--
|
--
|
||||||
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved.
|
-- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
|
||||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Auxiliary library for the Lua/C API.
|
** Auxiliary library for the Lua/C API.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major parts taken verbatim or adapted from the Lua interpreter.
|
** Major parts taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Base and coroutine library.
|
** Base and coroutine library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "lj_gc.h"
|
#include "lj_gc.h"
|
||||||
#include "lj_err.h"
|
#include "lj_err.h"
|
||||||
#include "lj_debug.h"
|
#include "lj_debug.h"
|
||||||
|
#include "lj_buf.h"
|
||||||
#include "lj_str.h"
|
#include "lj_str.h"
|
||||||
#include "lj_tab.h"
|
#include "lj_tab.h"
|
||||||
#include "lj_meta.h"
|
#include "lj_meta.h"
|
||||||
@@ -75,9 +76,10 @@ LJLIB_ASM_(type) LJLIB_REC(.)
|
|||||||
/* This solves a circular dependency problem -- change FF_next_N as needed. */
|
/* This solves a circular dependency problem -- change FF_next_N as needed. */
|
||||||
LJ_STATIC_ASSERT((int)FF_next == FF_next_N);
|
LJ_STATIC_ASSERT((int)FF_next == FF_next_N);
|
||||||
|
|
||||||
LJLIB_ASM(next)
|
LJLIB_ASM(next) LJLIB_REC(.)
|
||||||
{
|
{
|
||||||
lj_lib_checktab(L, 1);
|
lj_lib_checktab(L, 1);
|
||||||
|
lj_err_msg(L, LJ_ERR_NEXTIDX);
|
||||||
return FFH_UNREACHABLE;
|
return FFH_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,10 +408,22 @@ LJLIB_CF(load)
|
|||||||
GCstr *name = lj_lib_optstr(L, 2);
|
GCstr *name = lj_lib_optstr(L, 2);
|
||||||
GCstr *mode = lj_lib_optstr(L, 3);
|
GCstr *mode = lj_lib_optstr(L, 3);
|
||||||
int status;
|
int status;
|
||||||
if (L->base < L->top && (tvisstr(L->base) || tvisnumber(L->base))) {
|
if (L->base < L->top &&
|
||||||
GCstr *s = lj_lib_checkstr(L, 1);
|
(tvisstr(L->base) || tvisnumber(L->base) || tvisbuf(L->base))) {
|
||||||
|
const char *s;
|
||||||
|
MSize len;
|
||||||
|
if (tvisbuf(L->base)) {
|
||||||
|
SBufExt *sbx = bufV(L->base);
|
||||||
|
s = sbx->r;
|
||||||
|
len = sbufxlen(sbx);
|
||||||
|
if (!name) name = &G(L)->strempty; /* Buffers are not NUL-terminated. */
|
||||||
|
} else {
|
||||||
|
GCstr *str = lj_lib_checkstr(L, 1);
|
||||||
|
s = strdata(str);
|
||||||
|
len = str->len;
|
||||||
|
}
|
||||||
lua_settop(L, 4); /* Ensure env arg exists. */
|
lua_settop(L, 4); /* Ensure env arg exists. */
|
||||||
status = luaL_loadbufferx(L, strdata(s), s->len, strdata(name ? name : s),
|
status = luaL_loadbufferx(L, s, len, name ? strdata(name) : s,
|
||||||
mode ? strdata(mode) : NULL);
|
mode ? strdata(mode) : NULL);
|
||||||
} else {
|
} else {
|
||||||
lj_lib_checkfunc(L, 1);
|
lj_lib_checkfunc(L, 1);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bit manipulation library.
|
** Bit manipulation library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lib_bit_c
|
#define lib_bit_c
|
||||||
|
|||||||
@@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
** Buffer library.
|
||||||
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define lib_buffer_c
|
||||||
|
#define LUA_LIB
|
||||||
|
|
||||||
|
#include "lua.h"
|
||||||
|
#include "lauxlib.h"
|
||||||
|
#include "lualib.h"
|
||||||
|
|
||||||
|
#include "lj_obj.h"
|
||||||
|
|
||||||
|
#if LJ_HASBUFFER
|
||||||
|
#include "lj_gc.h"
|
||||||
|
#include "lj_err.h"
|
||||||
|
#include "lj_buf.h"
|
||||||
|
#include "lj_str.h"
|
||||||
|
#include "lj_tab.h"
|
||||||
|
#include "lj_udata.h"
|
||||||
|
#include "lj_meta.h"
|
||||||
|
#if LJ_HASFFI
|
||||||
|
#include "lj_ctype.h"
|
||||||
|
#include "lj_cdata.h"
|
||||||
|
#include "lj_cconv.h"
|
||||||
|
#endif
|
||||||
|
#include "lj_strfmt.h"
|
||||||
|
#include "lj_serialize.h"
|
||||||
|
#include "lj_lib.h"
|
||||||
|
|
||||||
|
/* -- Helper functions ---------------------------------------------------- */
|
||||||
|
|
||||||
|
/* Check that the first argument is a string buffer. */
|
||||||
|
static SBufExt *buffer_tobuf(lua_State *L)
|
||||||
|
{
|
||||||
|
if (!(L->base < L->top && tvisbuf(L->base)))
|
||||||
|
lj_err_argtype(L, 1, "buffer");
|
||||||
|
return bufV(L->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ditto, but for writers. */
|
||||||
|
static LJ_AINLINE SBufExt *buffer_tobufw(lua_State *L)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
setsbufXL_(sbx, L);
|
||||||
|
return sbx;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define buffer_toudata(sbx) ((GCudata *)(sbx)-1)
|
||||||
|
|
||||||
|
/* -- Buffer methods ------------------------------------------------------ */
|
||||||
|
|
||||||
|
#define LJLIB_MODULE_buffer_method
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_free)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
lj_bufx_free(L, sbx);
|
||||||
|
L->top = L->base+1; /* Chain buffer object. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_reset) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
lj_bufx_reset(sbx);
|
||||||
|
L->top = L->base+1; /* Chain buffer object. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_skip) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
MSize n = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF);
|
||||||
|
MSize len = sbufxlen(sbx);
|
||||||
|
if (n < len) {
|
||||||
|
sbx->r += n;
|
||||||
|
} else {
|
||||||
|
sbx->r = sbx->w = sbx->b;
|
||||||
|
}
|
||||||
|
L->top = L->base+1; /* Chain buffer object. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_set) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
GCobj *ref;
|
||||||
|
const char *p;
|
||||||
|
MSize len;
|
||||||
|
#if LJ_HASFFI
|
||||||
|
if (tviscdata(L->base+1)) {
|
||||||
|
CTState *cts = ctype_cts(L);
|
||||||
|
lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p,
|
||||||
|
L->base+1, CCF_ARG(2));
|
||||||
|
len = (MSize)lj_lib_checkintrange(L, 3, 0, LJ_MAX_BUF);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
GCstr *str = lj_lib_checkstrx(L, 2);
|
||||||
|
p = strdata(str);
|
||||||
|
len = str->len;
|
||||||
|
}
|
||||||
|
lj_bufx_free(L, sbx);
|
||||||
|
lj_bufx_set_cow(L, sbx, p, len);
|
||||||
|
ref = gcV(L->base+1);
|
||||||
|
setgcref(sbx->cowref, ref);
|
||||||
|
lj_gc_objbarrier(L, buffer_toudata(sbx), ref);
|
||||||
|
L->top = L->base+1; /* Chain buffer object. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_put) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobufw(L);
|
||||||
|
ptrdiff_t arg, narg = L->top - L->base;
|
||||||
|
for (arg = 1; arg < narg; arg++) {
|
||||||
|
cTValue *o = &L->base[arg], *mo = NULL;
|
||||||
|
retry:
|
||||||
|
if (tvisstr(o)) {
|
||||||
|
lj_buf_putstr((SBuf *)sbx, strV(o));
|
||||||
|
} else if (tvisint(o)) {
|
||||||
|
lj_strfmt_putint((SBuf *)sbx, intV(o));
|
||||||
|
} else if (tvisnum(o)) {
|
||||||
|
lj_strfmt_putfnum((SBuf *)sbx, STRFMT_G14, numV(o));
|
||||||
|
} else if (tvisbuf(o)) {
|
||||||
|
SBufExt *sbx2 = bufV(o);
|
||||||
|
if (sbx2 == sbx) lj_err_arg(L, arg+1, LJ_ERR_BUFFER_SELF);
|
||||||
|
lj_buf_putmem((SBuf *)sbx, sbx2->r, sbufxlen(sbx2));
|
||||||
|
} else if (!mo && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
|
||||||
|
/* Call __tostring metamethod inline. */
|
||||||
|
copyTV(L, L->top++, mo);
|
||||||
|
copyTV(L, L->top++, o);
|
||||||
|
lua_call(L, 1, 1);
|
||||||
|
o = &L->base[arg]; /* The stack may have been reallocated. */
|
||||||
|
copyTV(L, &L->base[arg], L->top-1);
|
||||||
|
L->top = L->base + narg;
|
||||||
|
goto retry; /* Retry with the result. */
|
||||||
|
} else {
|
||||||
|
lj_err_argtype(L, arg+1, "string/number/__tostring");
|
||||||
|
}
|
||||||
|
/* Probably not useful to inline other __tostring MMs, e.g. FFI numbers. */
|
||||||
|
}
|
||||||
|
L->top = L->base+1; /* Chain buffer object. */
|
||||||
|
lj_gc_check(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_putf) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobufw(L);
|
||||||
|
lj_strfmt_putarg(L, (SBuf *)sbx, 2, 2);
|
||||||
|
L->top = L->base+1; /* Chain buffer object. */
|
||||||
|
lj_gc_check(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_get) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
ptrdiff_t arg, narg = L->top - L->base;
|
||||||
|
if (narg == 1) {
|
||||||
|
narg++;
|
||||||
|
setnilV(L->top++); /* get() is the same as get(nil). */
|
||||||
|
}
|
||||||
|
for (arg = 1; arg < narg; arg++) {
|
||||||
|
TValue *o = &L->base[arg];
|
||||||
|
MSize n = tvisnil(o) ? LJ_MAX_BUF :
|
||||||
|
(MSize) lj_lib_checkintrange(L, arg+1, 0, LJ_MAX_BUF);
|
||||||
|
MSize len = sbufxlen(sbx);
|
||||||
|
if (n > len) n = len;
|
||||||
|
setstrV(L, o, lj_str_new(L, sbx->r, n));
|
||||||
|
sbx->r += n;
|
||||||
|
}
|
||||||
|
if (sbx->r == sbx->w) sbx->r = sbx->w = sbx->b;
|
||||||
|
lj_gc_check(L);
|
||||||
|
return narg-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LJ_HASFFI
|
||||||
|
LJLIB_CF(buffer_method_putcdata) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobufw(L);
|
||||||
|
const char *p;
|
||||||
|
MSize len;
|
||||||
|
if (tviscdata(L->base+1)) {
|
||||||
|
CTState *cts = ctype_cts(L);
|
||||||
|
lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p,
|
||||||
|
L->base+1, CCF_ARG(2));
|
||||||
|
} else {
|
||||||
|
lj_err_argtype(L, 2, "cdata");
|
||||||
|
}
|
||||||
|
len = (MSize)lj_lib_checkintrange(L, 3, 0, LJ_MAX_BUF);
|
||||||
|
lj_buf_putmem((SBuf *)sbx, p, len);
|
||||||
|
L->top = L->base+1; /* Chain buffer object. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_reserve) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobufw(L);
|
||||||
|
MSize sz = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF);
|
||||||
|
GCcdata *cd;
|
||||||
|
lj_buf_more((SBuf *)sbx, sz);
|
||||||
|
ctype_loadffi(L);
|
||||||
|
cd = lj_cdata_new_(L, CTID_P_UINT8, CTSIZE_PTR);
|
||||||
|
*(void **)cdataptr(cd) = sbx->w;
|
||||||
|
setcdataV(L, L->top++, cd);
|
||||||
|
setintV(L->top++, sbufleft(sbx));
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_commit) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
MSize len = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF);
|
||||||
|
if (len > sbufleft(sbx)) lj_err_arg(L, 2, LJ_ERR_NUMRNG);
|
||||||
|
sbx->w += len;
|
||||||
|
L->top = L->base+1; /* Chain buffer object. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_ref) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
GCcdata *cd;
|
||||||
|
ctype_loadffi(L);
|
||||||
|
cd = lj_cdata_new_(L, CTID_P_UINT8, CTSIZE_PTR);
|
||||||
|
*(void **)cdataptr(cd) = sbx->r;
|
||||||
|
setcdataV(L, L->top++, cd);
|
||||||
|
setintV(L->top++, sbufxlen(sbx));
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_encode) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobufw(L);
|
||||||
|
cTValue *o = lj_lib_checkany(L, 2);
|
||||||
|
lj_serialize_put(sbx, o);
|
||||||
|
lj_gc_check(L);
|
||||||
|
L->top = L->base+1; /* Chain buffer object. */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method_decode) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobufw(L);
|
||||||
|
setnilV(L->top++);
|
||||||
|
sbx->r = lj_serialize_get(sbx, L->top-1);
|
||||||
|
lj_gc_check(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method___gc)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
lj_bufx_free(L, sbx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method___tostring) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
setstrV(L, L->top-1, lj_str_new(L, sbx->r, sbufxlen(sbx)));
|
||||||
|
lj_gc_check(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_method___len) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
SBufExt *sbx = buffer_tobuf(L);
|
||||||
|
setintV(L->top-1, (int32_t)sbufxlen(sbx));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_PUSH("buffer") LJLIB_SET(__metatable)
|
||||||
|
LJLIB_PUSH(top-1) LJLIB_SET(__index)
|
||||||
|
|
||||||
|
/* -- Buffer library functions -------------------------------------------- */
|
||||||
|
|
||||||
|
#define LJLIB_MODULE_buffer
|
||||||
|
|
||||||
|
LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_new)
|
||||||
|
{
|
||||||
|
MSize sz = 0;
|
||||||
|
int targ = 1;
|
||||||
|
GCtab *env, *dict_str = NULL, *dict_mt = NULL;
|
||||||
|
GCudata *ud;
|
||||||
|
SBufExt *sbx;
|
||||||
|
if (L->base < L->top && !tvistab(L->base)) {
|
||||||
|
targ = 2;
|
||||||
|
if (!tvisnil(L->base))
|
||||||
|
sz = (MSize)lj_lib_checkintrange(L, 1, 0, LJ_MAX_BUF);
|
||||||
|
}
|
||||||
|
if (L->base+targ-1 < L->top) {
|
||||||
|
GCtab *options = lj_lib_checktab(L, targ);
|
||||||
|
cTValue *opt_dict, *opt_mt;
|
||||||
|
opt_dict = lj_tab_getstr(options, lj_str_newlit(L, "dict"));
|
||||||
|
if (opt_dict && tvistab(opt_dict)) {
|
||||||
|
dict_str = tabV(opt_dict);
|
||||||
|
lj_serialize_dict_prep_str(L, dict_str);
|
||||||
|
}
|
||||||
|
opt_mt = lj_tab_getstr(options, lj_str_newlit(L, "metatable"));
|
||||||
|
if (opt_mt && tvistab(opt_mt)) {
|
||||||
|
dict_mt = tabV(opt_mt);
|
||||||
|
lj_serialize_dict_prep_mt(L, dict_mt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env = tabref(curr_func(L)->c.env);
|
||||||
|
ud = lj_udata_new(L, sizeof(SBufExt), env);
|
||||||
|
ud->udtype = UDTYPE_BUFFER;
|
||||||
|
/* NOBARRIER: The GCudata is new (marked white). */
|
||||||
|
setgcref(ud->metatable, obj2gco(env));
|
||||||
|
setudataV(L, L->top++, ud);
|
||||||
|
sbx = (SBufExt *)uddata(ud);
|
||||||
|
lj_bufx_init(L, sbx);
|
||||||
|
setgcref(sbx->dict_str, obj2gco(dict_str));
|
||||||
|
setgcref(sbx->dict_mt, obj2gco(dict_mt));
|
||||||
|
if (sz > 0) lj_buf_need2((SBuf *)sbx, sz);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_encode) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
cTValue *o = lj_lib_checkany(L, 1);
|
||||||
|
setstrV(L, L->top++, lj_serialize_encode(L, o));
|
||||||
|
lj_gc_check(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
LJLIB_CF(buffer_decode) LJLIB_REC(.)
|
||||||
|
{
|
||||||
|
GCstr *str = lj_lib_checkstrx(L, 1);
|
||||||
|
setnilV(L->top++);
|
||||||
|
lj_serialize_decode(L, L->top-1, str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
#include "lj_libdef.h"
|
||||||
|
|
||||||
|
int luaopen_string_buffer(lua_State *L)
|
||||||
|
{
|
||||||
|
LJ_LIB_REG(L, NULL, buffer_method);
|
||||||
|
lua_getfield(L, -1, "__tostring");
|
||||||
|
lua_setfield(L, -2, "tostring");
|
||||||
|
LJ_LIB_REG(L, NULL, buffer);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Debug library.
|
** Debug library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** FFI library.
|
** FFI library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lib_ffi_c
|
#define lib_ffi_c
|
||||||
@@ -573,6 +573,7 @@ LJLIB_CF(ffi_typeinfo)
|
|||||||
setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "sib")), (int32_t)ct->sib);
|
setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "sib")), (int32_t)ct->sib);
|
||||||
if (gcref(ct->name)) {
|
if (gcref(ct->name)) {
|
||||||
GCstr *s = gco2str(gcref(ct->name));
|
GCstr *s = gco2str(gcref(ct->name));
|
||||||
|
if (isdead(G(L), obj2gco(s))) flipwhite(obj2gco(s));
|
||||||
setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "name")), s);
|
setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "name")), s);
|
||||||
}
|
}
|
||||||
lj_gc_check(L);
|
lj_gc_check(L);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Library initialization.
|
** Library initialization.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major parts taken verbatim from the Lua interpreter.
|
** Major parts taken verbatim from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
|
|||||||
+20
-14
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** I/O library.
|
** I/O library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
@@ -60,12 +60,12 @@ static IOFileUD *io_tofile(lua_State *L)
|
|||||||
return iof;
|
return iof;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE *io_stdfile(lua_State *L, ptrdiff_t id)
|
static IOFileUD *io_stdfile(lua_State *L, ptrdiff_t id)
|
||||||
{
|
{
|
||||||
IOFileUD *iof = IOSTDF_IOF(L, id);
|
IOFileUD *iof = IOSTDF_IOF(L, id);
|
||||||
if (iof->fp == NULL)
|
if (iof->fp == NULL)
|
||||||
lj_err_caller(L, LJ_ERR_IOSTDCL);
|
lj_err_caller(L, LJ_ERR_IOSTDCL);
|
||||||
return iof->fp;
|
return iof;
|
||||||
}
|
}
|
||||||
|
|
||||||
static IOFileUD *io_file_new(lua_State *L)
|
static IOFileUD *io_file_new(lua_State *L)
|
||||||
@@ -178,7 +178,7 @@ static int io_file_readlen(lua_State *L, FILE *fp, MSize m)
|
|||||||
MSize n = (MSize)fread(buf, 1, m, fp);
|
MSize n = (MSize)fread(buf, 1, m, fp);
|
||||||
setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
|
setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
|
||||||
lj_gc_check(L);
|
lj_gc_check(L);
|
||||||
return (n > 0 || m == 0);
|
return n > 0;
|
||||||
} else {
|
} else {
|
||||||
int c = getc(fp);
|
int c = getc(fp);
|
||||||
ungetc(c, fp);
|
ungetc(c, fp);
|
||||||
@@ -187,8 +187,9 @@ static int io_file_readlen(lua_State *L, FILE *fp, MSize m)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int io_file_read(lua_State *L, FILE *fp, int start)
|
static int io_file_read(lua_State *L, IOFileUD *iof, int start)
|
||||||
{
|
{
|
||||||
|
FILE *fp = iof->fp;
|
||||||
int ok, n, nargs = (int)(L->top - L->base) - start;
|
int ok, n, nargs = (int)(L->top - L->base) - start;
|
||||||
clearerr(fp);
|
clearerr(fp);
|
||||||
if (nargs == 0) {
|
if (nargs == 0) {
|
||||||
@@ -224,8 +225,9 @@ static int io_file_read(lua_State *L, FILE *fp, int start)
|
|||||||
return n - start;
|
return n - start;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int io_file_write(lua_State *L, FILE *fp, int start)
|
static int io_file_write(lua_State *L, IOFileUD *iof, int start)
|
||||||
{
|
{
|
||||||
|
FILE *fp = iof->fp;
|
||||||
cTValue *tv;
|
cTValue *tv;
|
||||||
int status = 1;
|
int status = 1;
|
||||||
for (tv = L->base+start; tv < L->top; tv++) {
|
for (tv = L->base+start; tv < L->top; tv++) {
|
||||||
@@ -253,13 +255,11 @@ static int io_file_iter(lua_State *L)
|
|||||||
lj_err_caller(L, LJ_ERR_IOCLFL);
|
lj_err_caller(L, LJ_ERR_IOCLFL);
|
||||||
L->top = L->base;
|
L->top = L->base;
|
||||||
if (n) { /* Copy upvalues with options to stack. */
|
if (n) { /* Copy upvalues with options to stack. */
|
||||||
if (n > LUAI_MAXCSTACK)
|
|
||||||
lj_err_caller(L, LJ_ERR_STKOV);
|
|
||||||
lj_state_checkstack(L, (MSize)n);
|
lj_state_checkstack(L, (MSize)n);
|
||||||
memcpy(L->top, &fn->c.upvalue[1], n*sizeof(TValue));
|
memcpy(L->top, &fn->c.upvalue[1], n*sizeof(TValue));
|
||||||
L->top += n;
|
L->top += n;
|
||||||
}
|
}
|
||||||
n = io_file_read(L, iof->fp, 0);
|
n = io_file_read(L, iof, 0);
|
||||||
if (ferror(iof->fp))
|
if (ferror(iof->fp))
|
||||||
lj_err_callermsg(L, strVdata(L->top-2));
|
lj_err_callermsg(L, strVdata(L->top-2));
|
||||||
if (tvisnil(L->base) && (iof->type & IOFILE_FLAG_CLOSE)) {
|
if (tvisnil(L->base) && (iof->type & IOFILE_FLAG_CLOSE)) {
|
||||||
@@ -284,19 +284,25 @@ static int io_file_lines(lua_State *L)
|
|||||||
|
|
||||||
LJLIB_CF(io_method_close)
|
LJLIB_CF(io_method_close)
|
||||||
{
|
{
|
||||||
IOFileUD *iof = L->base < L->top ? io_tofile(L) :
|
IOFileUD *iof;
|
||||||
IOSTDF_IOF(L, GCROOT_IO_OUTPUT);
|
if (L->base < L->top) {
|
||||||
|
iof = io_tofile(L);
|
||||||
|
} else {
|
||||||
|
iof = IOSTDF_IOF(L, GCROOT_IO_OUTPUT);
|
||||||
|
if (iof->fp == NULL)
|
||||||
|
lj_err_caller(L, LJ_ERR_IOCLFL);
|
||||||
|
}
|
||||||
return io_file_close(L, iof);
|
return io_file_close(L, iof);
|
||||||
}
|
}
|
||||||
|
|
||||||
LJLIB_CF(io_method_read)
|
LJLIB_CF(io_method_read)
|
||||||
{
|
{
|
||||||
return io_file_read(L, io_tofile(L)->fp, 1);
|
return io_file_read(L, io_tofile(L), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
LJLIB_CF(io_method_write) LJLIB_REC(io_write 0)
|
LJLIB_CF(io_method_write) LJLIB_REC(io_write 0)
|
||||||
{
|
{
|
||||||
return io_file_write(L, io_tofile(L)->fp, 1);
|
return io_file_write(L, io_tofile(L), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0)
|
LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0)
|
||||||
@@ -458,7 +464,7 @@ LJLIB_CF(io_write) LJLIB_REC(io_write GCROOT_IO_OUTPUT)
|
|||||||
|
|
||||||
LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT)
|
LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT)
|
||||||
{
|
{
|
||||||
return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)) == 0, NULL);
|
return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)->fp) == 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode)
|
static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** JIT library.
|
** JIT library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lib_jit_c
|
#define lib_jit_c
|
||||||
@@ -346,11 +346,7 @@ LJLIB_CF(jit_util_tracek)
|
|||||||
ir = &T->ir[ir->op1];
|
ir = &T->ir[ir->op1];
|
||||||
}
|
}
|
||||||
#if LJ_HASFFI
|
#if LJ_HASFFI
|
||||||
if (ir->o == IR_KINT64 && !ctype_ctsG(G(L))) {
|
if (ir->o == IR_KINT64) ctype_loadffi(L);
|
||||||
ptrdiff_t oldtop = savestack(L, L->top);
|
|
||||||
luaopen_ffi(L); /* Load FFI library on-demand. */
|
|
||||||
L->top = restorestack(L, oldtop);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
lj_ir_kvalue(L, L->top-2, ir);
|
lj_ir_kvalue(L, L->top-2, ir);
|
||||||
setintV(L->top-1, (int32_t)irt_type(ir->t));
|
setintV(L->top-1, (int32_t)irt_type(ir->t));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Math library.
|
** Math library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** OS library.
|
** OS library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Package library.
|
** Package library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2012 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2012 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** String library.
|
** String library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
@@ -640,89 +640,14 @@ LJLIB_CF(string_gsub)
|
|||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
/* Emulate tostring() inline. */
|
|
||||||
static GCstr *string_fmt_tostring(lua_State *L, int arg, int retry)
|
|
||||||
{
|
|
||||||
TValue *o = L->base+arg-1;
|
|
||||||
cTValue *mo;
|
|
||||||
lj_assertL(o < L->top, "bad usage"); /* Caller already checks for existence. */
|
|
||||||
if (LJ_LIKELY(tvisstr(o)))
|
|
||||||
return strV(o);
|
|
||||||
if (retry != 2 && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
|
|
||||||
copyTV(L, L->top++, mo);
|
|
||||||
copyTV(L, L->top++, o);
|
|
||||||
lua_call(L, 1, 1);
|
|
||||||
copyTV(L, L->base+arg-1, --L->top);
|
|
||||||
return NULL; /* Buffer may be overwritten, retry. */
|
|
||||||
}
|
|
||||||
return lj_strfmt_obj(L, o);
|
|
||||||
}
|
|
||||||
|
|
||||||
LJLIB_CF(string_format) LJLIB_REC(.)
|
LJLIB_CF(string_format) LJLIB_REC(.)
|
||||||
{
|
{
|
||||||
int arg, top = (int)(L->top - L->base);
|
|
||||||
GCstr *fmt;
|
|
||||||
SBuf *sb;
|
|
||||||
FormatState fs;
|
|
||||||
SFormat sf;
|
|
||||||
int retry = 0;
|
int retry = 0;
|
||||||
again:
|
SBuf *sb;
|
||||||
arg = 1;
|
do {
|
||||||
sb = lj_buf_tmp_(L);
|
sb = lj_buf_tmp_(L);
|
||||||
fmt = lj_lib_checkstr(L, arg);
|
retry = lj_strfmt_putarg(L, sb, 1, -retry);
|
||||||
lj_strfmt_init(&fs, strdata(fmt), fmt->len);
|
} while (retry > 0);
|
||||||
while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) {
|
|
||||||
if (sf == STRFMT_LIT) {
|
|
||||||
lj_buf_putmem(sb, fs.str, fs.len);
|
|
||||||
} else if (sf == STRFMT_ERR) {
|
|
||||||
lj_err_callerv(L, LJ_ERR_STRFMT, strdata(lj_str_new(L, fs.str, fs.len)));
|
|
||||||
} else {
|
|
||||||
if (++arg > top)
|
|
||||||
luaL_argerror(L, arg, lj_obj_typename[0]);
|
|
||||||
switch (STRFMT_TYPE(sf)) {
|
|
||||||
case STRFMT_INT:
|
|
||||||
if (tvisint(L->base+arg-1)) {
|
|
||||||
int32_t k = intV(L->base+arg-1);
|
|
||||||
if (sf == STRFMT_INT)
|
|
||||||
lj_strfmt_putint(sb, k); /* Shortcut for plain %d. */
|
|
||||||
else
|
|
||||||
lj_strfmt_putfxint(sb, sf, k);
|
|
||||||
} else {
|
|
||||||
lj_strfmt_putfnum_int(sb, sf, lj_lib_checknum(L, arg));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case STRFMT_UINT:
|
|
||||||
if (tvisint(L->base+arg-1))
|
|
||||||
lj_strfmt_putfxint(sb, sf, intV(L->base+arg-1));
|
|
||||||
else
|
|
||||||
lj_strfmt_putfnum_uint(sb, sf, lj_lib_checknum(L, arg));
|
|
||||||
break;
|
|
||||||
case STRFMT_NUM:
|
|
||||||
lj_strfmt_putfnum(sb, sf, lj_lib_checknum(L, arg));
|
|
||||||
break;
|
|
||||||
case STRFMT_STR: {
|
|
||||||
GCstr *str = string_fmt_tostring(L, arg, retry);
|
|
||||||
if (str == NULL)
|
|
||||||
retry = 1;
|
|
||||||
else if ((sf & STRFMT_T_QUOTED))
|
|
||||||
lj_strfmt_putquoted(sb, str); /* No formatting. */
|
|
||||||
else
|
|
||||||
lj_strfmt_putfstr(sb, sf, str);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STRFMT_CHAR:
|
|
||||||
lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg));
|
|
||||||
break;
|
|
||||||
case STRFMT_PTR: /* No formatting. */
|
|
||||||
lj_strfmt_putptr(sb, lj_obj_ptr(G(L), L->base+arg-1));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
lj_assertL(0, "bad string format type");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (retry++ == 1) goto again;
|
|
||||||
setstrV(L, L->top-1, lj_buf_str(L, sb));
|
setstrV(L, L->top-1, lj_buf_str(L, sb));
|
||||||
lj_gc_check(L);
|
lj_gc_check(L);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -743,6 +668,9 @@ LUALIB_API int luaopen_string(lua_State *L)
|
|||||||
setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt));
|
setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt));
|
||||||
settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1));
|
settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1));
|
||||||
mt->nomm = (uint8_t)(~(1u<<MM_index));
|
mt->nomm = (uint8_t)(~(1u<<MM_index));
|
||||||
|
#if LJ_HASBUFFER
|
||||||
|
lj_lib_prereg(L, LUA_STRLIBNAME ".buffer", luaopen_string_buffer, tabV(L->top-1));
|
||||||
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Table library.
|
** Table library.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
@@ -159,7 +159,7 @@ LJLIB_CF(table_concat) LJLIB_REC(.)
|
|||||||
SBuf *sb = lj_buf_tmp_(L);
|
SBuf *sb = lj_buf_tmp_(L);
|
||||||
SBuf *sbx = lj_buf_puttab(sb, t, sep, i, e);
|
SBuf *sbx = lj_buf_puttab(sb, t, sep, i, e);
|
||||||
if (LJ_UNLIKELY(!sbx)) { /* Error: bad element type. */
|
if (LJ_UNLIKELY(!sbx)) { /* Error: bad element type. */
|
||||||
int32_t idx = (int32_t)(intptr_t)sbufP(sb);
|
int32_t idx = (int32_t)(intptr_t)sb->w;
|
||||||
cTValue *o = lj_tab_getint(t, idx);
|
cTValue *o = lj_tab_getint(t, idx);
|
||||||
lj_err_callerv(L, LJ_ERR_TABCAT,
|
lj_err_callerv(L, LJ_ERR_TABCAT,
|
||||||
lj_obj_itypename[o ? itypemap(o) : ~LJ_TNIL], idx);
|
lj_obj_itypename[o ? itypemap(o) : ~LJ_TNIL], idx);
|
||||||
|
|||||||
@@ -365,7 +365,7 @@ static void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, int flags)
|
|||||||
#define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv))
|
#define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv))
|
||||||
#define CALL_MREMAP_NOMOVE 0
|
#define CALL_MREMAP_NOMOVE 0
|
||||||
#define CALL_MREMAP_MAYMOVE 1
|
#define CALL_MREMAP_MAYMOVE 1
|
||||||
#if LJ_64 && !LJ_GC64
|
#if LJ_64 && (!LJ_GC64 || LJ_TARGET_ARM64)
|
||||||
#define CALL_MREMAP_MV CALL_MREMAP_NOMOVE
|
#define CALL_MREMAP_MV CALL_MREMAP_NOMOVE
|
||||||
#else
|
#else
|
||||||
#define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE
|
#define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Public Lua/C API.
|
** Public Lua/C API.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||||
@@ -707,36 +707,10 @@ LUA_API void lua_pushboolean(lua_State *L, int b)
|
|||||||
incr_top(L);
|
incr_top(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LJ_64
|
|
||||||
static void *lightud_intern(lua_State *L, void *p)
|
|
||||||
{
|
|
||||||
global_State *g = G(L);
|
|
||||||
uint64_t u = (uint64_t)p;
|
|
||||||
uint32_t up = lightudup(u);
|
|
||||||
uint32_t *segmap = mref(g->gc.lightudseg, uint32_t);
|
|
||||||
MSize segnum = g->gc.lightudnum;
|
|
||||||
if (segmap) {
|
|
||||||
MSize seg;
|
|
||||||
for (seg = 0; seg <= segnum; seg++)
|
|
||||||
if (segmap[seg] == up) /* Fast path. */
|
|
||||||
return (void *)(((uint64_t)seg << LJ_LIGHTUD_BITS_LO) | lightudlo(u));
|
|
||||||
segnum++;
|
|
||||||
}
|
|
||||||
if (!((segnum-1) & segnum) && segnum != 1) {
|
|
||||||
if (segnum >= (1 << LJ_LIGHTUD_BITS_SEG)) lj_err_msg(L, LJ_ERR_BADLU);
|
|
||||||
lj_mem_reallocvec(L, segmap, segnum, segnum ? 2*segnum : 2u, uint32_t);
|
|
||||||
setmref(g->gc.lightudseg, segmap);
|
|
||||||
}
|
|
||||||
g->gc.lightudnum = segnum;
|
|
||||||
segmap[segnum] = up;
|
|
||||||
return (void *)(((uint64_t)segnum << LJ_LIGHTUD_BITS_LO) | lightudlo(u));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
|
LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
|
||||||
{
|
{
|
||||||
#if LJ_64
|
#if LJ_64
|
||||||
p = lightud_intern(L, p);
|
p = lj_lightud_intern(L, p);
|
||||||
#endif
|
#endif
|
||||||
setrawlightudV(L->top, p);
|
setrawlightudV(L->top, p);
|
||||||
incr_top(L);
|
incr_top(L);
|
||||||
@@ -919,11 +893,13 @@ LUA_API int lua_next(lua_State *L, int idx)
|
|||||||
cTValue *t = index2adr(L, idx);
|
cTValue *t = index2adr(L, idx);
|
||||||
int more;
|
int more;
|
||||||
lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
|
lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
|
||||||
more = lj_tab_next(L, tabV(t), L->top-1);
|
more = lj_tab_next(tabV(t), L->top-1, L->top-1);
|
||||||
if (more) {
|
if (more > 0) {
|
||||||
incr_top(L); /* Return new key and value slot. */
|
incr_top(L); /* Return new key and value slot. */
|
||||||
} else { /* End of traversal. */
|
} else if (!more) { /* End of traversal. */
|
||||||
L->top--; /* Remove key slot. */
|
L->top--; /* Remove key slot. */
|
||||||
|
} else {
|
||||||
|
lj_err_msg(L, LJ_ERR_NEXTIDX);
|
||||||
}
|
}
|
||||||
return more;
|
return more;
|
||||||
}
|
}
|
||||||
@@ -1179,7 +1155,7 @@ static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
|
|||||||
setfuncV(L, top++, fn);
|
setfuncV(L, top++, fn);
|
||||||
if (LJ_FR2) setnilV(top++);
|
if (LJ_FR2) setnilV(top++);
|
||||||
#if LJ_64
|
#if LJ_64
|
||||||
ud = lightud_intern(L, ud);
|
ud = lj_lightud_intern(L, ud);
|
||||||
#endif
|
#endif
|
||||||
setrawlightudV(top++, ud);
|
setrawlightudV(top++, ud);
|
||||||
cframe_nres(L->cframe) = 1+0; /* Zero results. */
|
cframe_nres(L->cframe) = 1+0; /* Zero results. */
|
||||||
|
|||||||
+36
-18
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Target architecture selection.
|
** Target architecture selection.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_ARCH_H
|
#ifndef _LJ_ARCH_H
|
||||||
@@ -170,14 +170,10 @@
|
|||||||
#define LJ_ARCH_NAME "x86"
|
#define LJ_ARCH_NAME "x86"
|
||||||
#define LJ_ARCH_BITS 32
|
#define LJ_ARCH_BITS 32
|
||||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||||
#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
|
|
||||||
#define LJ_ABI_WIN 1
|
|
||||||
#else
|
|
||||||
#define LJ_ABI_WIN 0
|
|
||||||
#endif
|
|
||||||
#define LJ_TARGET_X86 1
|
#define LJ_TARGET_X86 1
|
||||||
#define LJ_TARGET_X86ORX64 1
|
#define LJ_TARGET_X86ORX64 1
|
||||||
#define LJ_TARGET_EHRETREG 0
|
#define LJ_TARGET_EHRETREG 0
|
||||||
|
#define LJ_TARGET_EHRAREG 8
|
||||||
#define LJ_TARGET_MASKSHIFT 1
|
#define LJ_TARGET_MASKSHIFT 1
|
||||||
#define LJ_TARGET_MASKROT 1
|
#define LJ_TARGET_MASKROT 1
|
||||||
#define LJ_TARGET_UNALIGNED 1
|
#define LJ_TARGET_UNALIGNED 1
|
||||||
@@ -188,14 +184,10 @@
|
|||||||
#define LJ_ARCH_NAME "x64"
|
#define LJ_ARCH_NAME "x64"
|
||||||
#define LJ_ARCH_BITS 64
|
#define LJ_ARCH_BITS 64
|
||||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||||
#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
|
|
||||||
#define LJ_ABI_WIN 1
|
|
||||||
#else
|
|
||||||
#define LJ_ABI_WIN 0
|
|
||||||
#endif
|
|
||||||
#define LJ_TARGET_X64 1
|
#define LJ_TARGET_X64 1
|
||||||
#define LJ_TARGET_X86ORX64 1
|
#define LJ_TARGET_X86ORX64 1
|
||||||
#define LJ_TARGET_EHRETREG 0
|
#define LJ_TARGET_EHRETREG 0
|
||||||
|
#define LJ_TARGET_EHRAREG 16
|
||||||
#define LJ_TARGET_JUMPRANGE 31 /* +-2^31 = +-2GB */
|
#define LJ_TARGET_JUMPRANGE 31 /* +-2^31 = +-2GB */
|
||||||
#define LJ_TARGET_MASKSHIFT 1
|
#define LJ_TARGET_MASKSHIFT 1
|
||||||
#define LJ_TARGET_MASKROT 1
|
#define LJ_TARGET_MASKROT 1
|
||||||
@@ -203,6 +195,8 @@
|
|||||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE_DUAL
|
#define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE_DUAL
|
||||||
#ifndef LUAJIT_DISABLE_GC64
|
#ifndef LUAJIT_DISABLE_GC64
|
||||||
#define LJ_TARGET_GC64 1
|
#define LJ_TARGET_GC64 1
|
||||||
|
#elif LJ_TARGET_OSX
|
||||||
|
#error "macOS requires GC64 -- don't disable it"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM
|
#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM
|
||||||
@@ -219,6 +213,7 @@
|
|||||||
#define LJ_ABI_EABI 1
|
#define LJ_ABI_EABI 1
|
||||||
#define LJ_TARGET_ARM 1
|
#define LJ_TARGET_ARM 1
|
||||||
#define LJ_TARGET_EHRETREG 0
|
#define LJ_TARGET_EHRETREG 0
|
||||||
|
#define LJ_TARGET_EHRAREG 14
|
||||||
#define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */
|
#define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */
|
||||||
#define LJ_TARGET_MASKSHIFT 0
|
#define LJ_TARGET_MASKSHIFT 0
|
||||||
#define LJ_TARGET_MASKROT 1
|
#define LJ_TARGET_MASKROT 1
|
||||||
@@ -249,6 +244,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#define LJ_TARGET_ARM64 1
|
#define LJ_TARGET_ARM64 1
|
||||||
#define LJ_TARGET_EHRETREG 0
|
#define LJ_TARGET_EHRETREG 0
|
||||||
|
#define LJ_TARGET_EHRAREG 30
|
||||||
#define LJ_TARGET_JUMPRANGE 27 /* +-2^27 = +-128MB */
|
#define LJ_TARGET_JUMPRANGE 27 /* +-2^27 = +-128MB */
|
||||||
#define LJ_TARGET_MASKSHIFT 1
|
#define LJ_TARGET_MASKSHIFT 1
|
||||||
#define LJ_TARGET_MASKROT 1
|
#define LJ_TARGET_MASKROT 1
|
||||||
@@ -304,6 +300,7 @@
|
|||||||
|
|
||||||
#define LJ_TARGET_PPC 1
|
#define LJ_TARGET_PPC 1
|
||||||
#define LJ_TARGET_EHRETREG 3
|
#define LJ_TARGET_EHRETREG 3
|
||||||
|
#define LJ_TARGET_EHRAREG 65
|
||||||
#define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */
|
#define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */
|
||||||
#define LJ_TARGET_MASKSHIFT 0
|
#define LJ_TARGET_MASKSHIFT 0
|
||||||
#define LJ_TARGET_MASKROT 1
|
#define LJ_TARGET_MASKROT 1
|
||||||
@@ -406,6 +403,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#define LJ_TARGET_MIPS 1
|
#define LJ_TARGET_MIPS 1
|
||||||
#define LJ_TARGET_EHRETREG 4
|
#define LJ_TARGET_EHRETREG 4
|
||||||
|
#define LJ_TARGET_EHRAREG 31
|
||||||
#define LJ_TARGET_JUMPRANGE 27 /* 2*2^27 = 256MB-aligned region */
|
#define LJ_TARGET_JUMPRANGE 27 /* 2*2^27 = 256MB-aligned region */
|
||||||
#define LJ_TARGET_MASKSHIFT 1
|
#define LJ_TARGET_MASKSHIFT 1
|
||||||
#define LJ_TARGET_MASKROT 1
|
#define LJ_TARGET_MASKROT 1
|
||||||
@@ -551,6 +549,13 @@
|
|||||||
#define LJ_HASFFI 1
|
#define LJ_HASFFI 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Disable or enable the string buffer extension. */
|
||||||
|
#if defined(LUAJIT_DISABLE_BUFFER)
|
||||||
|
#define LJ_HASBUFFER 0
|
||||||
|
#else
|
||||||
|
#define LJ_HASBUFFER 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(LUAJIT_DISABLE_PROFILE)
|
#if defined(LUAJIT_DISABLE_PROFILE)
|
||||||
#define LJ_HASPROFILE 0
|
#define LJ_HASPROFILE 0
|
||||||
#elif LJ_TARGET_POSIX
|
#elif LJ_TARGET_POSIX
|
||||||
@@ -611,13 +616,10 @@
|
|||||||
#define LJ_NO_SYSTEM 1
|
#define LJ_NO_SYSTEM 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(LUAJIT_NO_UNWIND) && __GNU_COMPACT_EH__
|
#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
|
||||||
/* NYI: no support for compact unwind specification, yet. */
|
#define LJ_ABI_WIN 1
|
||||||
#define LUAJIT_NO_UNWIND 1
|
#else
|
||||||
#endif
|
#define LJ_ABI_WIN 0
|
||||||
|
|
||||||
#if defined(LUAJIT_NO_UNWIND) || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4
|
|
||||||
#define LJ_NO_UNWIND 1
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LJ_TARGET_WINDOWS
|
#if LJ_TARGET_WINDOWS
|
||||||
@@ -632,6 +634,22 @@ extern void *LJ_WIN_LOADLIBA(const char *path);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(LUAJIT_NO_UNWIND) || __GNU_COMPACT_EH__ || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4
|
||||||
|
#define LJ_NO_UNWIND 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !LJ_NO_UNWIND && !defined(LUAJIT_UNWIND_INTERNAL) && (LJ_ABI_WIN || (defined(LUAJIT_UNWIND_EXTERNAL) && (defined(__GNUC__) || defined(__clang__))))
|
||||||
|
#define LJ_UNWIND_EXT 1
|
||||||
|
#else
|
||||||
|
#define LJ_UNWIND_EXT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LJ_UNWIND_EXT && LJ_HASJIT && !LJ_TARGET_ARM && !(LJ_ABI_WIN && LJ_TARGET_X86)
|
||||||
|
#define LJ_UNWIND_JIT 1
|
||||||
|
#else
|
||||||
|
#define LJ_UNWIND_JIT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Compatibility with Lua 5.1 vs. 5.2. */
|
/* Compatibility with Lua 5.1 vs. 5.2. */
|
||||||
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|
#ifdef LUAJIT_ENABLE_LUA52COMPAT
|
||||||
#define LJ_52 1
|
#define LJ_52 1
|
||||||
|
|||||||
+155
-63
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** IR assembler (SSA IR -> machine code).
|
** IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_asm_c
|
#define lj_asm_c
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#if LJ_HASJIT
|
#if LJ_HASJIT
|
||||||
|
|
||||||
#include "lj_gc.h"
|
#include "lj_gc.h"
|
||||||
|
#include "lj_buf.h"
|
||||||
#include "lj_str.h"
|
#include "lj_str.h"
|
||||||
#include "lj_tab.h"
|
#include "lj_tab.h"
|
||||||
#include "lj_frame.h"
|
#include "lj_frame.h"
|
||||||
@@ -71,6 +72,8 @@ typedef struct ASMState {
|
|||||||
IRRef snaprename; /* Rename highwater mark for snapshot check. */
|
IRRef snaprename; /* Rename highwater mark for snapshot check. */
|
||||||
SnapNo snapno; /* Current snapshot number. */
|
SnapNo snapno; /* Current snapshot number. */
|
||||||
SnapNo loopsnapno; /* Loop snapshot number. */
|
SnapNo loopsnapno; /* Loop snapshot number. */
|
||||||
|
int snapalloc; /* Current snapshot needs allocation. */
|
||||||
|
BloomFilter snapfilt1, snapfilt2; /* Filled with snapshot refs. */
|
||||||
|
|
||||||
IRRef fuseref; /* Fusion limit (loopref, 0 or FUSE_DISABLED). */
|
IRRef fuseref; /* Fusion limit (loopref, 0 or FUSE_DISABLED). */
|
||||||
IRRef sectref; /* Section base reference (loopref or 0). */
|
IRRef sectref; /* Section base reference (loopref or 0). */
|
||||||
@@ -84,6 +87,7 @@ typedef struct ASMState {
|
|||||||
|
|
||||||
MCode *mcbot; /* Bottom of reserved MCode. */
|
MCode *mcbot; /* Bottom of reserved MCode. */
|
||||||
MCode *mctop; /* Top of generated MCode. */
|
MCode *mctop; /* Top of generated MCode. */
|
||||||
|
MCode *mctoporig; /* Original top of generated MCode. */
|
||||||
MCode *mcloop; /* Pointer to loop MCode (or NULL). */
|
MCode *mcloop; /* Pointer to loop MCode (or NULL). */
|
||||||
MCode *invmcp; /* Points to invertible loop branch (or NULL). */
|
MCode *invmcp; /* Points to invertible loop branch (or NULL). */
|
||||||
MCode *flagmcp; /* Pending opportunity to merge flag setting ins. */
|
MCode *flagmcp; /* Pending opportunity to merge flag setting ins. */
|
||||||
@@ -694,7 +698,14 @@ static void ra_rename(ASMState *as, Reg down, Reg up)
|
|||||||
RA_DBGX((as, "rename $f $r $r", regcost_ref(as->cost[up]), down, up));
|
RA_DBGX((as, "rename $f $r $r", regcost_ref(as->cost[up]), down, up));
|
||||||
emit_movrr(as, ir, down, up); /* Backwards codegen needs inverse move. */
|
emit_movrr(as, ir, down, up); /* Backwards codegen needs inverse move. */
|
||||||
if (!ra_hasspill(IR(ref)->s)) { /* Add the rename to the IR. */
|
if (!ra_hasspill(IR(ref)->s)) { /* Add the rename to the IR. */
|
||||||
ra_addrename(as, down, ref, as->snapno);
|
/*
|
||||||
|
** The rename is effective at the subsequent (already emitted) exit
|
||||||
|
** branch. This is for the current snapshot (as->snapno). Except if we
|
||||||
|
** haven't yet allocated any refs for the snapshot (as->snapalloc == 1),
|
||||||
|
** then it belongs to the next snapshot.
|
||||||
|
** See also the discussion at asm_snap_checkrename().
|
||||||
|
*/
|
||||||
|
ra_addrename(as, down, ref, as->snapno + as->snapalloc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -807,11 +818,11 @@ static void ra_leftov(ASMState *as, Reg dest, IRRef lref)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !LJ_64
|
|
||||||
/* Force a RID_RETLO/RID_RETHI destination register pair (marked as free). */
|
/* Force a RID_RETLO/RID_RETHI destination register pair (marked as free). */
|
||||||
static void ra_destpair(ASMState *as, IRIns *ir)
|
static void ra_destpair(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
Reg destlo = ir->r, desthi = (ir+1)->r;
|
Reg destlo = ir->r, desthi = (ir+1)->r;
|
||||||
|
IRIns *irx = (LJ_64 && !irt_is64(ir->t)) ? ir+1 : ir;
|
||||||
/* First spill unrelated refs blocking the destination registers. */
|
/* First spill unrelated refs blocking the destination registers. */
|
||||||
if (!rset_test(as->freeset, RID_RETLO) &&
|
if (!rset_test(as->freeset, RID_RETLO) &&
|
||||||
destlo != RID_RETLO && desthi != RID_RETLO)
|
destlo != RID_RETLO && desthi != RID_RETLO)
|
||||||
@@ -835,29 +846,28 @@ static void ra_destpair(ASMState *as, IRIns *ir)
|
|||||||
/* Check for conflicts and shuffle the registers as needed. */
|
/* Check for conflicts and shuffle the registers as needed. */
|
||||||
if (destlo == RID_RETHI) {
|
if (destlo == RID_RETHI) {
|
||||||
if (desthi == RID_RETLO) {
|
if (desthi == RID_RETLO) {
|
||||||
#if LJ_TARGET_X86
|
#if LJ_TARGET_X86ORX64
|
||||||
*--as->mcp = XI_XCHGa + RID_RETHI;
|
*--as->mcp = REX_64IR(irx, XI_XCHGa + RID_RETHI);
|
||||||
#else
|
#else
|
||||||
emit_movrr(as, ir, RID_RETHI, RID_TMP);
|
emit_movrr(as, irx, RID_RETHI, RID_TMP);
|
||||||
emit_movrr(as, ir, RID_RETLO, RID_RETHI);
|
emit_movrr(as, irx, RID_RETLO, RID_RETHI);
|
||||||
emit_movrr(as, ir, RID_TMP, RID_RETLO);
|
emit_movrr(as, irx, RID_TMP, RID_RETLO);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
emit_movrr(as, ir, RID_RETHI, RID_RETLO);
|
emit_movrr(as, irx, RID_RETHI, RID_RETLO);
|
||||||
if (desthi != RID_RETHI) emit_movrr(as, ir, desthi, RID_RETHI);
|
if (desthi != RID_RETHI) emit_movrr(as, irx, desthi, RID_RETHI);
|
||||||
}
|
}
|
||||||
} else if (desthi == RID_RETLO) {
|
} else if (desthi == RID_RETLO) {
|
||||||
emit_movrr(as, ir, RID_RETLO, RID_RETHI);
|
emit_movrr(as, irx, RID_RETLO, RID_RETHI);
|
||||||
if (destlo != RID_RETLO) emit_movrr(as, ir, destlo, RID_RETLO);
|
if (destlo != RID_RETLO) emit_movrr(as, irx, destlo, RID_RETLO);
|
||||||
} else {
|
} else {
|
||||||
if (desthi != RID_RETHI) emit_movrr(as, ir, desthi, RID_RETHI);
|
if (desthi != RID_RETHI) emit_movrr(as, irx, desthi, RID_RETHI);
|
||||||
if (destlo != RID_RETLO) emit_movrr(as, ir, destlo, RID_RETLO);
|
if (destlo != RID_RETLO) emit_movrr(as, irx, destlo, RID_RETLO);
|
||||||
}
|
}
|
||||||
/* Restore spill slots (if any). */
|
/* Restore spill slots (if any). */
|
||||||
if (ra_hasspill((ir+1)->s)) ra_save(as, ir+1, RID_RETHI);
|
if (ra_hasspill((ir+1)->s)) ra_save(as, ir+1, RID_RETHI);
|
||||||
if (ra_hasspill(ir->s)) ra_save(as, ir, RID_RETLO);
|
if (ra_hasspill(ir->s)) ra_save(as, ir, RID_RETLO);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* -- Snapshot handling --------- ----------------------------------------- */
|
/* -- Snapshot handling --------- ----------------------------------------- */
|
||||||
|
|
||||||
@@ -892,7 +902,10 @@ static int asm_sunk_store(ASMState *as, IRIns *ira, IRIns *irs)
|
|||||||
static void asm_snap_alloc1(ASMState *as, IRRef ref)
|
static void asm_snap_alloc1(ASMState *as, IRRef ref)
|
||||||
{
|
{
|
||||||
IRIns *ir = IR(ref);
|
IRIns *ir = IR(ref);
|
||||||
if (!irref_isk(ref) && (!(ra_used(ir) || ir->r == RID_SUNK))) {
|
if (!irref_isk(ref) && ir->r != RID_SUNK) {
|
||||||
|
bloomset(as->snapfilt1, ref);
|
||||||
|
bloomset(as->snapfilt2, hashrot(ref, ref + HASH_BIAS));
|
||||||
|
if (ra_used(ir)) return;
|
||||||
if (ir->r == RID_SINK) {
|
if (ir->r == RID_SINK) {
|
||||||
ir->r = RID_SUNK;
|
ir->r = RID_SUNK;
|
||||||
#if LJ_HASFFI
|
#if LJ_HASFFI
|
||||||
@@ -947,11 +960,12 @@ static void asm_snap_alloc1(ASMState *as, IRRef ref)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate refs escaping to a snapshot. */
|
/* Allocate refs escaping to a snapshot. */
|
||||||
static void asm_snap_alloc(ASMState *as)
|
static void asm_snap_alloc(ASMState *as, int snapno)
|
||||||
{
|
{
|
||||||
SnapShot *snap = &as->T->snap[as->snapno];
|
SnapShot *snap = &as->T->snap[snapno];
|
||||||
SnapEntry *map = &as->T->snapmap[snap->mapofs];
|
SnapEntry *map = &as->T->snapmap[snap->mapofs];
|
||||||
MSize n, nent = snap->nent;
|
MSize n, nent = snap->nent;
|
||||||
|
as->snapfilt1 = as->snapfilt2 = 0;
|
||||||
for (n = 0; n < nent; n++) {
|
for (n = 0; n < nent; n++) {
|
||||||
SnapEntry sn = map[n];
|
SnapEntry sn = map[n];
|
||||||
IRRef ref = snap_ref(sn);
|
IRRef ref = snap_ref(sn);
|
||||||
@@ -960,7 +974,7 @@ static void asm_snap_alloc(ASMState *as)
|
|||||||
if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) {
|
if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) {
|
||||||
lj_assertA(irt_type(IR(ref+1)->t) == IRT_SOFTFP,
|
lj_assertA(irt_type(IR(ref+1)->t) == IRT_SOFTFP,
|
||||||
"snap %d[%d] points to bad SOFTFP IR %04d",
|
"snap %d[%d] points to bad SOFTFP IR %04d",
|
||||||
as->snapno, n, ref - REF_BIAS);
|
snapno, n, ref - REF_BIAS);
|
||||||
asm_snap_alloc1(as, ref+1);
|
asm_snap_alloc1(as, ref+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -976,35 +990,26 @@ static void asm_snap_alloc(ASMState *as)
|
|||||||
*/
|
*/
|
||||||
static int asm_snap_checkrename(ASMState *as, IRRef ren)
|
static int asm_snap_checkrename(ASMState *as, IRRef ren)
|
||||||
{
|
{
|
||||||
SnapShot *snap = &as->T->snap[as->snapno];
|
if (bloomtest(as->snapfilt1, ren) &&
|
||||||
SnapEntry *map = &as->T->snapmap[snap->mapofs];
|
bloomtest(as->snapfilt2, hashrot(ren, ren + HASH_BIAS))) {
|
||||||
MSize n, nent = snap->nent;
|
IRIns *ir = IR(ren);
|
||||||
for (n = 0; n < nent; n++) {
|
ra_spill(as, ir); /* Register renamed, so force a spill slot. */
|
||||||
SnapEntry sn = map[n];
|
RA_DBGX((as, "snaprensp $f $s", ren, ir->s));
|
||||||
IRRef ref = snap_ref(sn);
|
return 1; /* Found. */
|
||||||
if (ref == ren || (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM) && ++ref == ren)) {
|
|
||||||
IRIns *ir = IR(ref);
|
|
||||||
ra_spill(as, ir); /* Register renamed, so force a spill slot. */
|
|
||||||
RA_DBGX((as, "snaprensp $f $s", ref, ir->s));
|
|
||||||
return 1; /* Found. */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0; /* Not found. */
|
return 0; /* Not found. */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare snapshot for next guard instruction. */
|
/* Prepare snapshot for next guard or throwing instruction. */
|
||||||
static void asm_snap_prep(ASMState *as)
|
static void asm_snap_prep(ASMState *as)
|
||||||
{
|
{
|
||||||
if (as->curins < as->snapref) {
|
if (as->snapalloc) {
|
||||||
do {
|
/* Alloc on first invocation for each snapshot. */
|
||||||
if (as->snapno == 0) return; /* Called by sunk stores before snap #0. */
|
as->snapalloc = 0;
|
||||||
as->snapno--;
|
asm_snap_alloc(as, as->snapno);
|
||||||
as->snapref = as->T->snap[as->snapno].ref;
|
|
||||||
} while (as->curins < as->snapref);
|
|
||||||
asm_snap_alloc(as);
|
|
||||||
as->snaprename = as->T->nins;
|
as->snaprename = as->T->nins;
|
||||||
} else {
|
} else {
|
||||||
/* Process any renames above the highwater mark. */
|
/* Check any renames above the highwater mark. */
|
||||||
for (; as->snaprename < as->T->nins; as->snaprename++) {
|
for (; as->snaprename < as->T->nins; as->snaprename++) {
|
||||||
IRIns *ir = &as->T->ir[as->snaprename];
|
IRIns *ir = &as->T->ir[as->snaprename];
|
||||||
if (asm_snap_checkrename(as, ir->op1))
|
if (asm_snap_checkrename(as, ir->op1))
|
||||||
@@ -1013,6 +1018,35 @@ static void asm_snap_prep(ASMState *as)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Move to previous snapshot when we cross the current snapshot ref. */
|
||||||
|
static void asm_snap_prev(ASMState *as)
|
||||||
|
{
|
||||||
|
if (as->curins < as->snapref) {
|
||||||
|
uintptr_t ofs = (uintptr_t)(as->mctoporig - as->mcp);
|
||||||
|
if (ofs >= 0x10000) lj_trace_err(as->J, LJ_TRERR_MCODEOV);
|
||||||
|
do {
|
||||||
|
if (as->snapno == 0) return;
|
||||||
|
as->snapno--;
|
||||||
|
as->snapref = as->T->snap[as->snapno].ref;
|
||||||
|
as->T->snap[as->snapno].mcofs = (uint16_t)ofs; /* Remember mcode ofs. */
|
||||||
|
} while (as->curins < as->snapref); /* May have no ins inbetween. */
|
||||||
|
as->snapalloc = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fixup snapshot mcode offsetst. */
|
||||||
|
static void asm_snap_fixup_mcofs(ASMState *as)
|
||||||
|
{
|
||||||
|
uint32_t sz = (uint32_t)(as->mctoporig - as->mcp);
|
||||||
|
SnapShot *snap = as->T->snap;
|
||||||
|
SnapNo i;
|
||||||
|
for (i = as->T->nsnap-1; i > 0; i--) {
|
||||||
|
/* Compute offset from mcode start and store in correct snapshot. */
|
||||||
|
snap[i].mcofs = (uint16_t)(sz - snap[i-1].mcofs);
|
||||||
|
}
|
||||||
|
snap[0].mcofs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* -- Miscellaneous helpers ----------------------------------------------- */
|
/* -- Miscellaneous helpers ----------------------------------------------- */
|
||||||
|
|
||||||
/* Calculate stack adjustment. */
|
/* Calculate stack adjustment. */
|
||||||
@@ -1057,6 +1091,7 @@ static void asm_snew(ASMState *as, IRIns *ir)
|
|||||||
{
|
{
|
||||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_new];
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_new];
|
||||||
IRRef args[3];
|
IRRef args[3];
|
||||||
|
asm_snap_prep(as);
|
||||||
args[0] = ASMREF_L; /* lua_State *L */
|
args[0] = ASMREF_L; /* lua_State *L */
|
||||||
args[1] = ir->op1; /* const char *str */
|
args[1] = ir->op1; /* const char *str */
|
||||||
args[2] = ir->op2; /* size_t len */
|
args[2] = ir->op2; /* size_t len */
|
||||||
@@ -1069,6 +1104,7 @@ static void asm_tnew(ASMState *as, IRIns *ir)
|
|||||||
{
|
{
|
||||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_new1];
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_new1];
|
||||||
IRRef args[2];
|
IRRef args[2];
|
||||||
|
asm_snap_prep(as);
|
||||||
args[0] = ASMREF_L; /* lua_State *L */
|
args[0] = ASMREF_L; /* lua_State *L */
|
||||||
args[1] = ASMREF_TMP1; /* uint32_t ahsize */
|
args[1] = ASMREF_TMP1; /* uint32_t ahsize */
|
||||||
as->gcsteps++;
|
as->gcsteps++;
|
||||||
@@ -1081,6 +1117,7 @@ static void asm_tdup(ASMState *as, IRIns *ir)
|
|||||||
{
|
{
|
||||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_dup];
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_dup];
|
||||||
IRRef args[2];
|
IRRef args[2];
|
||||||
|
asm_snap_prep(as);
|
||||||
args[0] = ASMREF_L; /* lua_State *L */
|
args[0] = ASMREF_L; /* lua_State *L */
|
||||||
args[1] = ir->op1; /* const GCtab *kt */
|
args[1] = ir->op1; /* const GCtab *kt */
|
||||||
as->gcsteps++;
|
as->gcsteps++;
|
||||||
@@ -1106,28 +1143,43 @@ static void asm_gcstep(ASMState *as, IRIns *ir)
|
|||||||
|
|
||||||
/* -- Buffer operations --------------------------------------------------- */
|
/* -- Buffer operations --------------------------------------------------- */
|
||||||
|
|
||||||
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref);
|
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode);
|
||||||
|
#if LJ_HASBUFFER
|
||||||
|
static void asm_bufhdr_write(ASMState *as, Reg sb);
|
||||||
|
#endif
|
||||||
|
|
||||||
static void asm_bufhdr(ASMState *as, IRIns *ir)
|
static void asm_bufhdr(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
Reg sb = ra_dest(as, ir, RSET_GPR);
|
Reg sb = ra_dest(as, ir, RSET_GPR);
|
||||||
if ((ir->op2 & IRBUFHDR_APPEND)) {
|
switch (ir->op2) {
|
||||||
|
case IRBUFHDR_RESET: {
|
||||||
|
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
|
||||||
|
IRIns irbp;
|
||||||
|
irbp.ot = IRT(0, IRT_PTR); /* Buffer data pointer type. */
|
||||||
|
emit_storeofs(as, &irbp, tmp, sb, offsetof(SBuf, w));
|
||||||
|
emit_loadofs(as, &irbp, tmp, sb, offsetof(SBuf, b));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IRBUFHDR_APPEND: {
|
||||||
/* Rematerialize const buffer pointer instead of likely spill. */
|
/* Rematerialize const buffer pointer instead of likely spill. */
|
||||||
IRIns *irp = IR(ir->op1);
|
IRIns *irp = IR(ir->op1);
|
||||||
if (!(ra_hasreg(irp->r) || irp == ir-1 ||
|
if (!(ra_hasreg(irp->r) || irp == ir-1 ||
|
||||||
(irp == ir-2 && !ra_used(ir-1)))) {
|
(irp == ir-2 && !ra_used(ir-1)))) {
|
||||||
while (!(irp->o == IR_BUFHDR && !(irp->op2 & IRBUFHDR_APPEND)))
|
while (!(irp->o == IR_BUFHDR && irp->op2 == IRBUFHDR_RESET))
|
||||||
irp = IR(irp->op1);
|
irp = IR(irp->op1);
|
||||||
if (irref_isk(irp->op1)) {
|
if (irref_isk(irp->op1)) {
|
||||||
ra_weak(as, ra_allocref(as, ir->op1, RSET_GPR));
|
ra_weak(as, ra_allocref(as, ir->op1, RSET_GPR));
|
||||||
ir = irp;
|
ir = irp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
|
}
|
||||||
/* Passing ir isn't strictly correct, but it's an IRT_PGC, too. */
|
#if LJ_HASBUFFER
|
||||||
emit_storeofs(as, ir, tmp, sb, offsetof(SBuf, p));
|
case IRBUFHDR_WRITE:
|
||||||
emit_loadofs(as, ir, tmp, sb, offsetof(SBuf, b));
|
asm_bufhdr_write(as, sb);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default: lj_assertA(0, "bad BUFHDR op2 %d", ir->op2); break;
|
||||||
}
|
}
|
||||||
#if LJ_TARGET_X86ORX64
|
#if LJ_TARGET_X86ORX64
|
||||||
ra_left(as, sb, ir->op1);
|
ra_left(as, sb, ir->op1);
|
||||||
@@ -1179,7 +1231,7 @@ static void asm_bufput(ASMState *as, IRIns *ir)
|
|||||||
if (args[1] == ASMREF_TMP1) {
|
if (args[1] == ASMREF_TMP1) {
|
||||||
Reg tmp = ra_releasetmp(as, ASMREF_TMP1);
|
Reg tmp = ra_releasetmp(as, ASMREF_TMP1);
|
||||||
if (kchar == -129)
|
if (kchar == -129)
|
||||||
asm_tvptr(as, tmp, irs->op1);
|
asm_tvptr(as, tmp, irs->op1, IRTMPREF_IN1);
|
||||||
else
|
else
|
||||||
ra_allockreg(as, kchar, tmp);
|
ra_allockreg(as, kchar, tmp);
|
||||||
}
|
}
|
||||||
@@ -1201,6 +1253,7 @@ static void asm_tostr(ASMState *as, IRIns *ir)
|
|||||||
{
|
{
|
||||||
const CCallInfo *ci;
|
const CCallInfo *ci;
|
||||||
IRRef args[2];
|
IRRef args[2];
|
||||||
|
asm_snap_prep(as);
|
||||||
args[0] = ASMREF_L;
|
args[0] = ASMREF_L;
|
||||||
as->gcsteps++;
|
as->gcsteps++;
|
||||||
if (ir->op2 == IRTOSTR_NUM) {
|
if (ir->op2 == IRTOSTR_NUM) {
|
||||||
@@ -1216,7 +1269,7 @@ static void asm_tostr(ASMState *as, IRIns *ir)
|
|||||||
asm_setupresult(as, ir, ci); /* GCstr * */
|
asm_setupresult(as, ir, ci); /* GCstr * */
|
||||||
asm_gencall(as, ci, args);
|
asm_gencall(as, ci, args);
|
||||||
if (ir->op2 == IRTOSTR_NUM)
|
if (ir->op2 == IRTOSTR_NUM)
|
||||||
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1);
|
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1, IRTMPREF_IN1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86
|
#if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86
|
||||||
@@ -1257,12 +1310,19 @@ static void asm_newref(ASMState *as, IRIns *ir)
|
|||||||
IRRef args[3];
|
IRRef args[3];
|
||||||
if (ir->r == RID_SINK)
|
if (ir->r == RID_SINK)
|
||||||
return;
|
return;
|
||||||
|
asm_snap_prep(as);
|
||||||
args[0] = ASMREF_L; /* lua_State *L */
|
args[0] = ASMREF_L; /* lua_State *L */
|
||||||
args[1] = ir->op1; /* GCtab *t */
|
args[1] = ir->op1; /* GCtab *t */
|
||||||
args[2] = ASMREF_TMP1; /* cTValue *key */
|
args[2] = ASMREF_TMP1; /* cTValue *key */
|
||||||
asm_setupresult(as, ir, ci); /* TValue * */
|
asm_setupresult(as, ir, ci); /* TValue * */
|
||||||
asm_gencall(as, ci, args);
|
asm_gencall(as, ci, args);
|
||||||
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2);
|
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2, IRTMPREF_IN1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void asm_tmpref(ASMState *as, IRIns *ir)
|
||||||
|
{
|
||||||
|
Reg r = ra_dest(as, ir, RSET_GPR);
|
||||||
|
asm_tvptr(as, r, ir->op1, ir->op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_lref(ASMState *as, IRIns *ir)
|
static void asm_lref(ASMState *as, IRIns *ir)
|
||||||
@@ -1744,6 +1804,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
|||||||
case IR_NEWREF: asm_newref(as, ir); break;
|
case IR_NEWREF: asm_newref(as, ir); break;
|
||||||
case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;
|
case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;
|
||||||
case IR_FREF: asm_fref(as, ir); break;
|
case IR_FREF: asm_fref(as, ir); break;
|
||||||
|
case IR_TMPREF: asm_tmpref(as, ir); break;
|
||||||
case IR_STRREF: asm_strref(as, ir); break;
|
case IR_STRREF: asm_strref(as, ir); break;
|
||||||
case IR_LREF: asm_lref(as, ir); break;
|
case IR_LREF: asm_lref(as, ir); break;
|
||||||
|
|
||||||
@@ -1838,8 +1899,7 @@ static void asm_head_side(ASMState *as)
|
|||||||
|
|
||||||
if (as->snapno && as->topslot > as->parent->topslot) {
|
if (as->snapno && as->topslot > as->parent->topslot) {
|
||||||
/* Force snap #0 alloc to prevent register overwrite in stack check. */
|
/* Force snap #0 alloc to prevent register overwrite in stack check. */
|
||||||
as->snapno = 0;
|
asm_snap_alloc(as, 0);
|
||||||
asm_snap_alloc(as);
|
|
||||||
}
|
}
|
||||||
allow = asm_head_side_base(as, irp, allow);
|
allow = asm_head_side_base(as, irp, allow);
|
||||||
|
|
||||||
@@ -2078,6 +2138,9 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ra_setup(as);
|
ra_setup(as);
|
||||||
|
#if LJ_TARGET_ARM64
|
||||||
|
ra_setkref(as, RID_GL, (intptr_t)J2G(as->J));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Clear reg/sp for constants. */
|
/* Clear reg/sp for constants. */
|
||||||
for (ir = IR(T->nk), lastir = IR(REF_BASE); ir < lastir; ir++) {
|
for (ir = IR(T->nk), lastir = IR(REF_BASE); ir < lastir; ir++) {
|
||||||
@@ -2100,6 +2163,7 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
as->snaprename = nins;
|
as->snaprename = nins;
|
||||||
as->snapref = nins;
|
as->snapref = nins;
|
||||||
as->snapno = T->nsnap;
|
as->snapno = T->nsnap;
|
||||||
|
as->snapalloc = 0;
|
||||||
|
|
||||||
as->stopins = REF_BASE;
|
as->stopins = REF_BASE;
|
||||||
as->orignins = nins;
|
as->orignins = nins;
|
||||||
@@ -2148,6 +2212,10 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
ir->prev = (uint16_t)REGSP_HINT((rload & 15));
|
ir->prev = (uint16_t)REGSP_HINT((rload & 15));
|
||||||
rload = lj_ror(rload, 4);
|
rload = lj_ror(rload, 4);
|
||||||
continue;
|
continue;
|
||||||
|
case IR_TMPREF:
|
||||||
|
if ((ir->op2 & IRTMPREF_OUT2) && as->evenspill < 4)
|
||||||
|
as->evenspill = 4; /* TMPREF OUT2 needs two TValues on the stack. */
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case IR_CALLXS: {
|
case IR_CALLXS: {
|
||||||
CCallInfo ci;
|
CCallInfo ci;
|
||||||
@@ -2157,7 +2225,17 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
as->modset |= RSET_SCRATCH;
|
as->modset |= RSET_SCRATCH;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case IR_CALLN: case IR_CALLA: case IR_CALLL: case IR_CALLS: {
|
case IR_CALLL:
|
||||||
|
/* lj_vm_next needs two TValues on the stack. */
|
||||||
|
#if LJ_TARGET_X64 && LJ_ABI_WIN
|
||||||
|
if (ir->op2 == IRCALL_lj_vm_next && as->evenspill < SPS_FIRST + 4)
|
||||||
|
as->evenspill = SPS_FIRST + 4;
|
||||||
|
#else
|
||||||
|
if (SPS_FIRST < 4 && ir->op2 == IRCALL_lj_vm_next && as->evenspill < 4)
|
||||||
|
as->evenspill = 4;
|
||||||
|
#endif
|
||||||
|
/* fallthrough */
|
||||||
|
case IR_CALLN: case IR_CALLA: case IR_CALLS: {
|
||||||
const CCallInfo *ci = &lj_ir_callinfo[ir->op2];
|
const CCallInfo *ci = &lj_ir_callinfo[ir->op2];
|
||||||
ir->prev = asm_setup_call_slots(as, ir, ci);
|
ir->prev = asm_setup_call_slots(as, ir, ci);
|
||||||
if (inloop)
|
if (inloop)
|
||||||
@@ -2165,7 +2243,6 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
(RSET_SCRATCH & ~RSET_FPR) : RSET_SCRATCH;
|
(RSET_SCRATCH & ~RSET_FPR) : RSET_SCRATCH;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
|
|
||||||
case IR_HIOP:
|
case IR_HIOP:
|
||||||
switch ((ir-1)->o) {
|
switch ((ir-1)->o) {
|
||||||
#if LJ_SOFTFP && LJ_TARGET_ARM
|
#if LJ_SOFTFP && LJ_TARGET_ARM
|
||||||
@@ -2176,7 +2253,7 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if !LJ_SOFTFP && LJ_NEED_FP64
|
#if !LJ_SOFTFP && LJ_NEED_FP64 && LJ_32 && LJ_HASFFI
|
||||||
case IR_CONV:
|
case IR_CONV:
|
||||||
if (irt_isfp((ir-1)->t)) {
|
if (irt_isfp((ir-1)->t)) {
|
||||||
ir->prev = REGSP_HINT(RID_FPRET);
|
ir->prev = REGSP_HINT(RID_FPRET);
|
||||||
@@ -2184,7 +2261,7 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case IR_CALLN: case IR_CALLXS:
|
case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
case IR_MIN: case IR_MAX:
|
case IR_MIN: case IR_MAX:
|
||||||
#endif
|
#endif
|
||||||
@@ -2195,7 +2272,6 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
case IR_MIN: case IR_MAX:
|
case IR_MIN: case IR_MAX:
|
||||||
if ((ir+1)->o != IR_HIOP) break;
|
if ((ir+1)->o != IR_HIOP) break;
|
||||||
@@ -2250,13 +2326,23 @@ static void asm_setup_regsp(ASMState *as)
|
|||||||
}
|
}
|
||||||
/* fallthrough */ /* for integer POW */
|
/* fallthrough */ /* for integer POW */
|
||||||
case IR_DIV: case IR_MOD:
|
case IR_DIV: case IR_MOD:
|
||||||
if (!irt_isnum(ir->t)) {
|
if ((LJ_64 && LJ_SOFTFP) || !irt_isnum(ir->t)) {
|
||||||
ir->prev = REGSP_HINT(RID_RET);
|
ir->prev = REGSP_HINT(RID_RET);
|
||||||
if (inloop)
|
if (inloop)
|
||||||
as->modset |= (RSET_SCRATCH & RSET_GPR);
|
as->modset |= (RSET_SCRATCH & RSET_GPR);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#if LJ_64 && LJ_SOFTFP
|
||||||
|
case IR_ADD: case IR_SUB: case IR_MUL:
|
||||||
|
if (irt_isnum(ir->t)) {
|
||||||
|
ir->prev = REGSP_HINT(RID_RET);
|
||||||
|
if (inloop)
|
||||||
|
as->modset |= (RSET_SCRATCH & RSET_GPR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
case IR_FPMATH:
|
case IR_FPMATH:
|
||||||
#if LJ_TARGET_X86ORX64
|
#if LJ_TARGET_X86ORX64
|
||||||
if (ir->op2 <= IRFPM_TRUNC) {
|
if (ir->op2 <= IRFPM_TRUNC) {
|
||||||
@@ -2327,7 +2413,6 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||||||
{
|
{
|
||||||
ASMState as_;
|
ASMState as_;
|
||||||
ASMState *as = &as_;
|
ASMState *as = &as_;
|
||||||
MCode *origtop;
|
|
||||||
|
|
||||||
/* Remove nops/renames left over from ASM restart due to LJ_TRERR_MCODELM. */
|
/* Remove nops/renames left over from ASM restart due to LJ_TRERR_MCODELM. */
|
||||||
{
|
{
|
||||||
@@ -2355,7 +2440,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||||||
as->parent = J->parent ? traceref(J, J->parent) : NULL;
|
as->parent = J->parent ? traceref(J, J->parent) : NULL;
|
||||||
|
|
||||||
/* Reserve MCode memory. */
|
/* Reserve MCode memory. */
|
||||||
as->mctop = origtop = lj_mcode_reserve(J, &as->mcbot);
|
as->mctop = as->mctoporig = lj_mcode_reserve(J, &as->mcbot);
|
||||||
as->mcp = as->mctop;
|
as->mcp = as->mctop;
|
||||||
as->mclim = as->mcbot + MCLIM_REDZONE;
|
as->mclim = as->mcbot + MCLIM_REDZONE;
|
||||||
asm_setup_target(as);
|
asm_setup_target(as);
|
||||||
@@ -2417,6 +2502,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||||||
lj_assertA(!(LJ_32 && irt_isint64(ir->t)),
|
lj_assertA(!(LJ_32 && irt_isint64(ir->t)),
|
||||||
"IR %04d has unsplit 64 bit type",
|
"IR %04d has unsplit 64 bit type",
|
||||||
(int)(ir - as->ir) - REF_BIAS);
|
(int)(ir - as->ir) - REF_BIAS);
|
||||||
|
asm_snap_prev(as);
|
||||||
if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE))
|
if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE))
|
||||||
continue; /* Dead-code elimination can be soooo easy. */
|
continue; /* Dead-code elimination can be soooo easy. */
|
||||||
if (irt_isguard(ir->t))
|
if (irt_isguard(ir->t))
|
||||||
@@ -2450,6 +2536,9 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||||||
memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins,
|
memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins,
|
||||||
(T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */
|
(T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */
|
||||||
T->nins = J->curfinal->nins;
|
T->nins = J->curfinal->nins;
|
||||||
|
/* Fill mcofs of any unprocessed snapshots. */
|
||||||
|
as->curins = REF_FIRST;
|
||||||
|
asm_snap_prev(as);
|
||||||
break; /* Done. */
|
break; /* Done. */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2468,13 +2557,16 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||||||
/* Set trace entry point before fixing up tail to allow link to self. */
|
/* Set trace entry point before fixing up tail to allow link to self. */
|
||||||
T->mcode = as->mcp;
|
T->mcode = as->mcp;
|
||||||
T->mcloop = as->mcloop ? (MSize)((char *)as->mcloop - (char *)as->mcp) : 0;
|
T->mcloop = as->mcloop ? (MSize)((char *)as->mcloop - (char *)as->mcp) : 0;
|
||||||
if (!as->loopref)
|
if (as->loopref)
|
||||||
|
asm_loop_tail_fixup(as);
|
||||||
|
else
|
||||||
asm_tail_fixup(as, T->link); /* Note: this may change as->mctop! */
|
asm_tail_fixup(as, T->link); /* Note: this may change as->mctop! */
|
||||||
T->szmcode = (MSize)((char *)as->mctop - (char *)as->mcp);
|
T->szmcode = (MSize)((char *)as->mctop - (char *)as->mcp);
|
||||||
|
asm_snap_fixup_mcofs(as);
|
||||||
#if LJ_TARGET_MCODE_FIXUP
|
#if LJ_TARGET_MCODE_FIXUP
|
||||||
asm_mcode_fixup(T->mcode, T->szmcode);
|
asm_mcode_fixup(T->mcode, T->szmcode);
|
||||||
#endif
|
#endif
|
||||||
lj_mcode_sync(T->mcode, origtop);
|
lj_mcode_sync(T->mcode, as->mctoporig);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef IR
|
#undef IR
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** IR assembler (SSA IR -> machine code).
|
** IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_ASM_H
|
#ifndef _LJ_ASM_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** ARM IR assembler (SSA IR -> machine code).
|
** ARM IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* -- Register allocator extensions --------------------------------------- */
|
/* -- Register allocator extensions --------------------------------------- */
|
||||||
@@ -185,6 +185,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow,
|
|||||||
*ofsp = (ofs & 255); /* Mask out less bits to allow LDRD. */
|
*ofsp = (ofs & 255); /* Mask out less bits to allow LDRD. */
|
||||||
return ra_allock(as, (ofs & ~255), allow);
|
return ra_allock(as, (ofs & ~255), allow);
|
||||||
}
|
}
|
||||||
|
} else if (ir->o == IR_TMPREF) {
|
||||||
|
*ofsp = 0;
|
||||||
|
return RID_SP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ofsp = 0;
|
*ofsp = 0;
|
||||||
@@ -498,6 +501,30 @@ static void asm_retf(ASMState *as, IRIns *ir)
|
|||||||
emit_lso(as, ARMI_LDR, RID_TMP, base, -4);
|
emit_lso(as, ARMI_LDR, RID_TMP, base, -4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -- Buffer operations --------------------------------------------------- */
|
||||||
|
|
||||||
|
#if LJ_HASBUFFER
|
||||||
|
static void asm_bufhdr_write(ASMState *as, Reg sb)
|
||||||
|
{
|
||||||
|
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
|
||||||
|
IRIns irgc;
|
||||||
|
int32_t addr = i32ptr((void *)&J2G(as->J)->cur_L);
|
||||||
|
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
|
||||||
|
emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L));
|
||||||
|
if ((as->flags & JIT_F_ARMV6T2)) {
|
||||||
|
emit_dnm(as, ARMI_BFI, RID_TMP, lj_fls(SBUF_MASK_FLAG), tmp);
|
||||||
|
} else {
|
||||||
|
emit_dnm(as, ARMI_ORR, RID_TMP, RID_TMP, tmp);
|
||||||
|
emit_dn(as, ARMI_AND|ARMI_K12|SBUF_MASK_FLAG, tmp, tmp);
|
||||||
|
}
|
||||||
|
emit_lso(as, ARMI_LDR, RID_TMP,
|
||||||
|
ra_allock(as, (addr & ~4095),
|
||||||
|
rset_exclude(rset_exclude(RSET_GPR, sb), tmp)),
|
||||||
|
(addr & 4095));
|
||||||
|
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -- Type conversions ---------------------------------------------------- */
|
/* -- Type conversions ---------------------------------------------------- */
|
||||||
|
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
@@ -666,35 +693,55 @@ static void asm_strto(ASMState *as, IRIns *ir)
|
|||||||
/* -- Memory references --------------------------------------------------- */
|
/* -- Memory references --------------------------------------------------- */
|
||||||
|
|
||||||
/* Get pointer to TValue. */
|
/* Get pointer to TValue. */
|
||||||
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
|
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
|
||||||
{
|
{
|
||||||
IRIns *ir = IR(ref);
|
if ((mode & IRTMPREF_IN1)) {
|
||||||
if (irt_isnum(ir->t)) {
|
IRIns *ir = IR(ref);
|
||||||
if (irref_isk(ref)) {
|
if (irt_isnum(ir->t)) {
|
||||||
/* Use the number constant itself as a TValue. */
|
if ((mode & IRTMPREF_OUT1)) {
|
||||||
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
|
|
||||||
} else {
|
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
lj_assertA(0, "unsplit FP op");
|
lj_assertA(irref_isk(ref), "unsplit FP op");
|
||||||
|
emit_dm(as, ARMI_MOV, dest, RID_SP);
|
||||||
|
emit_lso(as, ARMI_STR,
|
||||||
|
ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
|
||||||
|
RID_SP, 0);
|
||||||
|
emit_lso(as, ARMI_STR,
|
||||||
|
ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
|
||||||
|
RID_SP, 4);
|
||||||
#else
|
#else
|
||||||
/* Otherwise force a spill and use the spill slot. */
|
Reg src = ra_alloc1(as, ref, RSET_FPR);
|
||||||
emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
|
emit_dm(as, ARMI_MOV, dest, RID_SP);
|
||||||
|
emit_vlso(as, ARMI_VSTR_D, src, RID_SP, 0);
|
||||||
#endif
|
#endif
|
||||||
|
} else if (irref_isk(ref)) {
|
||||||
|
/* Use the number constant itself as a TValue. */
|
||||||
|
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
|
||||||
|
} else {
|
||||||
|
#if LJ_SOFTFP
|
||||||
|
lj_assertA(0, "unsplit FP op");
|
||||||
|
#else
|
||||||
|
/* Otherwise force a spill and use the spill slot. */
|
||||||
|
emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Otherwise use [sp] and [sp+4] to hold the TValue.
|
||||||
|
** This assumes the following call has max. 4 args.
|
||||||
|
*/
|
||||||
|
Reg type;
|
||||||
|
emit_dm(as, ARMI_MOV, dest, RID_SP);
|
||||||
|
if (!irt_ispri(ir->t)) {
|
||||||
|
Reg src = ra_alloc1(as, ref, RSET_GPR);
|
||||||
|
emit_lso(as, ARMI_STR, src, RID_SP, 0);
|
||||||
|
}
|
||||||
|
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
|
||||||
|
type = ra_alloc1(as, ref+1, RSET_GPR);
|
||||||
|
else
|
||||||
|
type = ra_allock(as, irt_toitype(ir->t), RSET_GPR);
|
||||||
|
emit_lso(as, ARMI_STR, type, RID_SP, 4);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise use [sp] and [sp+4] to hold the TValue. */
|
|
||||||
RegSet allow = rset_exclude(RSET_GPR, dest);
|
|
||||||
Reg type;
|
|
||||||
emit_dm(as, ARMI_MOV, dest, RID_SP);
|
emit_dm(as, ARMI_MOV, dest, RID_SP);
|
||||||
if (!irt_ispri(ir->t)) {
|
|
||||||
Reg src = ra_alloc1(as, ref, allow);
|
|
||||||
emit_lso(as, ARMI_STR, src, RID_SP, 0);
|
|
||||||
}
|
|
||||||
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP)
|
|
||||||
type = ra_alloc1(as, ref+1, allow);
|
|
||||||
else
|
|
||||||
type = ra_allock(as, irt_toitype(ir->t), allow);
|
|
||||||
emit_lso(as, ARMI_STR, type, RID_SP, 4);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1086,6 +1133,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
idx = asm_fuseahuref(as, ir->op1, &ofs, allow,
|
idx = asm_fuseahuref(as, ir->op1, &ofs, allow,
|
||||||
(!LJ_SOFTFP && t == IRT_NUM) ? 1024 : 4096);
|
(!LJ_SOFTFP && t == IRT_NUM) ? 1024 : 4096);
|
||||||
|
if (ir->o == IR_VLOAD) ofs += 8 * ir->op2;
|
||||||
if (!hiop || type == RID_NONE) {
|
if (!hiop || type == RID_NONE) {
|
||||||
rset_clear(allow, idx);
|
rset_clear(allow, idx);
|
||||||
if (ofs < 256 && ra_hasreg(dest) && (dest & 1) == 0 &&
|
if (ofs < 256 && ra_hasreg(dest) && (dest & 1) == 0 &&
|
||||||
@@ -1837,15 +1885,15 @@ static void asm_int64comp(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */
|
/* -- Split register ops -------------------------------------------------- */
|
||||||
|
|
||||||
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */
|
/* Hiword op of a split 32/32 bit op. Previous op is the loword op. */
|
||||||
static void asm_hiop(ASMState *as, IRIns *ir)
|
static void asm_hiop(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
#if LJ_HASFFI || LJ_SOFTFP
|
|
||||||
/* HIOP is marked as a store because it needs its own DCE logic. */
|
/* HIOP is marked as a store because it needs its own DCE logic. */
|
||||||
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
|
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
|
||||||
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
|
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
|
||||||
|
#if LJ_HASFFI || LJ_SOFTFP
|
||||||
if ((ir-1)->o <= IR_NE) { /* 64 bit integer or FP comparisons. ORDER IR. */
|
if ((ir-1)->o <= IR_NE) { /* 64 bit integer or FP comparisons. ORDER IR. */
|
||||||
as->curins--; /* Always skip the loword comparison. */
|
as->curins--; /* Always skip the loword comparison. */
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
@@ -1876,6 +1924,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
asm_xstore_(as, ir, 4);
|
asm_xstore_(as, ir, 4);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
|
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
|
||||||
switch ((ir-1)->o) {
|
switch ((ir-1)->o) {
|
||||||
#if LJ_HASFFI
|
#if LJ_HASFFI
|
||||||
@@ -1894,6 +1943,9 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
asm_intneg(as, ir, ARMI_RSC);
|
asm_intneg(as, ir, ARMI_RSC);
|
||||||
asm_intneg(as, ir-1, ARMI_RSB|ARMI_S);
|
asm_intneg(as, ir-1, ARMI_RSB|ARMI_S);
|
||||||
break;
|
break;
|
||||||
|
case IR_CNEWI:
|
||||||
|
/* Nothing to do here. Handled by lo op itself. */
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
|
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
|
||||||
@@ -1901,25 +1953,16 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
if (!uselo)
|
if (!uselo)
|
||||||
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
|
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
|
||||||
break;
|
break;
|
||||||
|
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
|
||||||
|
/* Nothing to do here. Handled by lo op itself. */
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case IR_CALLN:
|
case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
|
||||||
case IR_CALLS:
|
|
||||||
case IR_CALLXS:
|
|
||||||
if (!uselo)
|
if (!uselo)
|
||||||
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
|
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
|
||||||
break;
|
break;
|
||||||
#if LJ_SOFTFP
|
|
||||||
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR:
|
|
||||||
#endif
|
|
||||||
case IR_CNEWI:
|
|
||||||
/* Nothing to do here. Handled by lo op itself. */
|
|
||||||
break;
|
|
||||||
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/* Unused without SOFTFP or FFI. */
|
|
||||||
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Profiling ----------------------------------------------------------- */
|
/* -- Profiling ----------------------------------------------------------- */
|
||||||
@@ -2021,6 +2064,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
} else if ((sn & SNAP_SOFTFPNUM)) {
|
} else if ((sn & SNAP_SOFTFPNUM)) {
|
||||||
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPRODD, RID_BASE));
|
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPRODD, RID_BASE));
|
||||||
#endif
|
#endif
|
||||||
|
} else if ((sn & SNAP_KEYINDEX)) {
|
||||||
|
type = ra_allock(as, (int32_t)LJ_KEYINDEX, odd);
|
||||||
} else {
|
} else {
|
||||||
type = ra_allock(as, (int32_t)irt_toitype(ir->t), odd);
|
type = ra_allock(as, (int32_t)irt_toitype(ir->t), odd);
|
||||||
}
|
}
|
||||||
@@ -2082,6 +2127,12 @@ static void asm_loop_fixup(ASMState *as)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fixup the tail of the loop. */
|
||||||
|
static void asm_loop_tail_fixup(ASMState *as)
|
||||||
|
{
|
||||||
|
UNUSED(as); /* Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
/* -- Head of trace ------------------------------------------------------- */
|
/* -- Head of trace ------------------------------------------------------- */
|
||||||
|
|
||||||
/* Reload L register from g->cur_L. */
|
/* Reload L register from g->cur_L. */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** ARM64 IR assembler (SSA IR -> machine code).
|
** ARM64 IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
**
|
**
|
||||||
** Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
|
** Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
|
||||||
** Sponsored by Cisco Systems, Inc.
|
** Sponsored by Cisco Systems, Inc.
|
||||||
@@ -198,6 +198,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow,
|
|||||||
return RID_GL;
|
return RID_GL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (ir->o == IR_TMPREF) {
|
||||||
|
*ofsp = (int32_t)glofs(as, &J2G(as->J)->tmptv);
|
||||||
|
return RID_GL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ofsp = 0;
|
*ofsp = 0;
|
||||||
@@ -457,8 +460,11 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
||||||
{
|
{
|
||||||
RegSet drop = RSET_SCRATCH;
|
RegSet drop = RSET_SCRATCH;
|
||||||
|
int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
|
||||||
if (ra_hasreg(ir->r))
|
if (ra_hasreg(ir->r))
|
||||||
rset_clear(drop, ir->r); /* Dest reg handled below. */
|
rset_clear(drop, ir->r); /* Dest reg handled below. */
|
||||||
|
if (hiop && ra_hasreg((ir+1)->r))
|
||||||
|
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
|
||||||
ra_evictset(as, drop); /* Evictions must be performed first. */
|
ra_evictset(as, drop); /* Evictions must be performed first. */
|
||||||
if (ra_used(ir)) {
|
if (ra_used(ir)) {
|
||||||
lj_assertA(!irt_ispri(ir->t), "PRI dest");
|
lj_assertA(!irt_ispri(ir->t), "PRI dest");
|
||||||
@@ -470,6 +476,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
|||||||
} else {
|
} else {
|
||||||
ra_destreg(as, ir, RID_FPRET);
|
ra_destreg(as, ir, RID_FPRET);
|
||||||
}
|
}
|
||||||
|
} else if (hiop) {
|
||||||
|
ra_destpair(as, ir);
|
||||||
} else {
|
} else {
|
||||||
ra_destreg(as, ir, RID_RET);
|
ra_destreg(as, ir, RID_RET);
|
||||||
}
|
}
|
||||||
@@ -519,6 +527,21 @@ static void asm_retf(ASMState *as, IRIns *ir)
|
|||||||
emit_lso(as, A64I_LDRx, RID_TMP, base, -8);
|
emit_lso(as, A64I_LDRx, RID_TMP, base, -8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -- Buffer operations --------------------------------------------------- */
|
||||||
|
|
||||||
|
#if LJ_HASBUFFER
|
||||||
|
static void asm_bufhdr_write(ASMState *as, Reg sb)
|
||||||
|
{
|
||||||
|
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
|
||||||
|
IRIns irgc;
|
||||||
|
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
|
||||||
|
emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L));
|
||||||
|
emit_dn(as, A64I_BFMx | A64F_IMMS(lj_fls(SBUF_MASK_FLAG)) | A64F_IMMR(0), RID_TMP, tmp);
|
||||||
|
emit_getgl(as, RID_TMP, cur_L);
|
||||||
|
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -- Type conversions ---------------------------------------------------- */
|
/* -- Type conversions ---------------------------------------------------- */
|
||||||
|
|
||||||
static void asm_tointg(ASMState *as, IRIns *ir, Reg left)
|
static void asm_tointg(ASMState *as, IRIns *ir, Reg left)
|
||||||
@@ -602,7 +625,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
emit_dn(as, A64I_SXTW, dest, left);
|
emit_dn(as, A64I_SXTW, dest, left);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (st64) {
|
if (st64 && !(ir->op2 & IRCONV_NONE)) {
|
||||||
/* This is either a 32 bit reg/reg mov which zeroes the hiword
|
/* This is either a 32 bit reg/reg mov which zeroes the hiword
|
||||||
** or a load of the loword from a 64 bit address.
|
** or a load of the loword from a 64 bit address.
|
||||||
*/
|
*/
|
||||||
@@ -675,22 +698,23 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get pointer to TValue. */
|
/* Get pointer to TValue. */
|
||||||
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
|
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
|
||||||
{
|
{
|
||||||
IRIns *ir = IR(ref);
|
if ((mode & IRTMPREF_IN1)) {
|
||||||
if (irt_isnum(ir->t)) {
|
IRIns *ir = IR(ref);
|
||||||
if (irref_isk(ref)) {
|
if (irt_isnum(ir->t)) {
|
||||||
/* Use the number constant itself as a TValue. */
|
if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) {
|
||||||
ra_allockreg(as, i64ptr(ir_knum(ir)), dest);
|
/* Use the number constant itself as a TValue. */
|
||||||
|
ra_allockreg(as, i64ptr(ir_knum(ir)), dest);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emit_lso(as, A64I_STRd, (ra_alloc1(as, ref, RSET_FPR) & 31), dest, 0);
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise force a spill and use the spill slot. */
|
asm_tvstore64(as, dest, 0, ref);
|
||||||
emit_opk(as, A64I_ADDx, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
/* Otherwise use g->tmptv to hold the TValue. */
|
|
||||||
asm_tvstore64(as, dest, 0, ref);
|
|
||||||
ra_allockreg(as, i64ptr(&J2G(as->J)->tmptv), dest);
|
|
||||||
}
|
}
|
||||||
|
/* g->tmptv holds the TValue(s). */
|
||||||
|
emit_dn(as, A64I_ADDx^emit_isk12(glofs(as, &J2G(as->J)->tmptv)), dest, RID_GL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_aref(ASMState *as, IRIns *ir)
|
static void asm_aref(ASMState *as, IRIns *ir)
|
||||||
@@ -767,7 +791,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
}
|
}
|
||||||
} else if (irt_isaddr(kt)) {
|
} else if (irt_isaddr(kt)) {
|
||||||
if (isk) {
|
if (isk) {
|
||||||
int64_t kk = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64;
|
int64_t kk = ((int64_t)irt_toitype(kt) << 47) | irkey[1].tv.u64;
|
||||||
scr = ra_allock(as, kk, allow);
|
scr = ra_allock(as, kk, allow);
|
||||||
} else {
|
} else {
|
||||||
scr = ra_scratch(as, allow);
|
scr = ra_scratch(as, allow);
|
||||||
@@ -775,7 +799,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
rset_clear(allow, scr);
|
rset_clear(allow, scr);
|
||||||
} else {
|
} else {
|
||||||
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
|
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
|
||||||
type = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow);
|
type = ra_allock(as, ~((int64_t)~irt_toitype(kt) << 47), allow);
|
||||||
scr = ra_scratch(as, rset_clear(allow, type));
|
scr = ra_scratch(as, rset_clear(allow, type));
|
||||||
rset_clear(allow, scr);
|
rset_clear(allow, scr);
|
||||||
}
|
}
|
||||||
@@ -824,7 +848,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key.u64));
|
emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key.u64));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
emit_nm(as, A64I_CMPw, scr, type);
|
emit_nm(as, A64I_CMPx, scr, type);
|
||||||
emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key));
|
emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1059,6 +1083,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
type = ra_scratch(as, rset_clear(gpr, tmp));
|
type = ra_scratch(as, rset_clear(gpr, tmp));
|
||||||
idx = asm_fuseahuref(as, ir->op1, &ofs, rset_clear(gpr, type), A64I_LDRx);
|
idx = asm_fuseahuref(as, ir->op1, &ofs, rset_clear(gpr, type), A64I_LDRx);
|
||||||
|
if (ir->o == IR_VLOAD) ofs += 8 * ir->op2;
|
||||||
/* Always do the type check, even if the load result is unused. */
|
/* Always do the type check, even if the load result is unused. */
|
||||||
asm_guardcc(as, irt_isnum(ir->t) ? CC_LS : CC_NE);
|
asm_guardcc(as, irt_isnum(ir->t) ? CC_LS : CC_NE);
|
||||||
if (irt_type(ir->t) >= IRT_NUM) {
|
if (irt_type(ir->t) >= IRT_NUM) {
|
||||||
@@ -1261,17 +1286,13 @@ static void asm_tbar(ASMState *as, IRIns *ir)
|
|||||||
{
|
{
|
||||||
Reg tab = ra_alloc1(as, ir->op1, RSET_GPR);
|
Reg tab = ra_alloc1(as, ir->op1, RSET_GPR);
|
||||||
Reg link = ra_scratch(as, rset_exclude(RSET_GPR, tab));
|
Reg link = ra_scratch(as, rset_exclude(RSET_GPR, tab));
|
||||||
Reg gr = ra_allock(as, i64ptr(J2G(as->J)),
|
|
||||||
rset_exclude(rset_exclude(RSET_GPR, tab), link));
|
|
||||||
Reg mark = RID_TMP;
|
Reg mark = RID_TMP;
|
||||||
MCLabel l_end = emit_label(as);
|
MCLabel l_end = emit_label(as);
|
||||||
emit_lso(as, A64I_STRx, link, tab, (int32_t)offsetof(GCtab, gclist));
|
emit_lso(as, A64I_STRx, link, tab, (int32_t)offsetof(GCtab, gclist));
|
||||||
emit_lso(as, A64I_STRB, mark, tab, (int32_t)offsetof(GCtab, marked));
|
emit_lso(as, A64I_STRB, mark, tab, (int32_t)offsetof(GCtab, marked));
|
||||||
emit_lso(as, A64I_STRx, tab, gr,
|
emit_setgl(as, tab, gc.grayagain);
|
||||||
(int32_t)offsetof(global_State, gc.grayagain));
|
|
||||||
emit_dn(as, A64I_ANDw^emit_isk13(~LJ_GC_BLACK, 0), mark, mark);
|
emit_dn(as, A64I_ANDw^emit_isk13(~LJ_GC_BLACK, 0), mark, mark);
|
||||||
emit_lso(as, A64I_LDRx, link, gr,
|
emit_getgl(as, link, gc.grayagain);
|
||||||
(int32_t)offsetof(global_State, gc.grayagain));
|
|
||||||
emit_cond_branch(as, CC_EQ, l_end);
|
emit_cond_branch(as, CC_EQ, l_end);
|
||||||
emit_n(as, A64I_TSTw^emit_isk13(LJ_GC_BLACK, 0), mark);
|
emit_n(as, A64I_TSTw^emit_isk13(LJ_GC_BLACK, 0), mark);
|
||||||
emit_lso(as, A64I_LDRB, mark, tab, (int32_t)offsetof(GCtab, marked));
|
emit_lso(as, A64I_LDRB, mark, tab, (int32_t)offsetof(GCtab, marked));
|
||||||
@@ -1291,7 +1312,7 @@ static void asm_obar(ASMState *as, IRIns *ir)
|
|||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
args[1] = ir->op1; /* TValue *tv */
|
args[1] = ir->op1; /* TValue *tv */
|
||||||
asm_gencall(as, ci, args);
|
asm_gencall(as, ci, args);
|
||||||
ra_allockreg(as, i64ptr(J2G(as->J)), ra_releasetmp(as, ASMREF_TMP1) );
|
emit_dm(as, A64I_MOVx, ra_releasetmp(as, ASMREF_TMP1), RID_GL);
|
||||||
obj = IR(ir->op1)->r;
|
obj = IR(ir->op1)->r;
|
||||||
tmp = ra_scratch(as, rset_exclude(allow, obj));
|
tmp = ra_scratch(as, rset_exclude(allow, obj));
|
||||||
emit_cond_branch(as, CC_EQ, l_end);
|
emit_cond_branch(as, CC_EQ, l_end);
|
||||||
@@ -1704,13 +1725,25 @@ static void asm_comp(ASMState *as, IRIns *ir)
|
|||||||
|
|
||||||
#define asm_equal(as, ir) asm_comp(as, ir)
|
#define asm_equal(as, ir) asm_comp(as, ir)
|
||||||
|
|
||||||
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */
|
/* -- Split register ops -------------------------------------------------- */
|
||||||
|
|
||||||
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */
|
/* Hiword op of a split 64/64 bit op. Previous op is the loword op. */
|
||||||
static void asm_hiop(ASMState *as, IRIns *ir)
|
static void asm_hiop(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
UNUSED(as); UNUSED(ir);
|
/* HIOP is marked as a store because it needs its own DCE logic. */
|
||||||
lj_assertA(0, "unexpected HIOP"); /* Unused on 64 bit. */
|
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
|
||||||
|
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
|
||||||
|
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
|
||||||
|
switch ((ir-1)->o) {
|
||||||
|
case IR_CALLN:
|
||||||
|
case IR_CALLL:
|
||||||
|
case IR_CALLS:
|
||||||
|
case IR_CALLXS:
|
||||||
|
if (!uselo)
|
||||||
|
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
|
||||||
|
break;
|
||||||
|
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Profiling ----------------------------------------------------------- */
|
/* -- Profiling ----------------------------------------------------------- */
|
||||||
@@ -1781,7 +1814,14 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
IRIns *ir = IR(ref);
|
IRIns *ir = IR(ref);
|
||||||
if ((sn & SNAP_NORESTORE))
|
if ((sn & SNAP_NORESTORE))
|
||||||
continue;
|
continue;
|
||||||
if (irt_isnum(ir->t)) {
|
if ((sn & SNAP_KEYINDEX)) {
|
||||||
|
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
|
||||||
|
Reg r = irref_isk(ref) ? ra_allock(as, ir->i, allow) :
|
||||||
|
ra_alloc1(as, ref, allow);
|
||||||
|
rset_clear(allow, r);
|
||||||
|
emit_lso(as, A64I_STRw, r, RID_BASE, ofs);
|
||||||
|
emit_lso(as, A64I_STRw, ra_allock(as, LJ_KEYINDEX, allow), RID_BASE, ofs+4);
|
||||||
|
} else if (irt_isnum(ir->t)) {
|
||||||
Reg src = ra_alloc1(as, ref, RSET_FPR);
|
Reg src = ra_alloc1(as, ref, RSET_FPR);
|
||||||
emit_lso(as, A64I_STRd, (src & 31), RID_BASE, ofs);
|
emit_lso(as, A64I_STRd, (src & 31), RID_BASE, ofs);
|
||||||
} else {
|
} else {
|
||||||
@@ -1804,7 +1844,7 @@ static void asm_gc_check(ASMState *as)
|
|||||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_step_jit];
|
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_step_jit];
|
||||||
IRRef args[2];
|
IRRef args[2];
|
||||||
MCLabel l_end;
|
MCLabel l_end;
|
||||||
Reg tmp1, tmp2;
|
Reg tmp2;
|
||||||
ra_evictset(as, RSET_SCRATCH);
|
ra_evictset(as, RSET_SCRATCH);
|
||||||
l_end = emit_label(as);
|
l_end = emit_label(as);
|
||||||
/* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
|
/* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
|
||||||
@@ -1813,17 +1853,14 @@ static void asm_gc_check(ASMState *as)
|
|||||||
args[0] = ASMREF_TMP1; /* global_State *g */
|
args[0] = ASMREF_TMP1; /* global_State *g */
|
||||||
args[1] = ASMREF_TMP2; /* MSize steps */
|
args[1] = ASMREF_TMP2; /* MSize steps */
|
||||||
asm_gencall(as, ci, args);
|
asm_gencall(as, ci, args);
|
||||||
tmp1 = ra_releasetmp(as, ASMREF_TMP1);
|
emit_dm(as, A64I_MOVx, ra_releasetmp(as, ASMREF_TMP1), RID_GL);
|
||||||
tmp2 = ra_releasetmp(as, ASMREF_TMP2);
|
tmp2 = ra_releasetmp(as, ASMREF_TMP2);
|
||||||
emit_loadi(as, tmp2, as->gcsteps);
|
emit_loadi(as, tmp2, as->gcsteps);
|
||||||
/* Jump around GC step if GC total < GC threshold. */
|
/* Jump around GC step if GC total < GC threshold. */
|
||||||
emit_cond_branch(as, CC_LS, l_end);
|
emit_cond_branch(as, CC_LS, l_end);
|
||||||
emit_nm(as, A64I_CMPx, RID_TMP, tmp2);
|
emit_nm(as, A64I_CMPx, RID_TMP, tmp2);
|
||||||
emit_lso(as, A64I_LDRx, tmp2, tmp1,
|
emit_getgl(as, tmp2, gc.threshold);
|
||||||
(int32_t)offsetof(global_State, gc.threshold));
|
emit_getgl(as, RID_TMP, gc.total);
|
||||||
emit_lso(as, A64I_LDRx, RID_TMP, tmp1,
|
|
||||||
(int32_t)offsetof(global_State, gc.total));
|
|
||||||
ra_allockreg(as, i64ptr(J2G(as->J)), tmp1);
|
|
||||||
as->gcsteps = 0;
|
as->gcsteps = 0;
|
||||||
checkmclim(as);
|
checkmclim(as);
|
||||||
}
|
}
|
||||||
@@ -1846,6 +1883,12 @@ static void asm_loop_fixup(ASMState *as)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fixup the tail of the loop. */
|
||||||
|
static void asm_loop_tail_fixup(ASMState *as)
|
||||||
|
{
|
||||||
|
UNUSED(as); /* Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
/* -- Head of trace ------------------------------------------------------- */
|
/* -- Head of trace ------------------------------------------------------- */
|
||||||
|
|
||||||
/* Reload L register from g->cur_L. */
|
/* Reload L register from g->cur_L. */
|
||||||
|
|||||||
+143
-93
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** MIPS IR assembler (SSA IR -> machine code).
|
** MIPS IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* -- Register allocator extensions --------------------------------------- */
|
/* -- Register allocator extensions --------------------------------------- */
|
||||||
@@ -64,19 +64,31 @@ static Reg ra_alloc2(ASMState *as, IRIns *ir, RegSet allow)
|
|||||||
/* Setup spare long-range jump slots per mcarea. */
|
/* Setup spare long-range jump slots per mcarea. */
|
||||||
static void asm_sparejump_setup(ASMState *as)
|
static void asm_sparejump_setup(ASMState *as)
|
||||||
{
|
{
|
||||||
MCode *mxp = as->mcbot;
|
MCode *mxp = as->mctop;
|
||||||
if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == sizeof(MCLink)) {
|
if ((char *)mxp == (char *)as->J->mcarea + as->J->szmcarea) {
|
||||||
|
mxp -= MIPS_SPAREJUMP*2;
|
||||||
lj_assertA(MIPSI_NOP == 0, "bad NOP");
|
lj_assertA(MIPSI_NOP == 0, "bad NOP");
|
||||||
memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode));
|
memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode));
|
||||||
mxp += MIPS_SPAREJUMP*2;
|
as->mctop = mxp;
|
||||||
lj_assertA(mxp < as->mctop, "MIPS_SPAREJUMP too big");
|
|
||||||
lj_mcode_sync(as->mcbot, mxp);
|
|
||||||
lj_mcode_commitbot(as->J, mxp);
|
|
||||||
as->mcbot = mxp;
|
|
||||||
as->mclim = as->mcbot + MCLIM_REDZONE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MCode *asm_sparejump_use(MCode *mcarea, MCode tjump)
|
||||||
|
{
|
||||||
|
MCode *mxp = (MCode *)((char *)mcarea + ((MCLink *)mcarea)->size);
|
||||||
|
int slot = MIPS_SPAREJUMP;
|
||||||
|
while (slot--) {
|
||||||
|
mxp -= 2;
|
||||||
|
if (*mxp == tjump) {
|
||||||
|
return mxp;
|
||||||
|
} else if (*mxp == MIPSI_NOP) {
|
||||||
|
*mxp = tjump;
|
||||||
|
return mxp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup exit stub after the end of each trace. */
|
/* Setup exit stub after the end of each trace. */
|
||||||
static void asm_exitstub_setup(ASMState *as)
|
static void asm_exitstub_setup(ASMState *as)
|
||||||
{
|
{
|
||||||
@@ -181,6 +193,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
|
|||||||
return ra_allock(as, ofs-(int16_t)ofs, allow);
|
return ra_allock(as, ofs-(int16_t)ofs, allow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (ir->o == IR_TMPREF) {
|
||||||
|
*ofsp = (int32_t)(offsetof(global_State, tmptv)-32768);
|
||||||
|
return RID_JGL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ofsp = 0;
|
*ofsp = 0;
|
||||||
@@ -336,19 +351,15 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
||||||
{
|
{
|
||||||
RegSet drop = RSET_SCRATCH;
|
RegSet drop = RSET_SCRATCH;
|
||||||
#if LJ_32
|
|
||||||
int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
|
int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
|
||||||
#endif
|
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
if ((ci->flags & CCI_NOFPRCLOBBER))
|
if ((ci->flags & CCI_NOFPRCLOBBER))
|
||||||
drop &= ~RSET_FPR;
|
drop &= ~RSET_FPR;
|
||||||
#endif
|
#endif
|
||||||
if (ra_hasreg(ir->r))
|
if (ra_hasreg(ir->r))
|
||||||
rset_clear(drop, ir->r); /* Dest reg handled below. */
|
rset_clear(drop, ir->r); /* Dest reg handled below. */
|
||||||
#if LJ_32
|
|
||||||
if (hiop && ra_hasreg((ir+1)->r))
|
if (hiop && ra_hasreg((ir+1)->r))
|
||||||
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
|
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
|
||||||
#endif
|
|
||||||
ra_evictset(as, drop); /* Evictions must be performed first. */
|
ra_evictset(as, drop); /* Evictions must be performed first. */
|
||||||
if (ra_used(ir)) {
|
if (ra_used(ir)) {
|
||||||
lj_assertA(!irt_ispri(ir->t), "PRI dest");
|
lj_assertA(!irt_ispri(ir->t), "PRI dest");
|
||||||
@@ -377,10 +388,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
|||||||
} else {
|
} else {
|
||||||
ra_destreg(as, ir, RID_FPRET);
|
ra_destreg(as, ir, RID_FPRET);
|
||||||
}
|
}
|
||||||
#if LJ_32
|
|
||||||
} else if (hiop) {
|
} else if (hiop) {
|
||||||
ra_destpair(as, ir);
|
ra_destpair(as, ir);
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
ra_destreg(as, ir, RID_RET);
|
ra_destreg(as, ir, RID_RET);
|
||||||
}
|
}
|
||||||
@@ -450,6 +459,27 @@ static void asm_retf(ASMState *as, IRIns *ir)
|
|||||||
emit_tsi(as, MIPSI_AL, RID_TMP, base, -8);
|
emit_tsi(as, MIPSI_AL, RID_TMP, base, -8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -- Buffer operations --------------------------------------------------- */
|
||||||
|
|
||||||
|
#if LJ_HASBUFFER
|
||||||
|
static void asm_bufhdr_write(ASMState *as, Reg sb)
|
||||||
|
{
|
||||||
|
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
|
||||||
|
IRIns irgc;
|
||||||
|
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
|
||||||
|
emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L));
|
||||||
|
if ((as->flags & JIT_F_MIPSXXR2)) {
|
||||||
|
emit_tsml(as, LJ_64 ? MIPSI_DINS : MIPSI_INS, RID_TMP, tmp,
|
||||||
|
lj_fls(SBUF_MASK_FLAG), 0);
|
||||||
|
} else {
|
||||||
|
emit_dst(as, MIPSI_OR, RID_TMP, RID_TMP, tmp);
|
||||||
|
emit_tsi(as, MIPSI_ANDI, tmp, tmp, SBUF_MASK_FLAG);
|
||||||
|
}
|
||||||
|
emit_getgl(as, RID_TMP, cur_L);
|
||||||
|
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -- Type conversions ---------------------------------------------------- */
|
/* -- Type conversions ---------------------------------------------------- */
|
||||||
|
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
@@ -739,7 +769,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (st64) {
|
if (st64 && !(ir->op2 & IRCONV_NONE)) {
|
||||||
/* This is either a 32 bit reg/reg mov which zeroes the hiword
|
/* This is either a 32 bit reg/reg mov which zeroes the hiword
|
||||||
** or a load of the loword from a 64 bit address.
|
** or a load of the loword from a 64 bit address.
|
||||||
*/
|
*/
|
||||||
@@ -827,34 +857,63 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Get pointer to TValue. */
|
/* Get pointer to TValue. */
|
||||||
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
|
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
|
||||||
{
|
{
|
||||||
IRIns *ir = IR(ref);
|
int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768);
|
||||||
if (irt_isnum(ir->t)) {
|
if ((mode & IRTMPREF_IN1)) {
|
||||||
if (irref_isk(ref)) /* Use the number constant itself as a TValue. */
|
IRIns *ir = IR(ref);
|
||||||
ra_allockreg(as, igcptr(ir_knum(ir)), dest);
|
if (irt_isnum(ir->t)) {
|
||||||
else /* Otherwise force a spill and use the spill slot. */
|
if ((mode & IRTMPREF_OUT1)) {
|
||||||
emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir));
|
#if LJ_SOFTFP
|
||||||
} else {
|
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
|
||||||
/* Otherwise use g->tmptv to hold the TValue. */
|
#if LJ_64
|
||||||
#if LJ_32
|
emit_setgl(as, ra_alloc1(as, ref, RSET_GPR), tmptv.u64);
|
||||||
RegSet allow = rset_exclude(RSET_GPR, dest);
|
|
||||||
Reg type;
|
|
||||||
emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768));
|
|
||||||
if (!irt_ispri(ir->t)) {
|
|
||||||
Reg src = ra_alloc1(as, ref, allow);
|
|
||||||
emit_setgl(as, src, tmptv.gcr);
|
|
||||||
}
|
|
||||||
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP)
|
|
||||||
type = ra_alloc1(as, ref+1, allow);
|
|
||||||
else
|
|
||||||
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
|
|
||||||
emit_setgl(as, type, tmptv.it);
|
|
||||||
#else
|
#else
|
||||||
asm_tvstore64(as, dest, 0, ref);
|
lj_assertA(irref_isk(ref), "unsplit FP op");
|
||||||
emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL,
|
emit_setgl(as,
|
||||||
(int32_t)(offsetof(global_State, tmptv)-32768));
|
ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
|
||||||
|
tmptv.u32.lo);
|
||||||
|
emit_setgl(as,
|
||||||
|
ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
|
||||||
|
tmptv.u32.hi);
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
Reg src = ra_alloc1(as, ref, RSET_FPR);
|
||||||
|
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
|
||||||
|
emit_tsi(as, MIPSI_SDC1, (src & 31), RID_JGL, tmpofs);
|
||||||
|
#endif
|
||||||
|
} else if (irref_isk(ref)) {
|
||||||
|
/* Use the number constant itself as a TValue. */
|
||||||
|
ra_allockreg(as, igcptr(ir_knum(ir)), dest);
|
||||||
|
} else {
|
||||||
|
#if LJ_SOFTFP32
|
||||||
|
lj_assertA(0, "unsplit FP op");
|
||||||
|
#else
|
||||||
|
/* Otherwise force a spill and use the spill slot. */
|
||||||
|
emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Otherwise use g->tmptv to hold the TValue. */
|
||||||
|
#if LJ_32
|
||||||
|
Reg type;
|
||||||
|
emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, tmpofs);
|
||||||
|
if (!irt_ispri(ir->t)) {
|
||||||
|
Reg src = ra_alloc1(as, ref, RSET_GPR);
|
||||||
|
emit_setgl(as, src, tmptv.gcr);
|
||||||
|
}
|
||||||
|
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
|
||||||
|
type = ra_alloc1(as, ref+1, RSET_GPR);
|
||||||
|
else
|
||||||
|
type = ra_allock(as, (int32_t)irt_toitype(ir->t), RSET_GPR);
|
||||||
|
emit_setgl(as, type, tmptv.it);
|
||||||
|
#else
|
||||||
|
asm_tvstore64(as, dest, 0, ref);
|
||||||
|
emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, tmpofs);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -909,11 +968,16 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
MCLabel l_end, l_loop, l_next;
|
MCLabel l_end, l_loop, l_next;
|
||||||
|
|
||||||
rset_clear(allow, tab);
|
rset_clear(allow, tab);
|
||||||
#if LJ_SOFTFP32
|
if (!LJ_SOFTFP && irt_isnum(kt)) {
|
||||||
if (!isk) {
|
key = ra_alloc1(as, refkey, RSET_FPR);
|
||||||
key = ra_alloc1(as, refkey, allow);
|
tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
|
||||||
rset_clear(allow, key);
|
} else {
|
||||||
if (irkey[1].o == IR_HIOP) {
|
if (!irt_ispri(kt)) {
|
||||||
|
key = ra_alloc1(as, refkey, allow);
|
||||||
|
rset_clear(allow, key);
|
||||||
|
}
|
||||||
|
#if LJ_32
|
||||||
|
if (LJ_SOFTFP && irkey[1].o == IR_HIOP) {
|
||||||
if (ra_hasreg((irkey+1)->r)) {
|
if (ra_hasreg((irkey+1)->r)) {
|
||||||
type = tmpnum = (irkey+1)->r;
|
type = tmpnum = (irkey+1)->r;
|
||||||
tmp1 = ra_scratch(as, allow);
|
tmp1 = ra_scratch(as, allow);
|
||||||
@@ -924,23 +988,11 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
}
|
}
|
||||||
rset_clear(allow, tmpnum);
|
rset_clear(allow, tmpnum);
|
||||||
} else {
|
} else {
|
||||||
type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow);
|
type = ra_allock(as, (int32_t)irt_toitype(kt), allow);
|
||||||
rset_clear(allow, type);
|
rset_clear(allow, type);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (!LJ_SOFTFP && irt_isnum(kt)) {
|
|
||||||
key = ra_alloc1(as, refkey, RSET_FPR);
|
|
||||||
tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
|
|
||||||
} else if (!irt_ispri(kt)) {
|
|
||||||
key = ra_alloc1(as, refkey, allow);
|
|
||||||
rset_clear(allow, key);
|
|
||||||
#if LJ_32
|
|
||||||
type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow);
|
|
||||||
rset_clear(allow, type);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
tmp2 = ra_scratch(as, allow);
|
tmp2 = ra_scratch(as, allow);
|
||||||
rset_clear(allow, tmp2);
|
rset_clear(allow, tmp2);
|
||||||
#if LJ_64
|
#if LJ_64
|
||||||
@@ -953,10 +1005,10 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
|
|||||||
} else {
|
} else {
|
||||||
int64_t k;
|
int64_t k;
|
||||||
if (isk && irt_isaddr(kt)) {
|
if (isk && irt_isaddr(kt)) {
|
||||||
k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64;
|
k = ((int64_t)irt_toitype(kt) << 47) | irkey[1].tv.u64;
|
||||||
} else {
|
} else {
|
||||||
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
|
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
|
||||||
k = ~((int64_t)~irt_toitype(ir->t) << 47);
|
k = ~((int64_t)~irt_toitype(kt) << 47);
|
||||||
}
|
}
|
||||||
cmp64 = ra_allock(as, k, allow);
|
cmp64 = ra_allock(as, k, allow);
|
||||||
rset_clear(allow, cmp64);
|
rset_clear(allow, cmp64);
|
||||||
@@ -1352,6 +1404,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
|
idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
|
||||||
|
if (ir->o == IR_VLOAD) ofs += 8 * ir->op2;
|
||||||
rset_clear(allow, idx);
|
rset_clear(allow, idx);
|
||||||
if (irt_isnum(t)) {
|
if (irt_isnum(t)) {
|
||||||
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
|
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
|
||||||
@@ -2327,15 +2380,15 @@ static void asm_comp64eq(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */
|
/* -- Split register ops -------------------------------------------------- */
|
||||||
|
|
||||||
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */
|
/* Hiword op of a split 32/32 or 64/64 bit op. Previous op is the loword op. */
|
||||||
static void asm_hiop(ASMState *as, IRIns *ir)
|
static void asm_hiop(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
#if LJ_32 && (LJ_HASFFI || LJ_SOFTFP)
|
|
||||||
/* HIOP is marked as a store because it needs its own DCE logic. */
|
/* HIOP is marked as a store because it needs its own DCE logic. */
|
||||||
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
|
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
|
||||||
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
|
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
|
||||||
|
#if LJ_32 && (LJ_HASFFI || LJ_SOFTFP)
|
||||||
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
|
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
|
||||||
as->curins--; /* Always skip the CONV. */
|
as->curins--; /* Always skip the CONV. */
|
||||||
#if LJ_HASFFI && !LJ_SOFTFP
|
#if LJ_HASFFI && !LJ_SOFTFP
|
||||||
@@ -2382,38 +2435,33 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
|
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
|
||||||
switch ((ir-1)->o) {
|
switch ((ir-1)->o) {
|
||||||
#if LJ_HASFFI
|
#if LJ_32 && LJ_HASFFI
|
||||||
case IR_ADD: as->curins--; asm_add64(as, ir); break;
|
case IR_ADD: as->curins--; asm_add64(as, ir); break;
|
||||||
case IR_SUB: as->curins--; asm_sub64(as, ir); break;
|
case IR_SUB: as->curins--; asm_sub64(as, ir); break;
|
||||||
case IR_NEG: as->curins--; asm_neg64(as, ir); break;
|
case IR_NEG: as->curins--; asm_neg64(as, ir); break;
|
||||||
|
case IR_CNEWI:
|
||||||
|
/* Nothing to do here. Handled by lo op itself. */
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if LJ_SOFTFP
|
#if LJ_32 && LJ_SOFTFP
|
||||||
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
|
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
|
||||||
case IR_STRTO:
|
case IR_STRTO:
|
||||||
if (!uselo)
|
if (!uselo)
|
||||||
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
|
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
|
||||||
break;
|
break;
|
||||||
|
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
|
||||||
|
/* Nothing to do here. Handled by lo op itself. */
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case IR_CALLN:
|
case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
|
||||||
case IR_CALLS:
|
|
||||||
case IR_CALLXS:
|
|
||||||
if (!uselo)
|
if (!uselo)
|
||||||
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
|
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
|
||||||
break;
|
break;
|
||||||
#if LJ_SOFTFP
|
|
||||||
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR:
|
|
||||||
#endif
|
|
||||||
case IR_CNEWI:
|
|
||||||
/* Nothing to do here. Handled by lo op itself. */
|
|
||||||
break;
|
|
||||||
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/* Unused on MIPS64 or without SOFTFP or FFI. */
|
|
||||||
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Profiling ----------------------------------------------------------- */
|
/* -- Profiling ----------------------------------------------------------- */
|
||||||
@@ -2513,6 +2561,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
} else if ((sn & SNAP_SOFTFPNUM)) {
|
} else if ((sn & SNAP_SOFTFPNUM)) {
|
||||||
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE));
|
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE));
|
||||||
#endif
|
#endif
|
||||||
|
} else if ((sn & SNAP_KEYINDEX)) {
|
||||||
|
type = ra_allock(as, (int32_t)LJ_KEYINDEX, allow);
|
||||||
} else {
|
} else {
|
||||||
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
|
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
|
||||||
}
|
}
|
||||||
@@ -2575,6 +2625,12 @@ static void asm_loop_fixup(ASMState *as)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fixup the tail of the loop. */
|
||||||
|
static void asm_loop_tail_fixup(ASMState *as)
|
||||||
|
{
|
||||||
|
if (as->loopinv) as->mctop--;
|
||||||
|
}
|
||||||
|
|
||||||
/* -- Head of trace ------------------------------------------------------- */
|
/* -- Head of trace ------------------------------------------------------- */
|
||||||
|
|
||||||
/* Coalesce BASE register for a root trace. */
|
/* Coalesce BASE register for a root trace. */
|
||||||
@@ -2582,7 +2638,6 @@ static void asm_head_root_base(ASMState *as)
|
|||||||
{
|
{
|
||||||
IRIns *ir = IR(REF_BASE);
|
IRIns *ir = IR(REF_BASE);
|
||||||
Reg r = ir->r;
|
Reg r = ir->r;
|
||||||
if (as->loopinv) as->mctop--;
|
|
||||||
if (ra_hasreg(r)) {
|
if (ra_hasreg(r)) {
|
||||||
ra_free(as, r);
|
ra_free(as, r);
|
||||||
if (rset_test(as->modset, r) || irt_ismarked(ir->t))
|
if (rset_test(as->modset, r) || irt_ismarked(ir->t))
|
||||||
@@ -2597,7 +2652,6 @@ static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
|
|||||||
{
|
{
|
||||||
IRIns *ir = IR(REF_BASE);
|
IRIns *ir = IR(REF_BASE);
|
||||||
Reg r = ir->r;
|
Reg r = ir->r;
|
||||||
if (as->loopinv) as->mctop--;
|
|
||||||
if (ra_hasreg(r)) {
|
if (ra_hasreg(r)) {
|
||||||
ra_free(as, r);
|
ra_free(as, r);
|
||||||
if (rset_test(as->modset, r) || irt_ismarked(ir->t))
|
if (rset_test(as->modset, r) || irt_ismarked(ir->t))
|
||||||
@@ -2704,21 +2758,17 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
|
|||||||
patchbranch:
|
patchbranch:
|
||||||
p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu);
|
p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu);
|
||||||
*p = MIPSI_NOP; /* Replace the load of the exit number. */
|
*p = MIPSI_NOP; /* Replace the load of the exit number. */
|
||||||
cstop = p;
|
cstop = p+1;
|
||||||
if (!cstart) cstart = p-1;
|
if (!cstart) cstart = p-1;
|
||||||
} else { /* Branch out of range. Use spare jump slot in mcarea. */
|
} else { /* Branch out of range. Use spare jump slot in mcarea. */
|
||||||
int i;
|
MCode *mcjump = asm_sparejump_use(mcarea, tjump);
|
||||||
for (i = (int)(sizeof(MCLink)/sizeof(MCode));
|
if (mcjump) {
|
||||||
i < (int)(sizeof(MCLink)/sizeof(MCode)+MIPS_SPAREJUMP*2);
|
lj_mcode_sync(mcjump, mcjump+1);
|
||||||
i += 2) {
|
delta = mcjump - p;
|
||||||
if (mcarea[i] == tjump) {
|
if (((delta + 0x8000) >> 16) == 0) {
|
||||||
delta = mcarea+i - p;
|
|
||||||
goto patchbranch;
|
|
||||||
} else if (mcarea[i] == MIPSI_NOP) {
|
|
||||||
mcarea[i] = tjump;
|
|
||||||
cstart = mcarea+i;
|
|
||||||
delta = mcarea+i - p;
|
|
||||||
goto patchbranch;
|
goto patchbranch;
|
||||||
|
} else {
|
||||||
|
lj_assertJ(0, "spare jump out of range: -Osizemcode too big");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Ignore jump slot overflow. Child trace is simply not attached. */
|
/* Ignore jump slot overflow. Child trace is simply not attached. */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** PPC IR assembler (SSA IR -> machine code).
|
** PPC IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* -- Register allocator extensions --------------------------------------- */
|
/* -- Register allocator extensions --------------------------------------- */
|
||||||
@@ -156,6 +156,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
|
|||||||
return ra_allock(as, ofs-(int16_t)ofs, allow);
|
return ra_allock(as, ofs-(int16_t)ofs, allow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (ir->o == IR_TMPREF) {
|
||||||
|
*ofsp = (int32_t)(offsetof(global_State, tmptv)-32768);
|
||||||
|
return RID_JGL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*ofsp = 0;
|
*ofsp = 0;
|
||||||
@@ -337,10 +340,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
|||||||
} else {
|
} else {
|
||||||
ra_destreg(as, ir, RID_FPRET);
|
ra_destreg(as, ir, RID_FPRET);
|
||||||
}
|
}
|
||||||
#if LJ_32
|
|
||||||
} else if (hiop) {
|
} else if (hiop) {
|
||||||
ra_destpair(as, ir);
|
ra_destpair(as, ir);
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
ra_destreg(as, ir, RID_RET);
|
ra_destreg(as, ir, RID_RET);
|
||||||
}
|
}
|
||||||
@@ -389,6 +390,21 @@ static void asm_retf(ASMState *as, IRIns *ir)
|
|||||||
emit_tai(as, PPCI_LWZ, RID_TMP, base, -8);
|
emit_tai(as, PPCI_LWZ, RID_TMP, base, -8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -- Buffer operations --------------------------------------------------- */
|
||||||
|
|
||||||
|
#if LJ_HASBUFFER
|
||||||
|
static void asm_bufhdr_write(ASMState *as, Reg sb)
|
||||||
|
{
|
||||||
|
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
|
||||||
|
IRIns irgc;
|
||||||
|
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
|
||||||
|
emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L));
|
||||||
|
emit_rot(as, PPCI_RLWIMI, RID_TMP, tmp, 0, 31-lj_fls(SBUF_MASK_FLAG), 31);
|
||||||
|
emit_getgl(as, RID_TMP, cur_L);
|
||||||
|
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -- Type conversions ---------------------------------------------------- */
|
/* -- Type conversions ---------------------------------------------------- */
|
||||||
|
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
@@ -567,28 +583,54 @@ static void asm_strto(ASMState *as, IRIns *ir)
|
|||||||
/* -- Memory references --------------------------------------------------- */
|
/* -- Memory references --------------------------------------------------- */
|
||||||
|
|
||||||
/* Get pointer to TValue. */
|
/* Get pointer to TValue. */
|
||||||
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
|
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
|
||||||
{
|
{
|
||||||
IRIns *ir = IR(ref);
|
int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768);
|
||||||
if (irt_isnum(ir->t)) {
|
if ((mode & IRTMPREF_IN1)) {
|
||||||
if (irref_isk(ref)) /* Use the number constant itself as a TValue. */
|
IRIns *ir = IR(ref);
|
||||||
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
|
if (irt_isnum(ir->t)) {
|
||||||
else /* Otherwise force a spill and use the spill slot. */
|
if ((mode & IRTMPREF_OUT1)) {
|
||||||
emit_tai(as, PPCI_ADDI, dest, RID_SP, ra_spill(as, ir));
|
#if LJ_SOFTFP
|
||||||
} else {
|
lj_assertA(irref_isk(ref), "unsplit FP op");
|
||||||
/* Otherwise use g->tmptv to hold the TValue. */
|
emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
|
||||||
RegSet allow = rset_exclude(RSET_GPR, dest);
|
emit_setgl(as,
|
||||||
Reg type;
|
ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
|
||||||
emit_tai(as, PPCI_ADDI, dest, RID_JGL, (int32_t)offsetof(global_State, tmptv)-32768);
|
tmptv.u32.lo);
|
||||||
if (!irt_ispri(ir->t)) {
|
emit_setgl(as,
|
||||||
Reg src = ra_alloc1(as, ref, allow);
|
ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
|
||||||
emit_setgl(as, src, tmptv.gcr);
|
tmptv.u32.hi);
|
||||||
|
#else
|
||||||
|
Reg src = ra_alloc1(as, ref, RSET_FPR);
|
||||||
|
emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
|
||||||
|
emit_fai(as, PPCI_STFD, src, RID_JGL, tmpofs);
|
||||||
|
#endif
|
||||||
|
} else if (irref_isk(ref)) {
|
||||||
|
/* Use the number constant itself as a TValue. */
|
||||||
|
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
|
||||||
|
} else {
|
||||||
|
#if LJ_SOFTFP
|
||||||
|
lj_assertA(0, "unsplit FP op");
|
||||||
|
#else
|
||||||
|
/* Otherwise force a spill and use the spill slot. */
|
||||||
|
emit_tai(as, PPCI_ADDI, dest, RID_SP, ra_spill(as, ir));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Otherwise use g->tmptv to hold the TValue. */
|
||||||
|
Reg type;
|
||||||
|
emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
|
||||||
|
if (!irt_ispri(ir->t)) {
|
||||||
|
Reg src = ra_alloc1(as, ref, RSET_GPR);
|
||||||
|
emit_setgl(as, src, tmptv.gcr);
|
||||||
|
}
|
||||||
|
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
|
||||||
|
type = ra_alloc1(as, ref+1, RSET_GPR);
|
||||||
|
else
|
||||||
|
type = ra_allock(as, irt_toitype(ir->t), RSET_GPR);
|
||||||
|
emit_setgl(as, type, tmptv.it);
|
||||||
}
|
}
|
||||||
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP)
|
} else {
|
||||||
type = ra_alloc1(as, ref+1, allow);
|
emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
|
||||||
else
|
|
||||||
type = ra_allock(as, irt_toitype(ir->t), allow);
|
|
||||||
emit_setgl(as, type, tmptv.it);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,7 +936,7 @@ static void asm_fload(ASMState *as, IRIns *ir)
|
|||||||
int32_t ofs;
|
int32_t ofs;
|
||||||
if (ir->op1 == REF_NIL) { /* FLOAD from GG_State with offset. */
|
if (ir->op1 == REF_NIL) { /* FLOAD from GG_State with offset. */
|
||||||
idx = RID_JGL;
|
idx = RID_JGL;
|
||||||
ofs = (ir->op2 << 2) - 32768;
|
ofs = (ir->op2 << 2) - 32768 - GG_OFS(g);
|
||||||
} else {
|
} else {
|
||||||
idx = ra_alloc1(as, ir->op1, RSET_GPR);
|
idx = ra_alloc1(as, ir->op1, RSET_GPR);
|
||||||
if (ir->op2 == IRFL_TAB_ARRAY) {
|
if (ir->op2 == IRFL_TAB_ARRAY) {
|
||||||
@@ -975,6 +1017,10 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
rset_clear(allow, dest);
|
rset_clear(allow, dest);
|
||||||
}
|
}
|
||||||
idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
|
idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
|
||||||
|
if (ir->o == IR_VLOAD) {
|
||||||
|
ofs = ofs != AHUREF_LSX ? ofs + 8 * ir->op2 :
|
||||||
|
ir->op2 ? 8 * ir->op2 : AHUREF_LSX;
|
||||||
|
}
|
||||||
if (irt_isnum(t)) {
|
if (irt_isnum(t)) {
|
||||||
Reg tisnum = ra_allock(as, (int32_t)LJ_TISNUM, rset_exclude(allow, idx));
|
Reg tisnum = ra_allock(as, (int32_t)LJ_TISNUM, rset_exclude(allow, idx));
|
||||||
asm_guardcc(as, CC_GE);
|
asm_guardcc(as, CC_GE);
|
||||||
@@ -1057,7 +1103,8 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
lj_assertA(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK),
|
lj_assertA(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK),
|
||||||
"inconsistent SLOAD variant");
|
"inconsistent SLOAD variant");
|
||||||
lj_assertA(LJ_DUALNUM ||
|
lj_assertA(LJ_DUALNUM ||
|
||||||
!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)),
|
!irt_isint(t) ||
|
||||||
|
(ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME|IRSLOAD_KEYINDEX)),
|
||||||
"bad SLOAD type");
|
"bad SLOAD type");
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
lj_assertA(!(ir->op2 & IRSLOAD_CONVERT),
|
lj_assertA(!(ir->op2 & IRSLOAD_CONVERT),
|
||||||
@@ -1894,15 +1941,15 @@ static void asm_comp64(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */
|
/* -- Split register ops -------------------------------------------------- */
|
||||||
|
|
||||||
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */
|
/* Hiword op of a split 32/32 bit op. Previous op is be the loword op. */
|
||||||
static void asm_hiop(ASMState *as, IRIns *ir)
|
static void asm_hiop(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
#if LJ_HASFFI || LJ_SOFTFP
|
|
||||||
/* HIOP is marked as a store because it needs its own DCE logic. */
|
/* HIOP is marked as a store because it needs its own DCE logic. */
|
||||||
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
|
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
|
||||||
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
|
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
|
||||||
|
#if LJ_HASFFI || LJ_SOFTFP
|
||||||
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
|
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
|
||||||
as->curins--; /* Always skip the CONV. */
|
as->curins--; /* Always skip the CONV. */
|
||||||
#if LJ_HASFFI && !LJ_SOFTFP
|
#if LJ_HASFFI && !LJ_SOFTFP
|
||||||
@@ -1937,12 +1984,16 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
|
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
|
||||||
switch ((ir-1)->o) {
|
switch ((ir-1)->o) {
|
||||||
#if LJ_HASFFI
|
#if LJ_HASFFI
|
||||||
case IR_ADD: as->curins--; asm_add64(as, ir); break;
|
case IR_ADD: as->curins--; asm_add64(as, ir); break;
|
||||||
case IR_SUB: as->curins--; asm_sub64(as, ir); break;
|
case IR_SUB: as->curins--; asm_sub64(as, ir); break;
|
||||||
case IR_NEG: as->curins--; asm_neg64(as, ir); break;
|
case IR_NEG: as->curins--; asm_neg64(as, ir); break;
|
||||||
|
case IR_CNEWI:
|
||||||
|
/* Nothing to do here. Handled by lo op itself. */
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if LJ_SOFTFP
|
#if LJ_SOFTFP
|
||||||
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
|
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
|
||||||
@@ -1950,25 +2001,16 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
if (!uselo)
|
if (!uselo)
|
||||||
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
|
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
|
||||||
break;
|
break;
|
||||||
|
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
|
||||||
|
/* Nothing to do here. Handled by lo op itself. */
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
case IR_CALLN:
|
case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
|
||||||
case IR_CALLS:
|
|
||||||
case IR_CALLXS:
|
|
||||||
if (!uselo)
|
if (!uselo)
|
||||||
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
|
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
|
||||||
break;
|
break;
|
||||||
#if LJ_SOFTFP
|
|
||||||
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR:
|
|
||||||
#endif
|
|
||||||
case IR_CNEWI:
|
|
||||||
/* Nothing to do here. Handled by lo op itself. */
|
|
||||||
break;
|
|
||||||
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/* Unused without SOFTFP or FFI. */
|
|
||||||
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Profiling ----------------------------------------------------------- */
|
/* -- Profiling ----------------------------------------------------------- */
|
||||||
@@ -2055,6 +2097,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
} else if ((sn & SNAP_SOFTFPNUM)) {
|
} else if ((sn & SNAP_SOFTFPNUM)) {
|
||||||
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE));
|
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE));
|
||||||
#endif
|
#endif
|
||||||
|
} else if ((sn & SNAP_KEYINDEX)) {
|
||||||
|
type = ra_allock(as, (int32_t)LJ_KEYINDEX, allow);
|
||||||
} else {
|
} else {
|
||||||
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
|
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
|
||||||
}
|
}
|
||||||
@@ -2113,6 +2157,12 @@ static void asm_loop_fixup(ASMState *as)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fixup the tail of the loop. */
|
||||||
|
static void asm_loop_tail_fixup(ASMState *as)
|
||||||
|
{
|
||||||
|
UNUSED(as); /* Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
/* -- Head of trace ------------------------------------------------------- */
|
/* -- Head of trace ------------------------------------------------------- */
|
||||||
|
|
||||||
/* Coalesce BASE register for a root trace. */
|
/* Coalesce BASE register for a root trace. */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** x86/x64 IR assembler (SSA IR -> machine code).
|
** x86/x64 IR assembler (SSA IR -> machine code).
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* -- Guard handling ------------------------------------------------------ */
|
/* -- Guard handling ------------------------------------------------------ */
|
||||||
@@ -216,10 +216,17 @@ static void asm_fuseahuref(ASMState *as, IRRef ref, RegSet allow)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case IR_TMPREF:
|
||||||
|
#if LJ_GC64
|
||||||
|
as->mrm.ofs = (int32_t)dispofs(as, &J2G(as->J)->tmptv);
|
||||||
|
as->mrm.base = RID_DISPATCH;
|
||||||
|
as->mrm.idx = RID_NONE;
|
||||||
|
#else
|
||||||
|
as->mrm.ofs = igcptr(&J2G(as->J)->tmptv);
|
||||||
|
as->mrm.base = as->mrm.idx = RID_NONE;
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
lj_assertA(ir->o == IR_HREF || ir->o == IR_NEWREF || ir->o == IR_UREFO ||
|
|
||||||
ir->o == IR_KKPTR,
|
|
||||||
"bad IR op %d", ir->o);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -480,6 +487,7 @@ static Reg asm_fuseload(ASMState *as, IRRef ref, RegSet allow)
|
|||||||
}
|
}
|
||||||
} else if (ir->o == IR_VLOAD && !(LJ_GC64 && irt_isaddr(ir->t))) {
|
} else if (ir->o == IR_VLOAD && !(LJ_GC64 && irt_isaddr(ir->t))) {
|
||||||
asm_fuseahuref(as, ir->op1, xallow);
|
asm_fuseahuref(as, ir->op1, xallow);
|
||||||
|
as->mrm.ofs += 8 * ir->op2;
|
||||||
return RID_MRM;
|
return RID_MRM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -651,7 +659,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
|
|||||||
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
||||||
{
|
{
|
||||||
RegSet drop = RSET_SCRATCH;
|
RegSet drop = RSET_SCRATCH;
|
||||||
int hiop = (LJ_32 && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
|
int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
|
||||||
if ((ci->flags & CCI_NOFPRCLOBBER))
|
if ((ci->flags & CCI_NOFPRCLOBBER))
|
||||||
drop &= ~RSET_FPR;
|
drop &= ~RSET_FPR;
|
||||||
if (ra_hasreg(ir->r))
|
if (ra_hasreg(ir->r))
|
||||||
@@ -691,10 +699,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
|
|||||||
irt_isnum(ir->t) ? XOg_FSTPq : XOg_FSTPd, RID_ESP, ofs);
|
irt_isnum(ir->t) ? XOg_FSTPq : XOg_FSTPd, RID_ESP, ofs);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if LJ_32
|
|
||||||
} else if (hiop) {
|
} else if (hiop) {
|
||||||
ra_destpair(as, ir);
|
ra_destpair(as, ir);
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
lj_assertA(!irt_ispri(ir->t), "PRI dest");
|
lj_assertA(!irt_ispri(ir->t), "PRI dest");
|
||||||
ra_destreg(as, ir, RID_RET);
|
ra_destreg(as, ir, RID_RET);
|
||||||
@@ -781,6 +787,21 @@ static void asm_retf(ASMState *as, IRIns *ir)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -- Buffer operations --------------------------------------------------- */
|
||||||
|
|
||||||
|
#if LJ_HASBUFFER
|
||||||
|
static void asm_bufhdr_write(ASMState *as, Reg sb)
|
||||||
|
{
|
||||||
|
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
|
||||||
|
IRIns irgc;
|
||||||
|
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
|
||||||
|
emit_storeofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
|
||||||
|
emit_opgl(as, XO_ARITH(XOg_OR), tmp|REX_GC64, cur_L);
|
||||||
|
emit_gri(as, XG_ARITHi(XOg_AND), tmp, SBUF_MASK_FLAG);
|
||||||
|
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -- Type conversions ---------------------------------------------------- */
|
/* -- Type conversions ---------------------------------------------------- */
|
||||||
|
|
||||||
static void asm_tointg(ASMState *as, IRIns *ir, Reg left)
|
static void asm_tointg(ASMState *as, IRIns *ir, Reg left)
|
||||||
@@ -924,7 +945,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Reg dest = ra_dest(as, ir, RSET_GPR);
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
if (st64) {
|
if (st64 && !(ir->op2 & IRCONV_NONE)) {
|
||||||
Reg left = asm_fuseload(as, lref, RSET_GPR);
|
Reg left = asm_fuseload(as, lref, RSET_GPR);
|
||||||
/* This is either a 32 bit reg/reg mov which zeroes the hiword
|
/* This is either a 32 bit reg/reg mov which zeroes the hiword
|
||||||
** or a load of the loword from a 64 bit address.
|
** or a load of the loword from a 64 bit address.
|
||||||
@@ -1050,47 +1071,48 @@ static void asm_strto(ASMState *as, IRIns *ir)
|
|||||||
/* -- Memory references --------------------------------------------------- */
|
/* -- Memory references --------------------------------------------------- */
|
||||||
|
|
||||||
/* Get pointer to TValue. */
|
/* Get pointer to TValue. */
|
||||||
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref)
|
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
|
||||||
{
|
{
|
||||||
IRIns *ir = IR(ref);
|
if ((mode & IRTMPREF_IN1)) {
|
||||||
if (irt_isnum(ir->t)) {
|
IRIns *ir = IR(ref);
|
||||||
/* For numbers use the constant itself or a spill slot as a TValue. */
|
if (irt_isnum(ir->t)) {
|
||||||
if (irref_isk(ref))
|
if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) {
|
||||||
emit_loada(as, dest, ir_knum(ir));
|
/* Use the number constant itself as a TValue. */
|
||||||
else
|
emit_loada(as, dest, ir_knum(ir));
|
||||||
emit_rmro(as, XO_LEA, dest|REX_64, RID_ESP, ra_spill(as, ir));
|
return;
|
||||||
} else {
|
}
|
||||||
/* Otherwise use g->tmptv to hold the TValue. */
|
emit_rmro(as, XO_MOVSDto, ra_alloc1(as, ref, RSET_FPR), dest, 0);
|
||||||
#if LJ_GC64
|
} else {
|
||||||
if (irref_isk(ref)) {
|
#if LJ_GC64
|
||||||
TValue k;
|
if (irref_isk(ref)) {
|
||||||
lj_ir_kvalue(as->J->L, &k, ir);
|
TValue k;
|
||||||
emit_movmroi(as, dest, 4, k.u32.hi);
|
lj_ir_kvalue(as->J->L, &k, ir);
|
||||||
emit_movmroi(as, dest, 0, k.u32.lo);
|
emit_movmroi(as, dest, 4, k.u32.hi);
|
||||||
} else {
|
emit_movmroi(as, dest, 0, k.u32.lo);
|
||||||
/* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */
|
} else {
|
||||||
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest));
|
/* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */
|
||||||
if (irt_is64(ir->t)) {
|
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest));
|
||||||
emit_u32(as, irt_toitype(ir->t) << 15);
|
if (irt_is64(ir->t)) {
|
||||||
emit_rmro(as, XO_ARITHi, XOg_OR, dest, 4);
|
emit_u32(as, irt_toitype(ir->t) << 15);
|
||||||
} else {
|
emit_rmro(as, XO_ARITHi, XOg_OR, dest, 4);
|
||||||
/* Currently, no caller passes integers that might end up here. */
|
} else {
|
||||||
emit_movmroi(as, dest, 4, (irt_toitype(ir->t) << 15));
|
emit_movmroi(as, dest, 4, (irt_toitype(ir->t) << 15));
|
||||||
|
}
|
||||||
|
emit_movtomro(as, REX_64IR(ir, src), dest, 0);
|
||||||
}
|
}
|
||||||
emit_movtomro(as, REX_64IR(ir, src), dest, 0);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (!irref_isk(ref)) {
|
if (!irref_isk(ref)) {
|
||||||
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest));
|
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest));
|
||||||
emit_movtomro(as, REX_64IR(ir, src), dest, 0);
|
emit_movtomro(as, REX_64IR(ir, src), dest, 0);
|
||||||
} else if (!irt_ispri(ir->t)) {
|
} else if (!irt_ispri(ir->t)) {
|
||||||
emit_movmroi(as, dest, 0, ir->i);
|
emit_movmroi(as, dest, 0, ir->i);
|
||||||
}
|
}
|
||||||
if (!(LJ_64 && irt_islightud(ir->t)))
|
if (!(LJ_64 && irt_islightud(ir->t)))
|
||||||
emit_movmroi(as, dest, 4, irt_toitype(ir->t));
|
emit_movmroi(as, dest, 4, irt_toitype(ir->t));
|
||||||
#endif
|
#endif
|
||||||
emit_loada(as, dest, &J2G(as->J)->tmptv);
|
}
|
||||||
}
|
}
|
||||||
|
emit_loada(as, dest, &J2G(as->J)->tmptv); /* g->tmptv holds the TValue(s). */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_aref(ASMState *as, IRIns *ir)
|
static void asm_aref(ASMState *as, IRIns *ir)
|
||||||
@@ -1524,6 +1546,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
Reg dest = asm_load_lightud64(as, ir, 1);
|
Reg dest = asm_load_lightud64(as, ir, 1);
|
||||||
if (ra_hasreg(dest)) {
|
if (ra_hasreg(dest)) {
|
||||||
asm_fuseahuref(as, ir->op1, RSET_GPR);
|
asm_fuseahuref(as, ir->op1, RSET_GPR);
|
||||||
|
if (ir->o == IR_VLOAD) as->mrm.ofs += 8 * ir->op2;
|
||||||
emit_mrm(as, XO_MOV, dest|REX_64, RID_MRM);
|
emit_mrm(as, XO_MOV, dest|REX_64, RID_MRM);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -1533,6 +1556,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
RegSet allow = irt_isnum(ir->t) ? RSET_FPR : RSET_GPR;
|
RegSet allow = irt_isnum(ir->t) ? RSET_FPR : RSET_GPR;
|
||||||
Reg dest = ra_dest(as, ir, allow);
|
Reg dest = ra_dest(as, ir, allow);
|
||||||
asm_fuseahuref(as, ir->op1, RSET_GPR);
|
asm_fuseahuref(as, ir->op1, RSET_GPR);
|
||||||
|
if (ir->o == IR_VLOAD) as->mrm.ofs += 8 * ir->op2;
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
if (irt_isaddr(ir->t)) {
|
if (irt_isaddr(ir->t)) {
|
||||||
emit_shifti(as, XOg_SHR|REX_64, dest, 17);
|
emit_shifti(as, XOg_SHR|REX_64, dest, 17);
|
||||||
@@ -1560,6 +1584,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
asm_fuseahuref(as, ir->op1, gpr);
|
asm_fuseahuref(as, ir->op1, gpr);
|
||||||
|
if (ir->o == IR_VLOAD) as->mrm.ofs += 8 * ir->op2;
|
||||||
}
|
}
|
||||||
/* Always do the type check, even if the load result is unused. */
|
/* Always do the type check, even if the load result is unused. */
|
||||||
as->mrm.ofs += 4;
|
as->mrm.ofs += 4;
|
||||||
@@ -1675,7 +1700,8 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
lj_assertA(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK),
|
lj_assertA(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK),
|
||||||
"inconsistent SLOAD variant");
|
"inconsistent SLOAD variant");
|
||||||
lj_assertA(LJ_DUALNUM ||
|
lj_assertA(LJ_DUALNUM ||
|
||||||
!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)),
|
!irt_isint(t) ||
|
||||||
|
(ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME|IRSLOAD_KEYINDEX)),
|
||||||
"bad SLOAD type");
|
"bad SLOAD type");
|
||||||
if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) {
|
if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) {
|
||||||
Reg left = ra_scratch(as, RSET_FPR);
|
Reg left = ra_scratch(as, RSET_FPR);
|
||||||
@@ -2584,15 +2610,15 @@ static void asm_comp_int64(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */
|
/* -- Split register ops -------------------------------------------------- */
|
||||||
|
|
||||||
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */
|
/* Hiword op of a split 32/32 or 64/64 bit op. Previous op is the loword op. */
|
||||||
static void asm_hiop(ASMState *as, IRIns *ir)
|
static void asm_hiop(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
#if LJ_32 && LJ_HASFFI
|
|
||||||
/* HIOP is marked as a store because it needs its own DCE logic. */
|
/* HIOP is marked as a store because it needs its own DCE logic. */
|
||||||
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
|
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
|
||||||
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
|
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
|
||||||
|
#if LJ_32 && LJ_HASFFI
|
||||||
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
|
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
|
||||||
as->curins--; /* Always skip the CONV. */
|
as->curins--; /* Always skip the CONV. */
|
||||||
if (usehi || uselo)
|
if (usehi || uselo)
|
||||||
@@ -2606,8 +2632,10 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
asm_fxstore(as, ir);
|
asm_fxstore(as, ir);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
|
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
|
||||||
switch ((ir-1)->o) {
|
switch ((ir-1)->o) {
|
||||||
|
#if LJ_32 && LJ_HASFFI
|
||||||
case IR_ADD:
|
case IR_ADD:
|
||||||
as->flagmcp = NULL;
|
as->flagmcp = NULL;
|
||||||
as->curins--;
|
as->curins--;
|
||||||
@@ -2630,20 +2658,16 @@ static void asm_hiop(ASMState *as, IRIns *ir)
|
|||||||
asm_neg_not(as, ir-1, XOg_NEG);
|
asm_neg_not(as, ir-1, XOg_NEG);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IR_CALLN:
|
|
||||||
case IR_CALLXS:
|
|
||||||
if (!uselo)
|
|
||||||
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
|
|
||||||
break;
|
|
||||||
case IR_CNEWI:
|
case IR_CNEWI:
|
||||||
/* Nothing to do here. Handled by CNEWI itself. */
|
/* Nothing to do here. Handled by CNEWI itself. */
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
|
||||||
|
if (!uselo)
|
||||||
|
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
|
||||||
|
break;
|
||||||
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/* Unused on x64 or without FFI. */
|
|
||||||
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Profiling ----------------------------------------------------------- */
|
/* -- Profiling ----------------------------------------------------------- */
|
||||||
@@ -2704,7 +2728,15 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
IRIns *ir = IR(ref);
|
IRIns *ir = IR(ref);
|
||||||
if ((sn & SNAP_NORESTORE))
|
if ((sn & SNAP_NORESTORE))
|
||||||
continue;
|
continue;
|
||||||
if (irt_isnum(ir->t)) {
|
if ((sn & SNAP_KEYINDEX)) {
|
||||||
|
emit_movmroi(as, RID_BASE, ofs+4, LJ_KEYINDEX);
|
||||||
|
if (irref_isk(ref)) {
|
||||||
|
emit_movmroi(as, RID_BASE, ofs, ir->i);
|
||||||
|
} else {
|
||||||
|
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, RID_BASE));
|
||||||
|
emit_movtomro(as, src, RID_BASE, ofs);
|
||||||
|
}
|
||||||
|
} else if (irt_isnum(ir->t)) {
|
||||||
Reg src = ra_alloc1(as, ref, RSET_FPR);
|
Reg src = ra_alloc1(as, ref, RSET_FPR);
|
||||||
emit_rmro(as, XO_MOVSDto, src, RID_BASE, ofs);
|
emit_rmro(as, XO_MOVSDto, src, RID_BASE, ofs);
|
||||||
} else {
|
} else {
|
||||||
@@ -2837,6 +2869,12 @@ static void asm_loop_fixup(ASMState *as)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fixup the tail of the loop. */
|
||||||
|
static void asm_loop_tail_fixup(ASMState *as)
|
||||||
|
{
|
||||||
|
UNUSED(as); /* Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
/* -- Head of trace ------------------------------------------------------- */
|
/* -- Head of trace ------------------------------------------------------- */
|
||||||
|
|
||||||
/* Coalesce BASE register for a root trace. */
|
/* Coalesce BASE register for a root trace. */
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Internal assertions.
|
** Internal assertions.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_assert_c
|
#define lj_assert_c
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bytecode instruction modes.
|
** Bytecode instruction modes.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_bc_c
|
#define lj_bc_c
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bytecode instruction format.
|
** Bytecode instruction format.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_BC_H
|
#ifndef _LJ_BC_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bytecode dump definitions.
|
** Bytecode dump definitions.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_BCDUMP_H
|
#ifndef _LJ_BCDUMP_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bytecode reader.
|
** Bytecode reader.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_bcread_c
|
#define lj_bcread_c
|
||||||
@@ -53,11 +53,11 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
|
|||||||
do {
|
do {
|
||||||
const char *buf;
|
const char *buf;
|
||||||
size_t sz;
|
size_t sz;
|
||||||
char *p = sbufB(&ls->sb);
|
char *p = ls->sb.b;
|
||||||
MSize n = (MSize)(ls->pe - ls->p);
|
MSize n = (MSize)(ls->pe - ls->p);
|
||||||
if (n) { /* Copy remainder to buffer. */
|
if (n) { /* Copy remainder to buffer. */
|
||||||
if (sbuflen(&ls->sb)) { /* Move down in buffer. */
|
if (sbuflen(&ls->sb)) { /* Move down in buffer. */
|
||||||
lj_assertLS(ls->pe == sbufP(&ls->sb), "bad buffer pointer");
|
lj_assertLS(ls->pe == ls->sb.w, "bad buffer pointer");
|
||||||
if (ls->p != p) memmove(p, ls->p, n);
|
if (ls->p != p) memmove(p, ls->p, n);
|
||||||
} else { /* Copy from buffer provided by reader. */
|
} else { /* Copy from buffer provided by reader. */
|
||||||
p = lj_buf_need(&ls->sb, len);
|
p = lj_buf_need(&ls->sb, len);
|
||||||
@@ -66,7 +66,7 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
|
|||||||
ls->p = p;
|
ls->p = p;
|
||||||
ls->pe = p + n;
|
ls->pe = p + n;
|
||||||
}
|
}
|
||||||
setsbufP(&ls->sb, p + n);
|
ls->sb.w = p + n;
|
||||||
buf = ls->rfunc(ls->L, ls->rdata, &sz); /* Get more data from reader. */
|
buf = ls->rfunc(ls->L, ls->rdata, &sz); /* Get more data from reader. */
|
||||||
if (buf == NULL || sz == 0) { /* EOF? */
|
if (buf == NULL || sz == 0) { /* EOF? */
|
||||||
if (need) bcread_error(ls, LJ_ERR_BCBAD);
|
if (need) bcread_error(ls, LJ_ERR_BCBAD);
|
||||||
@@ -77,8 +77,8 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
|
|||||||
if (n) { /* Append to buffer. */
|
if (n) { /* Append to buffer. */
|
||||||
n += (MSize)sz;
|
n += (MSize)sz;
|
||||||
p = lj_buf_need(&ls->sb, n < len ? len : n);
|
p = lj_buf_need(&ls->sb, n < len ? len : n);
|
||||||
memcpy(sbufP(&ls->sb), buf, sz);
|
memcpy(ls->sb.w, buf, sz);
|
||||||
setsbufP(&ls->sb, p + n);
|
ls->sb.w = p + n;
|
||||||
ls->p = p;
|
ls->p = p;
|
||||||
ls->pe = p + n;
|
ls->pe = p + n;
|
||||||
} else { /* Return buffer provided by reader. */
|
} else { /* Return buffer provided by reader. */
|
||||||
@@ -399,11 +399,7 @@ static int bcread_header(LexState *ls)
|
|||||||
if ((flags & BCDUMP_F_FFI)) {
|
if ((flags & BCDUMP_F_FFI)) {
|
||||||
#if LJ_HASFFI
|
#if LJ_HASFFI
|
||||||
lua_State *L = ls->L;
|
lua_State *L = ls->L;
|
||||||
if (!ctype_ctsG(G(L))) {
|
ctype_loadffi(L);
|
||||||
ptrdiff_t oldtop = savestack(L, L->top);
|
|
||||||
luaopen_ffi(L); /* Load FFI library on-demand. */
|
|
||||||
L->top = restorestack(L, oldtop);
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Bytecode writer.
|
** Bytecode writer.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_bcwrite_c
|
#define lj_bcwrite_c
|
||||||
@@ -62,7 +62,7 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
|
|||||||
if (num == (lua_Number)k) { /* -0 is never a constant. */
|
if (num == (lua_Number)k) { /* -0 is never a constant. */
|
||||||
*p++ = BCDUMP_KTAB_INT;
|
*p++ = BCDUMP_KTAB_INT;
|
||||||
p = lj_strfmt_wuleb128(p, k);
|
p = lj_strfmt_wuleb128(p, k);
|
||||||
setsbufP(&ctx->sb, p);
|
ctx->sb.w = p;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
|
|||||||
lj_assertBCW(tvispri(o), "unhandled type %d", itype(o));
|
lj_assertBCW(tvispri(o), "unhandled type %d", itype(o));
|
||||||
*p++ = BCDUMP_KTAB_NIL+~itype(o);
|
*p++ = BCDUMP_KTAB_NIL+~itype(o);
|
||||||
}
|
}
|
||||||
setsbufP(&ctx->sb, p);
|
ctx->sb.w = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write a template table. */
|
/* Write a template table. */
|
||||||
@@ -97,7 +97,7 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
|
|||||||
/* Write number of array slots and hash slots. */
|
/* Write number of array slots and hash slots. */
|
||||||
p = lj_strfmt_wuleb128(p, narray);
|
p = lj_strfmt_wuleb128(p, narray);
|
||||||
p = lj_strfmt_wuleb128(p, nhash);
|
p = lj_strfmt_wuleb128(p, nhash);
|
||||||
setsbufP(&ctx->sb, p);
|
ctx->sb.w = p;
|
||||||
if (narray) { /* Write array entries (may contain nil). */
|
if (narray) { /* Write array entries (may contain nil). */
|
||||||
MSize i;
|
MSize i;
|
||||||
TValue *o = tvref(t->array);
|
TValue *o = tvref(t->array);
|
||||||
@@ -172,7 +172,7 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
setsbufP(&ctx->sb, p);
|
ctx->sb.w = p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ static void bcwrite_knum(BCWriteCtx *ctx, GCproto *pt)
|
|||||||
p = lj_strfmt_wuleb128(p, o->u32.hi);
|
p = lj_strfmt_wuleb128(p, o->u32.hi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setsbufP(&ctx->sb, p);
|
ctx->sb.w = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write bytecode instructions. */
|
/* Write bytecode instructions. */
|
||||||
@@ -281,7 +281,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
|
|||||||
/* Write bytecode instructions and upvalue refs. */
|
/* Write bytecode instructions and upvalue refs. */
|
||||||
p = bcwrite_bytecode(ctx, p, pt);
|
p = bcwrite_bytecode(ctx, p, pt);
|
||||||
p = lj_buf_wmem(p, proto_uv(pt), pt->sizeuv*2);
|
p = lj_buf_wmem(p, proto_uv(pt), pt->sizeuv*2);
|
||||||
setsbufP(&ctx->sb, p);
|
ctx->sb.w = p;
|
||||||
|
|
||||||
/* Write constants. */
|
/* Write constants. */
|
||||||
bcwrite_kgc(ctx, pt);
|
bcwrite_kgc(ctx, pt);
|
||||||
@@ -291,16 +291,16 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
|
|||||||
if (sizedbg) {
|
if (sizedbg) {
|
||||||
p = lj_buf_more(&ctx->sb, sizedbg);
|
p = lj_buf_more(&ctx->sb, sizedbg);
|
||||||
p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg);
|
p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg);
|
||||||
setsbufP(&ctx->sb, p);
|
ctx->sb.w = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pass buffer to writer function. */
|
/* Pass buffer to writer function. */
|
||||||
if (ctx->status == 0) {
|
if (ctx->status == 0) {
|
||||||
MSize n = sbuflen(&ctx->sb) - 5;
|
MSize n = sbuflen(&ctx->sb) - 5;
|
||||||
MSize nn = (lj_fls(n)+8)*9 >> 6;
|
MSize nn = (lj_fls(n)+8)*9 >> 6;
|
||||||
char *q = sbufB(&ctx->sb) + (5 - nn);
|
char *q = ctx->sb.b + (5 - nn);
|
||||||
p = lj_strfmt_wuleb128(q, n); /* Fill in final size. */
|
p = lj_strfmt_wuleb128(q, n); /* Fill in final size. */
|
||||||
lj_assertBCW(p == sbufB(&ctx->sb) + 5, "bad ULEB128 write");
|
lj_assertBCW(p == ctx->sb.b + 5, "bad ULEB128 write");
|
||||||
ctx->status = ctx->wfunc(sbufL(&ctx->sb), q, nn+n, ctx->wdata);
|
ctx->status = ctx->wfunc(sbufL(&ctx->sb), q, nn+n, ctx->wdata);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,8 +324,8 @@ static void bcwrite_header(BCWriteCtx *ctx)
|
|||||||
p = lj_strfmt_wuleb128(p, len);
|
p = lj_strfmt_wuleb128(p, len);
|
||||||
p = lj_buf_wmem(p, name, len);
|
p = lj_buf_wmem(p, name, len);
|
||||||
}
|
}
|
||||||
ctx->status = ctx->wfunc(sbufL(&ctx->sb), sbufB(&ctx->sb),
|
ctx->status = ctx->wfunc(sbufL(&ctx->sb), ctx->sb.b,
|
||||||
(MSize)(p - sbufB(&ctx->sb)), ctx->wdata);
|
(MSize)(p - ctx->sb.b), ctx->wdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write footer of bytecode dump. */
|
/* Write footer of bytecode dump. */
|
||||||
|
|||||||
+133
-60
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Buffer handling.
|
** Buffer handling.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lj_buf_c
|
#define lj_buf_c
|
||||||
@@ -20,12 +20,32 @@ static void buf_grow(SBuf *sb, MSize sz)
|
|||||||
{
|
{
|
||||||
MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz;
|
MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz;
|
||||||
char *b;
|
char *b;
|
||||||
|
GCSize flag;
|
||||||
if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF;
|
if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF;
|
||||||
while (nsz < sz) nsz += nsz;
|
while (nsz < sz) nsz += nsz;
|
||||||
b = (char *)lj_mem_realloc(sbufL(sb), sbufB(sb), osz, nsz);
|
flag = sbufflag(sb);
|
||||||
setmref(sb->b, b);
|
if ((flag & SBUF_FLAG_COW)) { /* Copy-on-write semantics. */
|
||||||
setmref(sb->p, b + len);
|
lj_assertG_(G(sbufL(sb)), sb->w == sb->e, "bad SBuf COW");
|
||||||
setmref(sb->e, b + nsz);
|
b = (char *)lj_mem_new(sbufL(sb), nsz);
|
||||||
|
setsbufflag(sb, flag & ~(GCSize)SBUF_FLAG_COW);
|
||||||
|
setgcrefnull(sbufX(sb)->cowref);
|
||||||
|
memcpy(b, sb->b, osz);
|
||||||
|
} else {
|
||||||
|
b = (char *)lj_mem_realloc(sbufL(sb), sb->b, osz, nsz);
|
||||||
|
}
|
||||||
|
if ((flag & SBUF_FLAG_EXT)) {
|
||||||
|
sbufX(sb)->r = sbufX(sb)->r - sb->b + b; /* Adjust read pointer, too. */
|
||||||
|
}
|
||||||
|
/* Adjust buffer pointers. */
|
||||||
|
sb->b = b;
|
||||||
|
sb->w = b + len;
|
||||||
|
sb->e = b + nsz;
|
||||||
|
if ((flag & SBUF_FLAG_BORROW)) { /* Adjust borrowed buffer pointers. */
|
||||||
|
SBuf *bsb = mref(sbufX(sb)->bsb, SBuf);
|
||||||
|
bsb->b = b;
|
||||||
|
bsb->w = b + len;
|
||||||
|
bsb->e = b + nsz;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
|
LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
|
||||||
@@ -34,30 +54,51 @@ LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
|
|||||||
if (LJ_UNLIKELY(sz > LJ_MAX_BUF))
|
if (LJ_UNLIKELY(sz > LJ_MAX_BUF))
|
||||||
lj_err_mem(sbufL(sb));
|
lj_err_mem(sbufL(sb));
|
||||||
buf_grow(sb, sz);
|
buf_grow(sb, sz);
|
||||||
return sbufB(sb);
|
return sb->b;
|
||||||
}
|
}
|
||||||
|
|
||||||
LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz)
|
LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz)
|
||||||
{
|
{
|
||||||
MSize len = sbuflen(sb);
|
if (sbufisext(sb)) {
|
||||||
lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow");
|
SBufExt *sbx = (SBufExt *)sb;
|
||||||
if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
|
MSize len = sbufxlen(sbx);
|
||||||
lj_err_mem(sbufL(sb));
|
if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
|
||||||
buf_grow(sb, len + sz);
|
lj_err_mem(sbufL(sbx));
|
||||||
return sbufP(sb);
|
if (len + sz > sbufsz(sbx)) { /* Must grow. */
|
||||||
|
buf_grow((SBuf *)sbx, len + sz);
|
||||||
|
} else if (sbufxslack(sbx) < (sbufsz(sbx) >> 3)) {
|
||||||
|
/* Also grow to avoid excessive compactions, if slack < size/8. */
|
||||||
|
buf_grow((SBuf *)sbx, sbuflen(sbx) + sz); /* Not sbufxlen! */
|
||||||
|
return sbx->w;
|
||||||
|
}
|
||||||
|
if (sbx->r != sbx->b) { /* Compact by moving down. */
|
||||||
|
memmove(sbx->b, sbx->r, len);
|
||||||
|
sbx->r = sbx->b;
|
||||||
|
sbx->w = sbx->b + len;
|
||||||
|
lj_assertG_(G(sbufL(sbx)), len + sz <= sbufsz(sbx), "bad SBuf compact");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MSize len = sbuflen(sb);
|
||||||
|
lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow");
|
||||||
|
if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
|
||||||
|
lj_err_mem(sbufL(sb));
|
||||||
|
buf_grow(sb, len + sz);
|
||||||
|
}
|
||||||
|
return sb->w;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb)
|
void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb)
|
||||||
{
|
{
|
||||||
char *b = sbufB(sb);
|
char *b = sb->b;
|
||||||
MSize osz = (MSize)(sbufE(sb) - b);
|
MSize osz = (MSize)(sb->e - b);
|
||||||
if (osz > 2*LJ_MIN_SBUF) {
|
if (osz > 2*LJ_MIN_SBUF) {
|
||||||
MSize n = (MSize)(sbufP(sb) - b);
|
MSize n = (MSize)(sb->w - b);
|
||||||
b = lj_mem_realloc(L, b, osz, (osz >> 1));
|
b = lj_mem_realloc(L, b, osz, (osz >> 1));
|
||||||
setmref(sb->b, b);
|
sb->b = b;
|
||||||
setmref(sb->p, b + n);
|
sb->w = b + n;
|
||||||
setmref(sb->e, b + (osz >> 1));
|
sb->e = b + (osz >> 1);
|
||||||
}
|
}
|
||||||
|
lj_assertG_(G(sbufL(sb)), !sbufisext(sb), "YAGNI shrink SBufExt");
|
||||||
}
|
}
|
||||||
|
|
||||||
char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz)
|
char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz)
|
||||||
@@ -67,30 +108,62 @@ char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz)
|
|||||||
return lj_buf_need(sb, sz);
|
return lj_buf_need(sb, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if LJ_HASBUFFER && LJ_HASJIT
|
||||||
|
void lj_bufx_set(SBufExt *sbx, const char *p, MSize len, GCobj *ref)
|
||||||
|
{
|
||||||
|
lua_State *L = sbufL(sbx);
|
||||||
|
lj_bufx_free(L, sbx);
|
||||||
|
lj_bufx_set_cow(L, sbx, p, len);
|
||||||
|
setgcref(sbx->cowref, ref);
|
||||||
|
lj_gc_objbarrier(L, (GCudata *)sbx - 1, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LJ_HASFFI
|
||||||
|
MSize LJ_FASTCALL lj_bufx_more(SBufExt *sbx, MSize sz)
|
||||||
|
{
|
||||||
|
lj_buf_more((SBuf *)sbx, sz);
|
||||||
|
return sbufleft(sbx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* -- Low-level buffer put operations ------------------------------------- */
|
/* -- Low-level buffer put operations ------------------------------------- */
|
||||||
|
|
||||||
SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len)
|
SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len)
|
||||||
{
|
{
|
||||||
char *p = lj_buf_more(sb, len);
|
char *w = lj_buf_more(sb, len);
|
||||||
p = lj_buf_wmem(p, q, len);
|
w = lj_buf_wmem(w, q, len);
|
||||||
setsbufP(sb, p);
|
sb->w = w;
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LJ_HASJIT || LJ_HASFFI
|
||||||
|
static LJ_NOINLINE SBuf * LJ_FASTCALL lj_buf_putchar2(SBuf *sb, int c)
|
||||||
|
{
|
||||||
|
char *w = lj_buf_more2(sb, 1);
|
||||||
|
*w++ = (char)c;
|
||||||
|
sb->w = w;
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c)
|
SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c)
|
||||||
{
|
{
|
||||||
char *p = lj_buf_more(sb, 1);
|
char *w = sb->w;
|
||||||
*p++ = (char)c;
|
if (LJ_LIKELY(w < sb->e)) {
|
||||||
setsbufP(sb, p);
|
*w++ = (char)c;
|
||||||
return sb;
|
sb->w = w;
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
return lj_buf_putchar2(sb, c);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s)
|
SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s)
|
||||||
{
|
{
|
||||||
MSize len = s->len;
|
MSize len = s->len;
|
||||||
char *p = lj_buf_more(sb, len);
|
char *w = lj_buf_more(sb, len);
|
||||||
p = lj_buf_wmem(p, strdata(s), len);
|
w = lj_buf_wmem(w, strdata(s), len);
|
||||||
setsbufP(sb, p);
|
sb->w = w;
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,47 +172,47 @@ SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s)
|
|||||||
SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s)
|
SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s)
|
||||||
{
|
{
|
||||||
MSize len = s->len;
|
MSize len = s->len;
|
||||||
char *p = lj_buf_more(sb, len), *e = p+len;
|
char *w = lj_buf_more(sb, len), *e = w+len;
|
||||||
const char *q = strdata(s)+len-1;
|
const char *q = strdata(s)+len-1;
|
||||||
while (p < e)
|
while (w < e)
|
||||||
*p++ = *q--;
|
*w++ = *q--;
|
||||||
setsbufP(sb, p);
|
sb->w = w;
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s)
|
SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s)
|
||||||
{
|
{
|
||||||
MSize len = s->len;
|
MSize len = s->len;
|
||||||
char *p = lj_buf_more(sb, len), *e = p+len;
|
char *w = lj_buf_more(sb, len), *e = w+len;
|
||||||
const char *q = strdata(s);
|
const char *q = strdata(s);
|
||||||
for (; p < e; p++, q++) {
|
for (; w < e; w++, q++) {
|
||||||
uint32_t c = *(unsigned char *)q;
|
uint32_t c = *(unsigned char *)q;
|
||||||
#if LJ_TARGET_PPC
|
#if LJ_TARGET_PPC
|
||||||
*p = c + ((c >= 'A' && c <= 'Z') << 5);
|
*w = c + ((c >= 'A' && c <= 'Z') << 5);
|
||||||
#else
|
#else
|
||||||
if (c >= 'A' && c <= 'Z') c += 0x20;
|
if (c >= 'A' && c <= 'Z') c += 0x20;
|
||||||
*p = c;
|
*w = c;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
setsbufP(sb, p);
|
sb->w = w;
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s)
|
SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s)
|
||||||
{
|
{
|
||||||
MSize len = s->len;
|
MSize len = s->len;
|
||||||
char *p = lj_buf_more(sb, len), *e = p+len;
|
char *w = lj_buf_more(sb, len), *e = w+len;
|
||||||
const char *q = strdata(s);
|
const char *q = strdata(s);
|
||||||
for (; p < e; p++, q++) {
|
for (; w < e; w++, q++) {
|
||||||
uint32_t c = *(unsigned char *)q;
|
uint32_t c = *(unsigned char *)q;
|
||||||
#if LJ_TARGET_PPC
|
#if LJ_TARGET_PPC
|
||||||
*p = c - ((c >= 'a' && c <= 'z') << 5);
|
*w = c - ((c >= 'a' && c <= 'z') << 5);
|
||||||
#else
|
#else
|
||||||
if (c >= 'a' && c <= 'z') c -= 0x20;
|
if (c >= 'a' && c <= 'z') c -= 0x20;
|
||||||
*p = c;
|
*w = c;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
setsbufP(sb, p);
|
sb->w = w;
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,21 +221,21 @@ SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep)
|
|||||||
MSize len = s->len;
|
MSize len = s->len;
|
||||||
if (rep > 0 && len) {
|
if (rep > 0 && len) {
|
||||||
uint64_t tlen = (uint64_t)rep * len;
|
uint64_t tlen = (uint64_t)rep * len;
|
||||||
char *p;
|
char *w;
|
||||||
if (LJ_UNLIKELY(tlen > LJ_MAX_STR))
|
if (LJ_UNLIKELY(tlen > LJ_MAX_STR))
|
||||||
lj_err_mem(sbufL(sb));
|
lj_err_mem(sbufL(sb));
|
||||||
p = lj_buf_more(sb, (MSize)tlen);
|
w = lj_buf_more(sb, (MSize)tlen);
|
||||||
if (len == 1) { /* Optimize a common case. */
|
if (len == 1) { /* Optimize a common case. */
|
||||||
uint32_t c = strdata(s)[0];
|
uint32_t c = strdata(s)[0];
|
||||||
do { *p++ = c; } while (--rep > 0);
|
do { *w++ = c; } while (--rep > 0);
|
||||||
} else {
|
} else {
|
||||||
const char *e = strdata(s) + len;
|
const char *e = strdata(s) + len;
|
||||||
do {
|
do {
|
||||||
const char *q = strdata(s);
|
const char *q = strdata(s);
|
||||||
do { *p++ = *q++; } while (q < e);
|
do { *w++ = *q++; } while (q < e);
|
||||||
} while (--rep > 0);
|
} while (--rep > 0);
|
||||||
}
|
}
|
||||||
setsbufP(sb, p);
|
sb->w = w;
|
||||||
}
|
}
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
@@ -173,27 +246,27 @@ SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, int32_t i, int32_t e)
|
|||||||
if (i <= e) {
|
if (i <= e) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
cTValue *o = lj_tab_getint(t, i);
|
cTValue *o = lj_tab_getint(t, i);
|
||||||
char *p;
|
char *w;
|
||||||
if (!o) {
|
if (!o) {
|
||||||
badtype: /* Error: bad element type. */
|
badtype: /* Error: bad element type. */
|
||||||
setsbufP(sb, (void *)(intptr_t)i); /* Store failing index. */
|
sb->w = (char *)(intptr_t)i; /* Store failing index. */
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (tvisstr(o)) {
|
} else if (tvisstr(o)) {
|
||||||
MSize len = strV(o)->len;
|
MSize len = strV(o)->len;
|
||||||
p = lj_buf_wmem(lj_buf_more(sb, len + seplen), strVdata(o), len);
|
w = lj_buf_wmem(lj_buf_more(sb, len + seplen), strVdata(o), len);
|
||||||
} else if (tvisint(o)) {
|
} else if (tvisint(o)) {
|
||||||
p = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT+seplen), intV(o));
|
w = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT+seplen), intV(o));
|
||||||
} else if (tvisnum(o)) {
|
} else if (tvisnum(o)) {
|
||||||
p = lj_buf_more(lj_strfmt_putfnum(sb, STRFMT_G14, numV(o)), seplen);
|
w = lj_buf_more(lj_strfmt_putfnum(sb, STRFMT_G14, numV(o)), seplen);
|
||||||
} else {
|
} else {
|
||||||
goto badtype;
|
goto badtype;
|
||||||
}
|
}
|
||||||
if (i++ == e) {
|
if (i++ == e) {
|
||||||
setsbufP(sb, p);
|
sb->w = w;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (seplen) p = lj_buf_wmem(p, strdata(sep), seplen);
|
if (seplen) w = lj_buf_wmem(w, strdata(sep), seplen);
|
||||||
setsbufP(sb, p);
|
sb->w = w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sb;
|
return sb;
|
||||||
@@ -203,7 +276,7 @@ SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, int32_t i, int32_t e)
|
|||||||
|
|
||||||
GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb)
|
GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb)
|
||||||
{
|
{
|
||||||
return lj_str_new(sbufL(sb), sbufB(sb), sbuflen(sb));
|
return lj_str_new(sbufL(sb), sb->b, sbuflen(sb));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Concatenate two strings. */
|
/* Concatenate two strings. */
|
||||||
@@ -219,14 +292,14 @@ GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2)
|
|||||||
/* Read ULEB128 from buffer. */
|
/* Read ULEB128 from buffer. */
|
||||||
uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp)
|
uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp)
|
||||||
{
|
{
|
||||||
const uint8_t *p = (const uint8_t *)*pp;
|
const uint8_t *w = (const uint8_t *)*pp;
|
||||||
uint32_t v = *p++;
|
uint32_t v = *w++;
|
||||||
if (LJ_UNLIKELY(v >= 0x80)) {
|
if (LJ_UNLIKELY(v >= 0x80)) {
|
||||||
int sh = 0;
|
int sh = 0;
|
||||||
v &= 0x7f;
|
v &= 0x7f;
|
||||||
do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
|
do { v |= ((*w & 0x7f) << (sh += 7)); } while (*w++ >= 0x80);
|
||||||
}
|
}
|
||||||
*pp = (const char *)p;
|
*pp = (const char *)w;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+115
-20
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Buffer handling.
|
** Buffer handling.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_BUF_H
|
#ifndef _LJ_BUF_H
|
||||||
@@ -10,16 +10,60 @@
|
|||||||
#include "lj_gc.h"
|
#include "lj_gc.h"
|
||||||
#include "lj_str.h"
|
#include "lj_str.h"
|
||||||
|
|
||||||
/* Resizable string buffers. Struct definition in lj_obj.h. */
|
/* Resizable string buffers. */
|
||||||
#define sbufB(sb) (mref((sb)->b, char))
|
|
||||||
#define sbufP(sb) (mref((sb)->p, char))
|
/* The SBuf struct definition is in lj_obj.h:
|
||||||
#define sbufE(sb) (mref((sb)->e, char))
|
** char *w; Write pointer.
|
||||||
#define sbufL(sb) (mref((sb)->L, lua_State))
|
** char *e; End pointer.
|
||||||
#define sbufsz(sb) ((MSize)(sbufE((sb)) - sbufB((sb))))
|
** char *b; Base pointer.
|
||||||
#define sbuflen(sb) ((MSize)(sbufP((sb)) - sbufB((sb))))
|
** MRef L; lua_State, used for buffer resizing. Extension bits in 3 LSB.
|
||||||
#define sbufleft(sb) ((MSize)(sbufE((sb)) - sbufP((sb))))
|
*/
|
||||||
#define setsbufP(sb, q) (setmref((sb)->p, (q)))
|
|
||||||
#define setsbufL(sb, l) (setmref((sb)->L, (l)))
|
/* Extended string buffer. */
|
||||||
|
typedef struct SBufExt {
|
||||||
|
SBufHeader;
|
||||||
|
union {
|
||||||
|
GCRef cowref; /* Copy-on-write object reference. */
|
||||||
|
MRef bsb; /* Borrowed string buffer. */
|
||||||
|
};
|
||||||
|
char *r; /* Read pointer. */
|
||||||
|
GCRef dict_str; /* Serialization string dictionary table. */
|
||||||
|
GCRef dict_mt; /* Serialization metatable dictionary table. */
|
||||||
|
int depth; /* Remaining recursion depth. */
|
||||||
|
} SBufExt;
|
||||||
|
|
||||||
|
#define sbufsz(sb) ((MSize)((sb)->e - (sb)->b))
|
||||||
|
#define sbuflen(sb) ((MSize)((sb)->w - (sb)->b))
|
||||||
|
#define sbufleft(sb) ((MSize)((sb)->e - (sb)->w))
|
||||||
|
#define sbufxlen(sbx) ((MSize)((sbx)->w - (sbx)->r))
|
||||||
|
#define sbufxslack(sbx) ((MSize)((sbx)->r - (sbx)->b))
|
||||||
|
|
||||||
|
#define SBUF_MASK_FLAG (7)
|
||||||
|
#define SBUF_MASK_L (~(GCSize)SBUF_MASK_FLAG)
|
||||||
|
#define SBUF_FLAG_EXT 1 /* Extended string buffer. */
|
||||||
|
#define SBUF_FLAG_COW 2 /* Copy-on-write buffer. */
|
||||||
|
#define SBUF_FLAG_BORROW 4 /* Borrowed string buffer. */
|
||||||
|
|
||||||
|
#define sbufL(sb) \
|
||||||
|
((lua_State *)(void *)(uintptr_t)(mrefu((sb)->L) & SBUF_MASK_L))
|
||||||
|
#define setsbufL(sb, l) (setmref((sb)->L, (l)))
|
||||||
|
#define setsbufXL(sb, l, flag) \
|
||||||
|
(setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) + (flag)))
|
||||||
|
#define setsbufXL_(sb, l) \
|
||||||
|
(setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) | (mrefu((sb)->L) & SBUF_MASK_FLAG)))
|
||||||
|
|
||||||
|
#define sbufflag(sb) (mrefu((sb)->L))
|
||||||
|
#define sbufisext(sb) (sbufflag((sb)) & SBUF_FLAG_EXT)
|
||||||
|
#define sbufiscow(sb) (sbufflag((sb)) & SBUF_FLAG_COW)
|
||||||
|
#define sbufisborrow(sb) (sbufflag((sb)) & SBUF_FLAG_BORROW)
|
||||||
|
#define sbufiscoworborrow(sb) (sbufflag((sb)) & (SBUF_FLAG_COW|SBUF_FLAG_BORROW))
|
||||||
|
#define sbufX(sb) \
|
||||||
|
(lj_assertG_(G(sbufL(sb)), sbufisext(sb), "not an SBufExt"), (SBufExt *)(sb))
|
||||||
|
#define setsbufflag(sb, flag) (setmrefu((sb)->L, (flag)))
|
||||||
|
|
||||||
|
#define tvisbuf(o) \
|
||||||
|
(LJ_HASBUFFER && tvisudata(o) && udataV(o)->udtype == UDTYPE_BUFFER)
|
||||||
|
#define bufV(o) check_exp(tvisbuf(o), ((SBufExt *)uddata(udataV(o))))
|
||||||
|
|
||||||
/* Buffer management */
|
/* Buffer management */
|
||||||
LJ_FUNC char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz);
|
LJ_FUNC char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz);
|
||||||
@@ -30,12 +74,12 @@ LJ_FUNC char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz);
|
|||||||
static LJ_AINLINE void lj_buf_init(lua_State *L, SBuf *sb)
|
static LJ_AINLINE void lj_buf_init(lua_State *L, SBuf *sb)
|
||||||
{
|
{
|
||||||
setsbufL(sb, L);
|
setsbufL(sb, L);
|
||||||
setmref(sb->p, NULL); setmref(sb->e, NULL); setmref(sb->b, NULL);
|
sb->w = sb->e = sb->b = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LJ_AINLINE void lj_buf_reset(SBuf *sb)
|
static LJ_AINLINE void lj_buf_reset(SBuf *sb)
|
||||||
{
|
{
|
||||||
setmrefr(sb->p, sb->b);
|
sb->w = sb->b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L)
|
static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L)
|
||||||
@@ -48,26 +92,77 @@ static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L)
|
|||||||
|
|
||||||
static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb)
|
static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb)
|
||||||
{
|
{
|
||||||
lj_mem_free(g, sbufB(sb), sbufsz(sb));
|
lj_assertG(!sbufisext(sb), "bad free of SBufExt");
|
||||||
|
lj_mem_free(g, sb->b, sbufsz(sb));
|
||||||
}
|
}
|
||||||
|
|
||||||
static LJ_AINLINE char *lj_buf_need(SBuf *sb, MSize sz)
|
static LJ_AINLINE char *lj_buf_need(SBuf *sb, MSize sz)
|
||||||
{
|
{
|
||||||
if (LJ_UNLIKELY(sz > sbufsz(sb)))
|
if (LJ_UNLIKELY(sz > sbufsz(sb)))
|
||||||
return lj_buf_need2(sb, sz);
|
return lj_buf_need2(sb, sz);
|
||||||
return sbufB(sb);
|
return sb->b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LJ_AINLINE char *lj_buf_more(SBuf *sb, MSize sz)
|
static LJ_AINLINE char *lj_buf_more(SBuf *sb, MSize sz)
|
||||||
{
|
{
|
||||||
if (LJ_UNLIKELY(sz > sbufleft(sb)))
|
if (LJ_UNLIKELY(sz > sbufleft(sb)))
|
||||||
return lj_buf_more2(sb, sz);
|
return lj_buf_more2(sb, sz);
|
||||||
return sbufP(sb);
|
return sb->w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Extended buffer management */
|
||||||
|
static LJ_AINLINE void lj_bufx_init(lua_State *L, SBufExt *sbx)
|
||||||
|
{
|
||||||
|
memset(sbx, 0, sizeof(SBufExt));
|
||||||
|
setsbufXL(sbx, L, SBUF_FLAG_EXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static LJ_AINLINE void lj_bufx_set_borrow(lua_State *L, SBufExt *sbx, SBuf *sb)
|
||||||
|
{
|
||||||
|
setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_BORROW);
|
||||||
|
setmref(sbx->bsb, sb);
|
||||||
|
sbx->r = sbx->w = sbx->b = sb->b;
|
||||||
|
sbx->e = sb->e;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LJ_AINLINE void lj_bufx_set_cow(lua_State *L, SBufExt *sbx,
|
||||||
|
const char *p, MSize len)
|
||||||
|
{
|
||||||
|
setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_COW);
|
||||||
|
sbx->r = sbx->b = (char *)p;
|
||||||
|
sbx->w = sbx->e = (char *)p + len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LJ_AINLINE void lj_bufx_reset(SBufExt *sbx)
|
||||||
|
{
|
||||||
|
if (sbufiscow(sbx)) {
|
||||||
|
setmrefu(sbx->L, (mrefu(sbx->L) & ~(GCSize)SBUF_FLAG_COW));
|
||||||
|
setgcrefnull(sbx->cowref);
|
||||||
|
sbx->b = sbx->e = NULL;
|
||||||
|
}
|
||||||
|
sbx->r = sbx->w = sbx->b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static LJ_AINLINE void lj_bufx_free(lua_State *L, SBufExt *sbx)
|
||||||
|
{
|
||||||
|
if (!sbufiscoworborrow(sbx)) lj_mem_free(G(L), sbx->b, sbufsz(sbx));
|
||||||
|
setsbufXL(sbx, L, SBUF_FLAG_EXT);
|
||||||
|
setgcrefnull(sbx->cowref);
|
||||||
|
sbx->r = sbx->w = sbx->b = sbx->e = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LJ_HASBUFFER && LJ_HASJIT
|
||||||
|
LJ_FUNC void lj_bufx_set(SBufExt *sbx, const char *p, MSize len, GCobj *o);
|
||||||
|
#if LJ_HASFFI
|
||||||
|
LJ_FUNC MSize LJ_FASTCALL lj_bufx_more(SBufExt *sbx, MSize sz);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Low-level buffer put operations */
|
/* Low-level buffer put operations */
|
||||||
LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len);
|
LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len);
|
||||||
|
#if LJ_HASJIT || LJ_HASFFI
|
||||||
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c);
|
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c);
|
||||||
|
#endif
|
||||||
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s);
|
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s);
|
||||||
|
|
||||||
static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len)
|
static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len)
|
||||||
@@ -77,9 +172,9 @@ static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len)
|
|||||||
|
|
||||||
static LJ_AINLINE void lj_buf_putb(SBuf *sb, int c)
|
static LJ_AINLINE void lj_buf_putb(SBuf *sb, int c)
|
||||||
{
|
{
|
||||||
char *p = lj_buf_more(sb, 1);
|
char *w = lj_buf_more(sb, 1);
|
||||||
*p++ = (char)c;
|
*w++ = (char)c;
|
||||||
setsbufP(sb, p);
|
sb->w = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* High-level buffer put operations */
|
/* High-level buffer put operations */
|
||||||
@@ -97,7 +192,7 @@ LJ_FUNC uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp);
|
|||||||
|
|
||||||
static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb)
|
static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb)
|
||||||
{
|
{
|
||||||
return lj_str_new(L, sbufB(sb), sbuflen(sb));
|
return lj_str_new(L, sb->b, sbuflen(sb));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** C data arithmetic.
|
** C data arithmetic.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lj_obj.h"
|
#include "lj_obj.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** C data arithmetic.
|
** C data arithmetic.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LJ_CARITH_H
|
#ifndef _LJ_CARITH_H
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** FFI C call handling.
|
** FFI C call handling.
|
||||||
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h
|
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "lj_obj.h"
|
#include "lj_obj.h"
|
||||||
@@ -334,7 +334,7 @@
|
|||||||
isfp = sz == 2*sizeof(float) ? 2 : 1;
|
isfp = sz == 2*sizeof(float) ? 2 : 1;
|
||||||
|
|
||||||
#define CCALL_HANDLE_REGARG \
|
#define CCALL_HANDLE_REGARG \
|
||||||
if (LJ_TARGET_IOS && isva) { \
|
if (LJ_TARGET_OSX && isva) { \
|
||||||
/* IOS: All variadic arguments are on the stack. */ \
|
/* IOS: All variadic arguments are on the stack. */ \
|
||||||
} else if (isfp) { /* Try to pass argument in FPRs. */ \
|
} else if (isfp) { /* Try to pass argument in FPRs. */ \
|
||||||
int n2 = ctype_isvector(d->info) ? 1 : \
|
int n2 = ctype_isvector(d->info) ? 1 : \
|
||||||
@@ -345,10 +345,10 @@
|
|||||||
goto done; \
|
goto done; \
|
||||||
} else { \
|
} else { \
|
||||||
nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \
|
nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \
|
||||||
if (LJ_TARGET_IOS && d->size < 8) goto err_nyi; \
|
if (LJ_TARGET_OSX && d->size < 8) goto err_nyi; \
|
||||||
} \
|
} \
|
||||||
} else { /* Try to pass argument in GPRs. */ \
|
} else { /* Try to pass argument in GPRs. */ \
|
||||||
if (!LJ_TARGET_IOS && (d->info & CTF_ALIGN) > CTALIGN_PTR) \
|
if (!LJ_TARGET_OSX && (d->info & CTF_ALIGN) > CTALIGN_PTR) \
|
||||||
ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \
|
ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \
|
||||||
if (ngpr + n <= maxgpr) { \
|
if (ngpr + n <= maxgpr) { \
|
||||||
dp = &cc->gpr[ngpr]; \
|
dp = &cc->gpr[ngpr]; \
|
||||||
@@ -356,7 +356,7 @@
|
|||||||
goto done; \
|
goto done; \
|
||||||
} else { \
|
} else { \
|
||||||
ngpr = maxgpr; /* Prevent reordering. */ \
|
ngpr = maxgpr; /* Prevent reordering. */ \
|
||||||
if (LJ_TARGET_IOS && d->size < 8) goto err_nyi; \
|
if (LJ_TARGET_OSX && d->size < 8) goto err_nyi; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user