mirror of https://github.com/odrling/Aegisub
Upgrade LuaJIT to 2.1.0-beta3
This commit is contained in:
parent
3a50ba0386
commit
52032dc14b
|
@ -7,7 +7,7 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
|||
|
||||
include_directories("build")
|
||||
include_directories("libaegisub/include")
|
||||
include_directories("vendor/luajit/include")
|
||||
include_directories("vendor/luajit/src")
|
||||
|
||||
add_library(libaegisub STATIC
|
||||
libaegisub/common/parser.cpp
|
||||
|
@ -202,11 +202,23 @@ add_custom_command(
|
|||
)
|
||||
|
||||
add_library(luajit STATIC
|
||||
vendor/luajit/src/lib_base.c
|
||||
vendor/luajit/src/lib_math.c
|
||||
vendor/luajit/src/lib_bit.c
|
||||
vendor/luajit/src/lib_string.c
|
||||
vendor/luajit/src/lib_table.c
|
||||
vendor/luajit/src/lib_io.c
|
||||
vendor/luajit/src/lib_os.c
|
||||
vendor/luajit/src/lib_package.c
|
||||
vendor/luajit/src/lib_debug.c
|
||||
vendor/luajit/src/lib_jit.c
|
||||
vendor/luajit/src/lib_ffi.c
|
||||
vendor/luajit/src/lj_gc.c
|
||||
vendor/luajit/src/lj_err.c
|
||||
vendor/luajit/src/lj_char.c
|
||||
vendor/luajit/src/lj_bc.c
|
||||
vendor/luajit/src/lj_obj.c
|
||||
vendor/luajit/src/lj_buf.c
|
||||
vendor/luajit/src/lj_str.c
|
||||
vendor/luajit/src/lj_tab.c
|
||||
vendor/luajit/src/lj_func.c
|
||||
|
@ -218,7 +230,10 @@ add_library(luajit STATIC
|
|||
vendor/luajit/src/lj_vmevent.c
|
||||
vendor/luajit/src/lj_vmmath.c
|
||||
vendor/luajit/src/lj_strscan.c
|
||||
vendor/luajit/src/lj_strfmt.c
|
||||
vendor/luajit/src/lj_strfmt_num.c
|
||||
vendor/luajit/src/lj_api.c
|
||||
vendor/luajit/src/lj_profile.c
|
||||
vendor/luajit/src/lj_lex.c
|
||||
vendor/luajit/src/lj_parse.c
|
||||
vendor/luajit/src/lj_bcread.c
|
||||
|
@ -251,17 +266,6 @@ add_library(luajit STATIC
|
|||
vendor/luajit/src/lj_lib.c
|
||||
vendor/luajit/src/lj_alloc.c
|
||||
vendor/luajit/src/lib_aux.c
|
||||
vendor/luajit/src/lib_base.c
|
||||
vendor/luajit/src/lib_math.c
|
||||
vendor/luajit/src/lib_bit.c
|
||||
vendor/luajit/src/lib_string.c
|
||||
vendor/luajit/src/lib_table.c
|
||||
vendor/luajit/src/lib_io.c
|
||||
vendor/luajit/src/lib_os.c
|
||||
vendor/luajit/src/lib_package.c
|
||||
vendor/luajit/src/lib_debug.c
|
||||
vendor/luajit/src/lib_jit.c
|
||||
vendor/luajit/src/lib_ffi.c
|
||||
vendor/luajit/src/lib_init.c
|
||||
|
||||
vendor/luajit/src/gen/lj_ffdef.h
|
||||
|
|
|
@ -104,10 +104,6 @@ LIBS_PORTAUDIO = @PORTAUDIO_LIBS@
|
|||
LIBS_PTHREAD = @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
|
||||
LIBS_UCHARDET = @UCHARDET_LIBS@
|
||||
|
||||
ifeq (yes, $(BUILD_DARWIN))
|
||||
LIBS_LUA = $(TOP)vendor/luajit/src/libluajit-aegisub.so
|
||||
endif
|
||||
|
||||
FONTCONFIG_CONF_DIR = @FONTCONFIG_CONF_DIR@
|
||||
|
||||
#####################
|
||||
|
|
|
@ -5,8 +5,8 @@ COMMANDS := all install clean distclean test depclean osx-bundle osx-dmg test-au
|
|||
|
||||
# Would be nice to move this somewhere else (Makefile.inc?)
|
||||
ifeq (yes, $(BUILD_DARWIN))
|
||||
CFLAGS += -mmacosx-version-min=10.8 -gfull
|
||||
CXXFLAGS += -mmacosx-version-min=10.8 -gfull
|
||||
CFLAGS += -mmacosx-version-min=10.8 -gfull -DLUAJIT_ENABLE_GC64
|
||||
CXXFLAGS += -mmacosx-version-min=10.8 -gfull -DLUAJIT_ENABLE_GC64
|
||||
LDFLAGS += -mmacosx-version-min=10.8 -Wl,-dead_strip
|
||||
LIB_SHARED_LINK = $(LIB_SHARED_LINK_OSX)
|
||||
endif
|
||||
|
|
|
@ -53,7 +53,7 @@ int main(int argc, char **argv) {
|
|||
agi::log::log = new agi::log::LogSink;
|
||||
|
||||
// Init lua state
|
||||
lua_State *L = lua_open();
|
||||
lua_State *L = luaL_newstate();
|
||||
if (!L) {
|
||||
fprintf(stderr, "Failed to create Lua state\n");
|
||||
return 1;
|
||||
|
|
|
@ -431,7 +431,7 @@ AS_IF([test x$with_system_luajit != xno], [
|
|||
])
|
||||
|
||||
AS_IF([test $with_system_luajit = no],
|
||||
[AC_SUBST([LUAJIT_CFLAGS], ['-I$(TOP)vendor/luajit/include'])
|
||||
[AC_SUBST([LUAJIT_CFLAGS], ['-I$(TOP)vendor/luajit/src'])
|
||||
AC_SUBST([LUAJIT_LIBS], ['$(TOP)vendor/luajit/src/libluajit.a'])])
|
||||
|
||||
# We also need a Lua binary to run part of the build system
|
||||
|
|
|
@ -54,7 +54,7 @@ static int l_load(lua_State * L)
|
|||
}
|
||||
|
||||
/* luabins Lua module API */
|
||||
static const struct luaL_reg R[] =
|
||||
static const struct luaL_Reg R[] =
|
||||
{
|
||||
{ "save", l_save },
|
||||
{ "load", l_load },
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
*.[oa]
|
||||
*.so
|
||||
*.obj
|
||||
*.lib
|
||||
*.exp
|
||||
*.dll
|
||||
*.exe
|
||||
*.manifest
|
||||
*.dmp
|
||||
*.swp
|
||||
.tags
|
|
@ -1,7 +1,7 @@
|
|||
===============================================================================
|
||||
LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
|
||||
|
||||
Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
README for LuaJIT 2.0.4
|
||||
-----------------------
|
||||
README for LuaJIT 2.1.0-beta3
|
||||
-----------------------------
|
||||
|
||||
LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.
|
||||
|
||||
Project Homepage: http://luajit.org/
|
||||
|
||||
LuaJIT is Copyright (C) 2005-2015 Mike Pall.
|
||||
LuaJIT is Copyright (C) 2005-2017 Mike Pall.
|
||||
LuaJIT is free software, released under the MIT license.
|
||||
See full Copyright Notice in the COPYRIGHT file or in luajit.h.
|
||||
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
/* Copyright (C) 2004-2017 Mike Pall.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
body {
|
||||
font-family: serif;
|
||||
font-size: 11pt;
|
||||
margin: 0 3em;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
a:link, a:visited, a:hover, a:active {
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
color: #0000ff;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
margin: 0.5em 0;
|
||||
padding: 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 200%;
|
||||
}
|
||||
h2 {
|
||||
font-size: 150%;
|
||||
}
|
||||
h3 {
|
||||
font-size: 125%;
|
||||
}
|
||||
p {
|
||||
margin: 0 0 0.5em 0;
|
||||
padding: 0;
|
||||
}
|
||||
ul, ol {
|
||||
margin: 0.5em 0;
|
||||
padding: 0 0 0 2em;
|
||||
}
|
||||
ul {
|
||||
list-style: outside square;
|
||||
}
|
||||
ol {
|
||||
list-style: outside decimal;
|
||||
}
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
dl {
|
||||
margin: 1em 0;
|
||||
padding: 1em;
|
||||
border: 1px solid black;
|
||||
}
|
||||
dt {
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
dt sup {
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
}
|
||||
dd {
|
||||
margin: 0.5em 0 0 2em;
|
||||
padding: 0;
|
||||
}
|
||||
table {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
margin: 1em 0;
|
||||
padding: 0;
|
||||
border: 1px solid black;
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
tr {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
td {
|
||||
text-align: left;
|
||||
margin: 0;
|
||||
padding: 0.2em 0.5em;
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
tr.separate td {
|
||||
border-top: double;
|
||||
}
|
||||
tt, pre, code, kbd, samp {
|
||||
font-family: monospace;
|
||||
font-size: 75%;
|
||||
}
|
||||
kbd {
|
||||
font-weight: bolder;
|
||||
}
|
||||
blockquote, pre {
|
||||
margin: 1em 2em;
|
||||
padding: 0;
|
||||
}
|
||||
img {
|
||||
border: none;
|
||||
vertical-align: baseline;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
img.left {
|
||||
float: left;
|
||||
margin: 0.5em 1em 0.5em 0;
|
||||
}
|
||||
img.right {
|
||||
float: right;
|
||||
margin: 0.5em 0 0.5em 1em;
|
||||
}
|
||||
.flush {
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
.hide, .noprint, #nav {
|
||||
display: none !important;
|
||||
}
|
||||
.pagebreak {
|
||||
page-break-before: always;
|
||||
}
|
||||
#site {
|
||||
text-align: right;
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
margin: 0 1em;
|
||||
border-bottom: 1pt solid black;
|
||||
}
|
||||
#site a {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
#site a:link, #site a:visited {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
background: transparent;
|
||||
color: #ffffff;
|
||||
}
|
||||
#logo {
|
||||
color: #ff8000;
|
||||
}
|
||||
#head {
|
||||
clear: both;
|
||||
margin: 0 1em;
|
||||
}
|
||||
#main {
|
||||
line-height: 1.3;
|
||||
text-align: justify;
|
||||
margin: 1em;
|
||||
}
|
||||
#foot {
|
||||
clear: both;
|
||||
font-size: 80%;
|
||||
text-align: center;
|
||||
margin: 0 1.25em;
|
||||
padding: 0.5em 0 0 0;
|
||||
border-top: 1pt solid black;
|
||||
page-break-before: avoid;
|
||||
page-break-after: avoid;
|
||||
}
|
|
@ -0,0 +1,325 @@
|
|||
/* Copyright (C) 2004-2017 Mike Pall.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/* colorscheme:
|
||||
*
|
||||
* site | head #4162bf/white | #6078bf/#e6ecff
|
||||
* ------+------ ----------------+-------------------
|
||||
* nav | main #bfcfff | #e6ecff/black
|
||||
*
|
||||
* nav: hiback loback #c5d5ff #b9c9f9
|
||||
* hiborder loborder #e6ecff #97a7d7
|
||||
* link hover #2142bf #ff0000
|
||||
*
|
||||
* link: link visited hover #2142bf #8122bf #ff0000
|
||||
*
|
||||
* main: boxback boxborder #f0f4ff #bfcfff
|
||||
*/
|
||||
body {
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
font-size: 10pt;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: #e0e0e0;
|
||||
color: #000000;
|
||||
}
|
||||
a:link {
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
color: #2142bf;
|
||||
}
|
||||
a:visited {
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
color: #8122bf;
|
||||
}
|
||||
a:hover, a:active {
|
||||
text-decoration: underline;
|
||||
background: transparent;
|
||||
color: #ff0000;
|
||||
}
|
||||
h1, h2, h3 {
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
margin: 0.5em 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
}
|
||||
h1 {
|
||||
font-size: 200%;
|
||||
line-height: 3em; /* really 6em relative to body, match #site span */
|
||||
margin: 0;
|
||||
}
|
||||
h2 {
|
||||
font-size: 150%;
|
||||
color: #606060;
|
||||
}
|
||||
h3 {
|
||||
font-size: 125%;
|
||||
color: #404040;
|
||||
}
|
||||
p {
|
||||
max-width: 600px;
|
||||
margin: 0 0 0.5em 0;
|
||||
padding: 0;
|
||||
}
|
||||
b {
|
||||
color: #404040;
|
||||
}
|
||||
ul, ol {
|
||||
max-width: 600px;
|
||||
margin: 0.5em 0;
|
||||
padding: 0 0 0 2em;
|
||||
}
|
||||
ul {
|
||||
list-style: outside square;
|
||||
}
|
||||
ol {
|
||||
list-style: outside decimal;
|
||||
}
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
dl {
|
||||
max-width: 600px;
|
||||
margin: 1em 0;
|
||||
padding: 1em;
|
||||
border: 1px solid #bfcfff;
|
||||
background: #f0f4ff;
|
||||
}
|
||||
dt {
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
dt sup {
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
color: #808080;
|
||||
}
|
||||
dt a:visited {
|
||||
text-decoration: none;
|
||||
color: #2142bf;
|
||||
}
|
||||
dt a:hover, dt a:active {
|
||||
text-decoration: none;
|
||||
color: #ff0000;
|
||||
}
|
||||
dd {
|
||||
margin: 0.5em 0 0 2em;
|
||||
padding: 0;
|
||||
}
|
||||
div.tablewrap { /* for IE *sigh* */
|
||||
max-width: 600px;
|
||||
}
|
||||
table {
|
||||
table-layout: fixed;
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
max-width: 600px;
|
||||
width: 100%;
|
||||
margin: 1em 0;
|
||||
padding: 0;
|
||||
border: 1px solid #bfcfff;
|
||||
}
|
||||
tr {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
tr.odd {
|
||||
background: #f0f4ff;
|
||||
}
|
||||
tr.separate td {
|
||||
border-top: 1px solid #bfcfff;
|
||||
}
|
||||
td {
|
||||
text-align: left;
|
||||
margin: 0;
|
||||
padding: 0.2em 0.5em;
|
||||
border: none;
|
||||
}
|
||||
tt, code, kbd, samp {
|
||||
font-family: Courier New, Courier, monospace;
|
||||
line-height: 1.2;
|
||||
font-size: 110%;
|
||||
}
|
||||
kbd {
|
||||
font-weight: bolder;
|
||||
}
|
||||
blockquote, pre {
|
||||
max-width: 600px;
|
||||
margin: 1em 2em;
|
||||
padding: 0;
|
||||
}
|
||||
pre {
|
||||
line-height: 1.1;
|
||||
}
|
||||
pre.code {
|
||||
line-height: 1.4;
|
||||
margin: 0.5em 0 1em 0.5em;
|
||||
padding: 0.5em 1em;
|
||||
border: 1px solid #bfcfff;
|
||||
background: #f0f4ff;
|
||||
}
|
||||
pre.mark {
|
||||
padding-left: 2em;
|
||||
}
|
||||
span.codemark {
|
||||
position:absolute;
|
||||
left: 16em;
|
||||
color: #4040c0;
|
||||
}
|
||||
span.mark {
|
||||
color: #4040c0;
|
||||
font-family: Courier New, Courier, monospace;
|
||||
line-height: 1.1;
|
||||
}
|
||||
img {
|
||||
border: none;
|
||||
vertical-align: baseline;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
img.left {
|
||||
float: left;
|
||||
margin: 0.5em 1em 0.5em 0;
|
||||
}
|
||||
img.right {
|
||||
float: right;
|
||||
margin: 0.5em 0 0.5em 1em;
|
||||
}
|
||||
.indent {
|
||||
padding-left: 1em;
|
||||
}
|
||||
.flush {
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
.hide, .noscreen {
|
||||
display: none !important;
|
||||
}
|
||||
.ext {
|
||||
color: #ff8000;
|
||||
}
|
||||
.new {
|
||||
font-size: 6pt;
|
||||
vertical-align: middle;
|
||||
background: #ff8000;
|
||||
color: #ffffff;
|
||||
}
|
||||
#site {
|
||||
clear: both;
|
||||
float: left;
|
||||
width: 13em;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
color: #ffffff;
|
||||
}
|
||||
#site a {
|
||||
font-size: 200%;
|
||||
}
|
||||
#site a:link, #site a:visited {
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
background: transparent;
|
||||
color: #ffffff;
|
||||
}
|
||||
#site span {
|
||||
line-height: 3em; /* really 6em relative to body, match h1 */
|
||||
}
|
||||
#logo {
|
||||
color: #ffb380;
|
||||
}
|
||||
#head {
|
||||
margin: 0;
|
||||
padding: 0 0 0 2em;
|
||||
border-left: solid 13em #4162bf;
|
||||
border-right: solid 3em #6078bf;
|
||||
background: #6078bf;
|
||||
color: #e6ecff;
|
||||
}
|
||||
#nav {
|
||||
clear: both;
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
line-height: 1.5;
|
||||
width: 13em;
|
||||
padding-top: 1em;
|
||||
background: transparent;
|
||||
}
|
||||
#nav ul {
|
||||
list-style: none outside;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#nav li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#nav a {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
padding: 2px 1em;
|
||||
border-top: 1px solid transparent;
|
||||
border-bottom: 1px solid transparent;
|
||||
background: transparent;
|
||||
color: #2142bf;
|
||||
}
|
||||
#nav a:hover, #nav a:active {
|
||||
text-decoration: none;
|
||||
border-top: 1px solid #97a7d7;
|
||||
border-bottom: 1px solid #e6ecff;
|
||||
background: #b9c9f9;
|
||||
color: #ff0000;
|
||||
}
|
||||
#nav a.current, #nav a.current:hover, #nav a.current:active {
|
||||
border-top: 1px solid #e6ecff;
|
||||
border-bottom: 1px solid #97a7d7;
|
||||
background: #c5d5ff;
|
||||
color: #2142bf;
|
||||
}
|
||||
#nav ul ul a {
|
||||
padding: 0 1em 0 1.7em;
|
||||
}
|
||||
#nav ul ul ul a {
|
||||
padding: 0 0.5em 0 2.4em;
|
||||
}
|
||||
#main {
|
||||
line-height: 1.5;
|
||||
text-align: left;
|
||||
margin: 0;
|
||||
padding: 1em 2em;
|
||||
border-left: solid 13em #bfcfff;
|
||||
border-right: solid 3em #e6ecff;
|
||||
background: #e6ecff;
|
||||
}
|
||||
#foot {
|
||||
clear: both;
|
||||
font-size: 80%;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: 0.5em;
|
||||
background: #6078bf;
|
||||
color: #ffffff;
|
||||
}
|
||||
#foot a:link, #foot a:visited {
|
||||
text-decoration: underline;
|
||||
background: transparent;
|
||||
color: #ffffff;
|
||||
}
|
||||
#foot a:hover, #foot a:active {
|
||||
text-decoration: underline;
|
||||
background: transparent;
|
||||
color: #bfcfff;
|
||||
}
|
|
@ -0,0 +1,883 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>LuaJIT Change History</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
div.major { max-width: 600px; padding: 1em; margin: 1em 0 1em 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>LuaJIT Change History</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 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>
|
||||
<ul><li>
|
||||
<a class="current" href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
This is a list of changes between the released versions of LuaJIT.<br>
|
||||
The current <span style="color: #0000c0;">stable version</span> is <strong>LuaJIT 2.0.5</strong>.<br>
|
||||
</p>
|
||||
<p>
|
||||
Please check the
|
||||
<a href="http://luajit.org/changes.html"><span class="ext">»</span> Online Change History</a>
|
||||
to see whether newer versions are available.
|
||||
</p>
|
||||
|
||||
<div class="major" style="background: #d0d0ff;">
|
||||
<h2 id="LuaJIT-2.1.0-beta3">LuaJIT 2.1.0-beta3 — 2017-05-01</h2>
|
||||
<ul>
|
||||
<li>Rewrite memory block allocator.</li>
|
||||
<li>Add various extension from Lua 5.2/5.3.</li>
|
||||
<li>Remove old Lua 5.0 compatibility defines.</li>
|
||||
<li>Set arg table before evaluating <tt>LUA_INIT</tt> and <tt>-e</tt> chunks.</li>
|
||||
<li>Fix FOLD rules for <tt>math.abs()</tt> and FP negation.</li>
|
||||
<li>Fix soft-float <tt>math.abs()</tt> and negation.</li>
|
||||
<li>Fix formatting of some small denormals at low precision.</li>
|
||||
<li>LJ_GC64: Add JIT compiler support.</li>
|
||||
<li>x64/LJ_GC64: Add JIT compiler backend.</li>
|
||||
<li>x86/x64: Generate BMI2 shifts and rotates, if available.</li>
|
||||
<li>Windows/x86: Add full exception interoperability.</li>
|
||||
<li>ARM64: Add big-endian support.</li>
|
||||
<li>ARM64: Add JIT compiler backend.</li>
|
||||
<li>MIPS: Fix <tt>TSETR</tt> barrier.</li>
|
||||
<li>MIPS: Support MIPS16 interlinking.</li>
|
||||
<li>MIPS soft-float: Fix code generation for <tt>HREF</tt>.</li>
|
||||
<li>MIPS64: Add MIPS64 hard-float JIT compiler backend.</li>
|
||||
<li>MIPS64: Add MIPS64 hard-float/soft-float support to interpreter.</li>
|
||||
<li>FFI: Compile bitfield loads/stores.</li>
|
||||
<li>Various fixes common with the 2.0 branch.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.1.0-beta2">LuaJIT 2.1.0-beta2 — 2016-03-03</h2>
|
||||
<ul>
|
||||
<li>Enable trace stitching.</li>
|
||||
<li>Use internal implementation for converting FP numbers to strings.</li>
|
||||
<li>Parse Unicode escape <tt>'\u{XX...}'</tt> in string literals.</li>
|
||||
<li>Add MIPS soft-float support.</li>
|
||||
<li>Switch MIPS port to dual-number mode.</li>
|
||||
<li>x86/x64: Add support for AES-NI, AVX and AVX2 to DynASM.</li>
|
||||
<li>FFI: Add <tt>ssize_t</tt> declaration.</li>
|
||||
<li>FFI: Parse <tt>#line NN</tt> and <tt>#NN</tt>.</li>
|
||||
<li>Various minor fixes.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.1.0-beta1">LuaJIT 2.1.0-beta1 — 2015-08-25</h2>
|
||||
<p>
|
||||
This is a brief summary of the major changes in LuaJIT 2.1 compared to 2.0.
|
||||
Please take a look at the commit history for more details.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Changes to the VM core:
|
||||
<ul>
|
||||
<li>Add low-overhead profiler (<tt>-jp</tt>).</li>
|
||||
<li>Add <tt>LJ_GC64</tt> mode: 64 bit GC object references (really: 47 bit). Interpreter-only for now.</li>
|
||||
<li>Add <tt>LJ_FR2</tt> mode: Two-slot frame info. Required by <tt>LJ_GC64</tt> mode.</li>
|
||||
<li>Add <tt>table.new()</tt> and <tt>table.clear()</tt>.</li>
|
||||
<li>Parse binary number literals (<tt>0bxxx</tt>).</li>
|
||||
</ul></li>
|
||||
<li>Improvements to the JIT compiler:
|
||||
<ul>
|
||||
<li>Add trace stitching (disabled for now).</li>
|
||||
<li>Compile various builtins: <tt>string.char()</tt>, <tt>string.reverse()</tt>, <tt>string.lower()</tt>, <tt>string.upper()</tt>, <tt>string.rep()</tt>, <tt>string.format()</tt>, <tt>table.concat()</tt>, <tt>bit.tohex()</tt>, <tt>getfenv(0)</tt>, <tt>debug.getmetatable()</tt>.</li>
|
||||
<li>Compile <tt>string.find()</tt> for fixed string searches (no patterns).</li>
|
||||
<li>Compile <tt>BC_TSETM</tt>, e.g. <tt>{1,2,3,f()}</tt>.</li>
|
||||
<li>Compile string concatenations (<tt>BC_CAT</tt>).</li>
|
||||
<li>Compile <tt>__concat</tt> metamethod.</li>
|
||||
<li>Various minor optimizations.</li>
|
||||
</ul></li>
|
||||
<li>Internal Changes:
|
||||
<ul>
|
||||
<li>Add support for embedding LuaJIT bytecode for builtins.</li>
|
||||
<li>Replace various builtins with embedded bytecode.</li>
|
||||
<li>Refactor string buffers and string formatting.</li>
|
||||
<li>Remove obsolete non-truncating number to integer conversions.</li>
|
||||
</ul></li>
|
||||
<li>Ports:
|
||||
<ul>
|
||||
<li>Add Xbox One port (<tt>LJ_GC64</tt> mode).</li>
|
||||
<li>ARM64: Add port of the interpreter (<tt>LJ_GC64</tt> mode).</li>
|
||||
<li>x64: Add separate port of the interpreter to <tt>LJ_GC64</tt> mode.</li>
|
||||
<li>x86/x64: Drop internal x87 math functions. Use libm functions.</li>
|
||||
<li>x86: Remove x87 support from interpreter. SSE2 is mandatory now.</li>
|
||||
<li>PPC/e500: Drop support for this architecture.</li>
|
||||
</ul></li>
|
||||
<li>FFI library:
|
||||
<ul>
|
||||
<li>FFI: Add 64 bit bitwise operations.</li>
|
||||
<li>FFI: Compile VLA/VLS and large cdata allocations with default initialization.</li>
|
||||
<li>FFI: Compile conversions from functions to function pointers.</li>
|
||||
<li>FFI: Compile lightuserdata to <tt>void *</tt> conversion.</li>
|
||||
<li>FFI: Compile <tt>ffi.gc(cdata, nil)</tt>, too.</li>
|
||||
<li>FFI: Add <tt>ffi.typeinfo()</tt>.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="major" style="background: #ffffd0;">
|
||||
<h2 id="LuaJIT-2.0.5">LuaJIT 2.0.5 — 2017-05-01</h2>
|
||||
<ul>
|
||||
<li>Add workaround for MSVC 2015 stdio changes.</li>
|
||||
<li>Limit mcode alloc probing, depending on the available pool size.</li>
|
||||
<li>Fix overly restrictive range calculation in mcode allocation.</li>
|
||||
<li>Fix out-of-scope goto handling in parser.</li>
|
||||
<li>Remove internal <tt>__mode = "K"</tt> and replace with safe check.</li>
|
||||
<li>Add "proto" field to <tt>jit.util.funcinfo()</tt>.</li>
|
||||
<li>Fix GC step size calculation.</li>
|
||||
<li>Initialize <tt>uv->immutable</tt> for upvalues of loaded chunks.</li>
|
||||
<li>Fix for cdata vs. non-cdata arithmetics/comparisons.</li>
|
||||
<li>Drop leftover regs in 'for' iterator assignment, too.</li>
|
||||
<li>Fix PHI remarking in SINK pass.</li>
|
||||
<li>Don't try to record outermost <tt>pcall()</tt> return to lower frame.</li>
|
||||
<li>Add guard for obscure aliasing between open upvalues and SSA slots.</li>
|
||||
<li>Remove assumption that <tt>lj_math_random_step()</tt> doesn't clobber FPRs.</li>
|
||||
<li>Fix handling of non-numeric strings in arithmetic coercions.</li>
|
||||
<li>Fix recording of <tt>select(n, ...)</tt> with off-trace varargs</li>
|
||||
<li>Fix install for cross-builds.</li>
|
||||
<li>Don't allocate unused 2nd result register in JIT compiler backend.</li>
|
||||
<li>Drop marks from replayed instructions when sinking.</li>
|
||||
<li>Fix unsinking check.</li>
|
||||
<li>Properly handle OOM in <tt>trace_save()</tt>.</li>
|
||||
<li>Limit number of arguments given to <tt>io.lines()</tt> and <tt>fp:lines()</tt>.</li>
|
||||
<li>Fix narrowing of <tt>TOBIT</tt>.</li>
|
||||
<li>OSX: Fix build with recent XCode.</li>
|
||||
<li>x86/x64: Don't spill an explicit <tt>REF_BASE</tt> in the IR.</li>
|
||||
<li>x86/x64: Fix instruction length decoder.</li>
|
||||
<li>x86/x64: Search for exit jumps with instruction length decoder.</li>
|
||||
<li>ARM: Fix <tt>BLX</tt> encoding for Thumb interworking calls.</li>
|
||||
<li>MIPS: Don't use <tt>RID_GP</tt> as a scratch register.</li>
|
||||
<li>MIPS: Fix emitted code for U32 to float conversion.</li>
|
||||
<li>MIPS: Backport workaround for compact unwind tables.</li>
|
||||
<li>MIPS: Fix cross-endian jit.bcsave.</li>
|
||||
<li>MIPS: Fix <tt>BC_ISNEXT</tt> fallback path.</li>
|
||||
<li>MIPS: Fix use of ffgccheck delay slots in interpreter.</li>
|
||||
<li>FFI: Fix FOLD rules for <tt>int64_t</tt> comparisons.</li>
|
||||
<li>FFI: Fix SPLIT pass for <tt>CONV i64.u64</tt>.</li>
|
||||
<li>FFI: Fix <tt>ipairs()</tt> recording.</li>
|
||||
<li>FFI: Don't propagate qualifiers into subtypes of complex.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.4">LuaJIT 2.0.4 — 2015-05-14</h2>
|
||||
<ul>
|
||||
<li>Fix stack check in narrowing optimization.</li>
|
||||
<li>Fix Lua/C API typecheck error for special indexes.</li>
|
||||
<li>Fix string to number conversion.</li>
|
||||
<li>Fix lexer error for chunks without tokens.</li>
|
||||
<li>Don't compile <tt>IR_RETF</tt> after <tt>CALLT</tt> to ff with-side effects.</li>
|
||||
<li>Fix <tt>BC_UCLO</tt>/<tt>BC_JMP</tt> join optimization in Lua parser.</li>
|
||||
<li>Fix corner case in string to number conversion.</li>
|
||||
<li>Gracefully handle <tt>lua_error()</tt> for a suspended coroutine.</li>
|
||||
<li>Avoid error messages when building with Clang.</li>
|
||||
<li>Fix snapshot #0 handling for traces with a stack check on entry.</li>
|
||||
<li>Fix fused constant loads under high register pressure.</li>
|
||||
<li>Invalidate backpropagation cache after DCE.</li>
|
||||
<li>Fix ABC elimination.</li>
|
||||
<li>Fix debug info for main chunk of stripped bytecode.</li>
|
||||
<li>Fix FOLD rule for <tt>string.sub(s, ...) == k</tt>.</li>
|
||||
<li>Fix FOLD rule for <tt>STRREF</tt> of <tt>SNEW</tt>.</li>
|
||||
<li>Fix frame traversal while searching for error function.</li>
|
||||
<li>Prevent GC estimate miscalculation due to buffer growth.</li>
|
||||
<li>Prevent adding side traces for stack checks.</li>
|
||||
<li>Fix top slot calculation for snapshots with continuations.</li>
|
||||
<li>Fix check for reuse of SCEV results in <tt>FORL</tt>.</li>
|
||||
<li>Add PS Vita port.</li>
|
||||
<li>Fix compatibility issues with Illumos.</li>
|
||||
<li>Fix DragonFly build (unsupported).</li>
|
||||
<li>OpenBSD/x86: Better executable memory allocation for W^X mode.</li>
|
||||
<li>x86: Fix argument checks for <tt>ipairs()</tt> iterator.</li>
|
||||
<li>x86: <tt>lj_math_random_step()</tt> clobbers XMM regs on OSX Clang.</li>
|
||||
<li>x86: Fix code generation for unused result of <tt>math.random()</tt>.</li>
|
||||
<li>x64: Allow building with <tt>LUAJIT_USE_SYSMALLOC</tt> and <tt>LUAJIT_USE_VALGRIND</tt>.</li>
|
||||
<li>x86/x64: Fix argument check for bit shifts.</li>
|
||||
<li>x86/x64: Fix code generation for fused test/arith ops.</li>
|
||||
<li>ARM: Fix write barrier check in <tt>BC_USETS</tt>.</li>
|
||||
<li>PPC: Fix red zone overflow in machine code generation.</li>
|
||||
<li>PPC: Don't use <tt>mcrxr</tt> on PPE.</li>
|
||||
<li>Various archs: Fix excess stack growth in interpreter.</li>
|
||||
<li>FFI: Fix FOLD rule for <tt>TOBIT</tt> + <tt>CONV num.u32</tt>.</li>
|
||||
<li>FFI: Prevent DSE across <tt>ffi.string()</tt>.</li>
|
||||
<li>FFI: No meta fallback when indexing pointer to incomplete struct.</li>
|
||||
<li>FFI: Fix initialization of unions of subtypes.</li>
|
||||
<li>FFI: Fix cdata vs. non-cdata arithmetic and comparisons.</li>
|
||||
<li>FFI: Fix <tt>__index</tt>/<tt>__newindex</tt> metamethod resolution for ctypes.</li>
|
||||
<li>FFI: Fix compilation of reference field access.</li>
|
||||
<li>FFI: Fix frame traversal for backtraces with FFI callbacks.</li>
|
||||
<li>FFI: Fix recording of indexing a struct pointer ctype object itself.</li>
|
||||
<li>FFI: Allow non-scalar cdata to be compared for equality by address.</li>
|
||||
<li>FFI: Fix pseudo type conversions for type punning.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.3">LuaJIT 2.0.3 — 2014-03-12</h2>
|
||||
<ul>
|
||||
<li>Add PS4 port.</li>
|
||||
<li>Add support for multilib distro builds.</li>
|
||||
<li>Fix OSX build.</li>
|
||||
<li>Fix MinGW build.</li>
|
||||
<li>Fix Xbox 360 build.</li>
|
||||
<li>Improve ULOAD forwarding for open upvalues.</li>
|
||||
<li>Fix GC steps threshold handling when called by JIT-compiled code.</li>
|
||||
<li>Fix argument checks for <tt>math.deg()</tt> and <tt>math.rad()</tt>.</li>
|
||||
<li>Fix <tt>jit.flush(func|true)</tt>.</li>
|
||||
<li>Respect <tt>jit.off(func)</tt> when returning to a function, too.</li>
|
||||
<li>Fix compilation of <tt>string.byte(s, nil, n)</tt>.</li>
|
||||
<li>Fix line number for relocated bytecode after closure fixup</li>
|
||||
<li>Fix frame traversal for backtraces.</li>
|
||||
<li>Fix ABC elimination.</li>
|
||||
<li>Fix handling of redundant PHIs.</li>
|
||||
<li>Fix snapshot restore for exit to function header.</li>
|
||||
<li>Fix type punning alias analysis for constified pointers</li>
|
||||
<li>Fix call unroll checks in the presence of metamethod frames.</li>
|
||||
<li>Fix initial maxslot for down-recursive traces.</li>
|
||||
<li>Prevent BASE register coalescing if parent uses <tt>IR_RETF</tt>.</li>
|
||||
<li>Don't purge modified function from stack slots in <tt>BC_RET</tt>.</li>
|
||||
<li>Fix recording of <tt>BC_VARG</tt>.</li>
|
||||
<li>Don't access dangling reference to reallocated IR.</li>
|
||||
<li>Fix frame depth display for bytecode dump in <tt>-jdump</tt>.</li>
|
||||
<li>ARM: Fix register allocation when rematerializing FPRs.</li>
|
||||
<li>x64: Fix store to upvalue for lightuserdata values.</li>
|
||||
<li>FFI: Add missing GC steps for callback argument conversions.</li>
|
||||
<li>FFI: Properly unload loaded DLLs.</li>
|
||||
<li>FFI: Fix argument checks for <tt>ffi.string()</tt>.</li>
|
||||
<li>FFI/x64: Fix passing of vector arguments to calls.</li>
|
||||
<li>FFI: Rehash finalizer table after GC cycle, if needed.</li>
|
||||
<li>FFI: Fix <tt>cts->L</tt> for cdata unsinking in snapshot restore.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.2">LuaJIT 2.0.2 — 2013-06-03</h2>
|
||||
<ul>
|
||||
<li>Fix memory access check for fast string interning.</li>
|
||||
<li>Fix MSVC intrinsics for older versions.</li>
|
||||
<li>Add missing GC steps for <tt>io.*</tt> functions.</li>
|
||||
<li>Fix spurious red zone overflows in machine code generation.</li>
|
||||
<li>Fix jump-range constrained mcode allocation.</li>
|
||||
<li>Inhibit DSE for implicit loads via calls.</li>
|
||||
<li>Fix builtin string to number conversion for overflow digits.</li>
|
||||
<li>Fix optional argument handling while recording builtins.</li>
|
||||
<li>Fix optional argument handling in <tt>table.concat()</tt>.</li>
|
||||
<li>Add partial support for building with MingW64 GCC 4.8-SEH.</li>
|
||||
<li>Add missing PHI barrier to <tt>string.sub(str, a, b) == kstr</tt> FOLD rule.</li>
|
||||
<li>Fix compatibility issues with Illumos.</li>
|
||||
<li>ARM: Fix cache flush/sync for exit stubs of JIT-compiled code.</li>
|
||||
<li>MIPS: Fix cache flush/sync for JIT-compiled code jump area.</li>
|
||||
<li>PPC: Add <tt>plt</tt> suffix for external calls from assembler code.</li>
|
||||
<li>FFI: Fix snapshot substitution in SPLIT pass.</li>
|
||||
<li>FFI/x86: Fix register allocation for 64 bit comparisons.</li>
|
||||
<li>FFI: Fix tailcall in lowest frame to C function with bool result.</li>
|
||||
<li>FFI: Ignore <tt>long</tt> type specifier in <tt>ffi.istype()</tt>.</li>
|
||||
<li>FFI: Fix calling conventions for 32 bit OSX and iOS simulator (struct returns).</li>
|
||||
<li>FFI: Fix calling conventions for ARM hard-float EABI (nested structs).</li>
|
||||
<li>FFI: Improve error messages for arithmetic and comparison operators.</li>
|
||||
<li>FFI: Insert no-op type conversion for pointer to integer cast.</li>
|
||||
<li>FFI: Fix unroll limit for <tt>ffi.fill()</tt>.</li>
|
||||
<li>FFI: Must sink <tt>XBAR</tt> together with <tt>XSTORE</tt>s.</li>
|
||||
<li>FFI: Preserve intermediate string for <tt>const char *</tt> conversion.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.1">LuaJIT 2.0.1 — 2013-02-19</h2>
|
||||
<ul>
|
||||
<li>Don't clear frame for out-of-memory error.</li>
|
||||
<li>Leave hook when resume catches error thrown from hook.</li>
|
||||
<li>Add missing GC steps for template table creation.</li>
|
||||
<li>Fix discharge order of comparisons in Lua parser.</li>
|
||||
<li>Improve buffer handling for <tt>io.read()</tt>.</li>
|
||||
<li>OSX: Add support for Mach-O object files to <tt>-b</tt> option.</li>
|
||||
<li>Fix PS3 port.</li>
|
||||
<li>Fix/enable Xbox 360 port.</li>
|
||||
<li>x86/x64: Always mark ref for shift count as non-weak.</li>
|
||||
<li>x64: Don't fuse implicitly 32-to-64 extended operands.</li>
|
||||
<li>ARM: Fix armhf call argument handling.</li>
|
||||
<li>ARM: Fix code generation for integer math.min/math.max.</li>
|
||||
<li>PPC/e500: Fix <tt>lj_vm_floor()</tt> for Inf/NaN.</li>
|
||||
<li>FFI: Change priority of table initializer variants for structs.</li>
|
||||
<li>FFI: Fix code generation for bool call result check on x86/x64.</li>
|
||||
<li>FFI: Load FFI library on-demand for bytecode with cdata literals.</li>
|
||||
<li>FFI: Fix handling of qualified transparent structs/unions.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0">LuaJIT 2.0.0 — 2012-11-08</h2>
|
||||
<ul>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix Android/x86 build.</li>
|
||||
<li>Fix recording of equality comparisons with <tt>__eq</tt> metamethods.</li>
|
||||
<li>Fix detection of immutable upvalues.</li>
|
||||
<li>Replace error with PANIC for callbacks from JIT-compiled code.</li>
|
||||
<li>Fix builtin string to number conversion for <tt>INT_MIN</tt>.</li>
|
||||
<li>Don't create unneeded array part for template tables.</li>
|
||||
<li>Fix <tt>CONV.num.int</tt> sinking.</li>
|
||||
<li>Don't propagate implicitly widened number to index metamethods.</li>
|
||||
<li>ARM: Fix ordered comparisons of number vs. non-number.</li>
|
||||
<li>FFI: Fix code generation for replay of sunk float fields.</li>
|
||||
<li>FFI: Fix signedness of bool.</li>
|
||||
<li>FFI: Fix recording of bool call result check on x86/x64.</li>
|
||||
<li>FFI: Fix stack-adjustment for <tt>__thiscall</tt> callbacks.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta11">LuaJIT 2.0.0-beta11 — 2012-10-16</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>Use ARM VFP instructions, if available (build-time detection).</li>
|
||||
<li>Add support for ARM hard-float EABI (<tt>armhf</tt>).</li>
|
||||
<li>Add PS3 port.</li>
|
||||
<li>Add many features from Lua 5.2, e.g. <tt>goto</tt>/labels.
|
||||
Refer to <a href="extensions.html#lua52">this list</a>.</li>
|
||||
<li>FFI: Add parameterized C types.</li>
|
||||
<li>FFI: Add support for copy constructors.</li>
|
||||
<li>FFI: Equality comparisons never raise an error (treat as unequal instead).</li>
|
||||
<li>FFI: Box all accessed or returned enums.</li>
|
||||
<li>FFI: Check for <tt>__new</tt> metamethod when calling a constructor.</li>
|
||||
<li>FFI: Handle <tt>__pairs</tt>/<tt>__ipairs</tt> metamethods for cdata objects.</li>
|
||||
<li>FFI: Convert <tt>io.*</tt> file handle to <tt>FILE *</tt> pointer (but as a <tt>void *</tt>).</li>
|
||||
<li>FFI: Detect and support type punning through unions.</li>
|
||||
<li>FFI: Improve various error messages.</li>
|
||||
</ul></li>
|
||||
<li>Build-system reorganization:
|
||||
<ul>
|
||||
<li>Reorganize directory layout:<br>
|
||||
<tt>lib/*</tt> → <tt>src/jit/*</tt><br>
|
||||
<tt>src/buildvm_*.dasc</tt> → <tt>src/vm_*.dasc</tt><br>
|
||||
<tt>src/buildvm_*.h</tt> → removed<br>
|
||||
<tt>src/buildvm*</tt> → <tt>src/host/*</tt></li>
|
||||
<li>Add minified Lua interpreter plus Lua BitOp (<tt>minilua</tt>) to run DynASM.</li>
|
||||
<li>Change DynASM bit operations to use Lua BitOp</li>
|
||||
<li>Translate only <tt>vm_*.dasc</tt> for detected target architecture.</li>
|
||||
<li>Improve target detection for <tt>msvcbuild.bat</tt>.</li>
|
||||
<li>Fix build issues on Cygwin and MinGW with optional MSys.</li>
|
||||
<li>Handle cross-compiles with FPU/no-FPU or hard-fp/soft-fp ABI mismatch.</li>
|
||||
<li>Remove some library functions for no-JIT/no-FFI builds.</li>
|
||||
<li>Add uninstall target to top-level Makefile.</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Preserve snapshot #0 PC for all traces.</li>
|
||||
<li>Fix argument checks for <tt>coroutine.create()</tt>.</li>
|
||||
<li>Command line prints version and JIT status to <tt>stdout</tt>, not <tt>stderr</tt>.</li>
|
||||
<li>Fix userdata <tt>__gc</tt> separations at Lua state close.</li>
|
||||
<li>Fix <tt>TDUP</tt> to <tt>HLOAD</tt> forwarding for <tt>LJ_DUALNUM</tt> builds.</li>
|
||||
<li>Fix buffer check in bytecode writer.</li>
|
||||
<li>Make <tt>os.date()</tt> thread-safe.</li>
|
||||
<li>Add missing declarations for MSVC intrinsics.</li>
|
||||
<li>Fix dispatch table modifications for return hooks.</li>
|
||||
<li>Workaround for MSVC conversion bug (<tt>double</tt> → <tt>uint32_t</tt> → <tt>int32_t</tt>).</li>
|
||||
<li>Fix FOLD rule <tt>(i-j)-i => 0-j</tt>.</li>
|
||||
<li>Never use DWARF unwinder on Windows.</li>
|
||||
<li>Fix shrinking of direct mapped blocks in builtin allocator.</li>
|
||||
<li>Limit recursion depth in <tt>string.match()</tt> et al.</li>
|
||||
<li>Fix late despecialization of <tt>ITERN</tt> after loop has been entered.</li>
|
||||
<li>Fix <tt>'f'</tt> and <tt>'L'</tt> options for <tt>debug.getinfo()</tt> and <tt>lua_getinfo()</tt>.</li>
|
||||
<li>Fix <tt>package.searchpath()</tt>.</li>
|
||||
<li>OSX: Change dylib names to be consistent with other platforms.</li>
|
||||
<li>Android: Workaround for broken <tt>sprintf("%g", -0.0)</tt>.</li>
|
||||
<li>x86: Remove support for ancient CPUs without <tt>CMOV</tt> (before Pentium Pro).</li>
|
||||
<li>x86: Fix register allocation for calls returning register pair.</li>
|
||||
<li>x86/x64: Fix fusion of unsigned byte comparisons with swapped operands.</li>
|
||||
<li>ARM: Fix <tt>tonumber()</tt> argument check.</li>
|
||||
<li>ARM: Fix modulo operator and <tt>math.floor()</tt>/<tt>math.ceil()</tt> for <tt>inf</tt>/<tt>nan</tt>.</li>
|
||||
<li>ARM: Invoke SPLIT pass for leftover <tt>IR_TOBIT</tt>.</li>
|
||||
<li>ARM: Fix BASE register coalescing.</li>
|
||||
<li>PPC: Fix interpreter state setup in callbacks.</li>
|
||||
<li>PPC: Fix <tt>string.sub()</tt> range check.</li>
|
||||
<li>MIPS: Support generation of MIPS/MIPSEL bytecode object files.</li>
|
||||
<li>MIPS: Fix calls to <tt>floor()</tt>/<tt>ceil()</tt><tt>/trunc()</tt>.</li>
|
||||
<li>ARM/PPC: Detect more target architecture variants.</li>
|
||||
<li>ARM/PPC/e500/MIPS: Fix tailcalls from fast functions, esp. <tt>tostring()</tt>.</li>
|
||||
<li>ARM/PPC/MIPS: Fix rematerialization of FP constants.</li>
|
||||
<li>FFI: Don't call <tt>FreeLibrary()</tt> on our own EXE/DLL.</li>
|
||||
<li>FFI: Resolve metamethods for constructors, too.</li>
|
||||
<li>FFI: Properly disable callbacks on iOS (would require executable memory).</li>
|
||||
<li>FFI: Fix cdecl string parsing during recording.</li>
|
||||
<li>FFI: Show address pointed to for <tt>tostring(ref)</tt>, too.</li>
|
||||
<li>FFI: Fix alignment of C call argument/return structure.</li>
|
||||
<li>FFI: Initialize all fields of standard types.</li>
|
||||
<li>FFI: Fix callback handling when new C types are declared in callback.</li>
|
||||
<li>FFI: Fix recording of constructors for pointers.</li>
|
||||
<li>FFI: Always resolve metamethods for pointers to structs.</li>
|
||||
<li>FFI: Correctly propagate alignment when interning nested types.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Add allocation sinking and store sinking optimization.</li>
|
||||
<li>Constify immutable upvalues.</li>
|
||||
<li>Add builtin string to integer or FP number conversion. Improves cross-platform consistency and correctness.</li>
|
||||
<li>Create string hash slots in template tables for non-const values, too. Avoids later table resizes.</li>
|
||||
<li>Eliminate <tt>HREFK</tt> guard for template table references.</li>
|
||||
<li>Add various new FOLD rules.</li>
|
||||
<li>Don't use stack unwinding for <tt>lua_yield()</tt> (slow on x64).</li>
|
||||
<li>ARM, PPC, MIPS: Improve <tt>XLOAD</tt> operand fusion and register hinting.</li>
|
||||
<li>PPC, MIPS: Compile <tt>math.sqrt()</tt> to sqrt instruction, if available.</li>
|
||||
<li>FFI: Fold <tt>KPTR</tt> + constant offset in SPLIT pass.</li>
|
||||
<li>FFI: Optimize/inline <tt>ffi.copy()</tt> and <tt>ffi.fill()</tt>.</li>
|
||||
<li>FFI: Compile and optimize array/struct copies.</li>
|
||||
<li>FFI: Compile <tt>ffi.typeof(cdata|ctype)</tt>, <tt>ffi.sizeof()</tt>, <tt>ffi.alignof()</tt>, <tt>ffi.offsetof()</tt> and <tt>ffi.gc()</tt>.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta10">LuaJIT 2.0.0-beta10 — 2012-05-09</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>The MIPS of LuaJIT is complete. It requires a CPU conforming to the
|
||||
MIPS32 R1 architecture with hardware FPU. O32 hard-fp ABI,
|
||||
little-endian or big-endian.</li>
|
||||
<li>Auto-detect target arch via cross-compiler. No need for
|
||||
<tt>TARGET=arch</tt> anymore.</li>
|
||||
<li>Make DynASM compatible with Lua 5.2.</li>
|
||||
<li>From Lua 5.2: Try <tt>__tostring</tt> metamethod on non-string error
|
||||
messages..</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix parsing of hex literals with exponents.</li>
|
||||
<li>Fix bytecode dump for certain number constants.</li>
|
||||
<li>Fix argument type in error message for relative arguments.</li>
|
||||
<li>Fix argument error handling on Lua stacks without a frame.</li>
|
||||
<li>Add missing mcode limit check in assembler backend.</li>
|
||||
<li>Fix compilation on OpenBSD.</li>
|
||||
<li>Avoid recursive GC steps after GC-triggered trace exit.</li>
|
||||
<li>Replace <tt><unwind.h></tt> definitions with our own.</li>
|
||||
<li>Fix OSX build issues. Bump minimum required OSX version to 10.4.</li>
|
||||
<li>Fix discharge order of comparisons in Lua parser.</li>
|
||||
<li>Ensure running <tt>__gc</tt> of userdata created in <tt>__gc</tt>
|
||||
at state close.</li>
|
||||
<li>Limit number of userdata <tt>__gc</tt> separations at state close.</li>
|
||||
<li>Fix bytecode <tt>JMP</tt> slot range when optimizing
|
||||
<tt>and</tt>/<tt>or</tt> with constant LHS.</li>
|
||||
<li>Fix DSE of <tt>USTORE</tt>.</li>
|
||||
<li>Make <tt>lua_concat()</tt> work from C hook with partial frame.</li>
|
||||
<li>Add required PHIs for implicit conversions, e.g. via <tt>XREF</tt>
|
||||
forwarding.</li>
|
||||
<li>Add more comparison variants to Valgrind suppressions file.</li>
|
||||
<li>Disable loading bytecode with an extra header (BOM or <tt>#!</tt>).</li>
|
||||
<li>Fix PHI stack slot syncing.</li>
|
||||
<li>ARM: Reorder type/value tests to silence Valgrind.</li>
|
||||
<li>ARM: Fix register allocation for <tt>ldrd</tt>-optimized
|
||||
<tt>HREFK</tt>.</li>
|
||||
<li>ARM: Fix conditional branch fixup for <tt>OBAR</tt>.</li>
|
||||
<li>ARM: Invoke SPLIT pass for <tt>double</tt> args in FFI call.</li>
|
||||
<li>ARM: Handle all <tt>CALL*</tt> ops with <tt>double</tt> results in
|
||||
SPLIT pass.</li>
|
||||
<li>ARM: Fix rejoin of <tt>POW</tt> in SPLIT pass.</li>
|
||||
<li>ARM: Fix compilation of <tt>math.sinh</tt>, <tt>math.cosh</tt>,
|
||||
<tt>math.tanh</tt>.</li>
|
||||
<li>ARM, PPC: Avoid pointless arg clearing in <tt>BC_IFUNCF</tt>.</li>
|
||||
<li>PPC: Fix resume after yield from hook.</li>
|
||||
<li>PPC: Fix argument checking for <tt>rawget()</tt>.</li>
|
||||
<li>PPC: Fix fusion of floating-point <tt>XLOAD</tt>/<tt>XSTORE</tt>.</li>
|
||||
<li>PPC: Fix <tt>HREFK</tt> code generation for huge tables.</li>
|
||||
<li>PPC: Use builtin D-Cache/I-Cache sync code.</li>
|
||||
</ul></li>
|
||||
<li>FFI library:
|
||||
<ul>
|
||||
<li>Ignore empty statements in <tt>ffi.cdef()</tt>.</li>
|
||||
<li>Ignore number parsing errors while skipping definitions.</li>
|
||||
<li>Don't touch frame in callbacks with tailcalls to fast functions.</li>
|
||||
<li>Fix library unloading on POSIX systems.</li>
|
||||
<li>Finalize cdata before userdata when closing the state.</li>
|
||||
<li>Change <tt>ffi.load()</tt> library name resolution for Cygwin.</li>
|
||||
<li>Fix resolving of function name redirects on Windows/x86.</li>
|
||||
<li>Fix symbol resolving error messages on Windows.</li>
|
||||
<li>Fix blacklisting of C functions calling callbacks.</li>
|
||||
<li>Fix result type of pointer difference.</li>
|
||||
<li>Use correct PC in FFI metamethod error message.</li>
|
||||
<li>Allow <tt>'typedef _Bool int BOOL;'</tt> for the Windows API.</li>
|
||||
<li>Don't record test for bool result of call, if ignored.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta9">LuaJIT 2.0.0-beta9 — 2011-12-14</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>PPC port of LuaJIT is complete. Default is the dual-number port
|
||||
(usually faster). Single-number port selectable via <tt>src/Makefile</tt>
|
||||
at build time.</li>
|
||||
<li>Add FFI callback support.</li>
|
||||
<li>Extend <tt>-b</tt> to generate <tt>.c</tt>, <tt>.h</tt> or <tt>.obj/.o</tt>
|
||||
files with embedded bytecode.</li>
|
||||
<li>Allow loading embedded bytecode with <tt>require()</tt>.</li>
|
||||
<li>From Lua 5.2: Change to <tt>'\z'</tt> escape. Reject undefined escape
|
||||
sequences.</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix OSX 10.7 build. Fix <tt>install_name</tt> and versioning on OSX.</li>
|
||||
<li>Fix iOS build.</li>
|
||||
<li>Install <tt>dis_arm.lua</tt>, too.</li>
|
||||
<li>Mark installed shared library as executable.</li>
|
||||
<li>Add debug option to <tt>msvcbuild.bat</tt> and improve error handling.</li>
|
||||
<li>Fix data-flow analysis for iterators.</li>
|
||||
<li>Fix forced unwinding triggered by external unwinder.</li>
|
||||
<li>Record missing <tt>for</tt> loop slot loads (return to lower frame).</li>
|
||||
<li>Always use ANSI variants of Windows system functions.</li>
|
||||
<li>Fix GC barrier for multi-result table constructor (<tt>TSETM</tt>).</li>
|
||||
<li>Fix/add various FOLD rules.</li>
|
||||
<li>Add potential PHI for number conversions due to type instability.</li>
|
||||
<li>Do not eliminate PHIs only referenced from other PHIs.</li>
|
||||
<li>Correctly anchor implicit number to string conversions in Lua/C API.</li>
|
||||
<li>Fix various stack limit checks.</li>
|
||||
<li>x64: Use thread-safe exceptions for external unwinding (GCC platforms).</li>
|
||||
<li>x64: Fix result type of cdata index conversions.</li>
|
||||
<li>x64: Fix <tt>math.random()</tt> and <tt>bit.bswap()</tt> code generation.</li>
|
||||
<li>x64: Fix <tt>lightuserdata</tt> comparisons.</li>
|
||||
<li>x64: Always extend stack-passed arguments to pointer size.</li>
|
||||
<li>ARM: Many fixes to code generation backend.</li>
|
||||
<li>PPC/e500: Fix dispatch for binop metamethods.</li>
|
||||
<li>PPC/e500: Save/restore condition registers when entering/leaving the VM.</li>
|
||||
<li>PPC/e500: Fix write barrier in stores of strings to upvalues.</li>
|
||||
</ul></li>
|
||||
<li>FFI library:
|
||||
<ul>
|
||||
<li>Fix C comment parsing.</li>
|
||||
<li>Fix snapshot optimization for cdata comparisons.</li>
|
||||
<li>Fix recording of const/enum lookups in namespaces.</li>
|
||||
<li>Fix call argument and return handling for <tt>I8/U8/I16/U16</tt> types.</li>
|
||||
<li>Fix unfused loads of float fields.</li>
|
||||
<li>Fix <tt>ffi.string()</tt> recording.</li>
|
||||
<li>Save <tt>GetLastError()</tt> around <tt>ffi.load()</tt> and symbol
|
||||
resolving, too.</li>
|
||||
<li>Improve ld script detection in <tt>ffi.load()</tt>.</li>
|
||||
<li>Record loads/stores to external variables in namespaces.</li>
|
||||
<li>Compile calls to stdcall, fastcall and vararg functions.</li>
|
||||
<li>Treat function ctypes like pointers in comparisons.</li>
|
||||
<li>Resolve <tt>__call</tt> metamethod for pointers, too.</li>
|
||||
<li>Record C function calls with bool return values.</li>
|
||||
<li>Record <tt>ffi.errno()</tt>.</li>
|
||||
<li>x86: Fix number to <tt>uint32_t</tt> conversion rounding.</li>
|
||||
<li>x86: Fix 64 bit arithmetic in assembler backend.</li>
|
||||
<li>x64: Fix struct-by-value calling conventions.</li>
|
||||
<li>ARM: Ensure invocation of SPLIT pass for float conversions.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Display trace types with <tt>-jv</tt> and <tt>-jdump</tt>.</li>
|
||||
<li>Record isolated calls. But prefer recording loops over calls.</li>
|
||||
<li>Specialize to prototype for non-monomorphic functions. Solves the
|
||||
trace-explosion problem for closure-heavy programming styles.</li>
|
||||
<li>Always generate a portable <tt>vmdef.lua</tt>. Easier for distros.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta8">LuaJIT 2.0.0-beta8 — 2011-06-23</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>Soft-float ARM port of LuaJIT is complete.</li>
|
||||
<li>Add support for bytecode loading/saving and <tt>-b</tt> command line
|
||||
option.</li>
|
||||
<li>From Lua 5.2: <tt>__len</tt> metamethod for tables
|
||||
(disabled by default).</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>ARM: Misc. fixes for interpreter.</li>
|
||||
<li>x86/x64: Fix <tt>bit.*</tt> argument checking in interpreter.</li>
|
||||
<li>Catch early out-of-memory in memory allocator initialization.</li>
|
||||
<li>Fix data-flow analysis for paths leading to an upvalue close.</li>
|
||||
<li>Fix check for missing arguments in <tt>string.format()</tt>.</li>
|
||||
<li>Fix Solaris/x86 build (note: not a supported target).</li>
|
||||
<li>Fix recording of loops with instable directions in side traces.</li>
|
||||
<li>x86/x64: Fix fusion of comparisons with <tt>u8</tt>/<tt>u16</tt>
|
||||
<tt>XLOAD</tt>.</li>
|
||||
<li>x86/x64: Fix register allocation for variable shifts.</li>
|
||||
</ul></li>
|
||||
<li>FFI library:
|
||||
<ul>
|
||||
<li>Add <tt>ffi.errno()</tt>. Save <tt>errno</tt>/<tt>GetLastError()</tt>
|
||||
around allocations etc.</li>
|
||||
<li>Fix <tt>__gc</tt> for VLA/VLS cdata objects.</li>
|
||||
<li>Fix recording of casts from 32 bit cdata pointers to integers.</li>
|
||||
<li><tt>tonumber(cdata)</tt> returns <tt>nil</tt> for non-numbers.</li>
|
||||
<li>Show address pointed to for <tt>tostring(pointer)</tt>.</li>
|
||||
<li>Print <tt>NULL</tt> pointers as <tt>"cdata<... *>: NULL"</tt>.</li>
|
||||
<li>Support <tt>__tostring</tt> metamethod for pointers to structs, too.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>More tuning for loop unrolling heuristics.</li>
|
||||
<li>Flatten and compress in-memory debug info (saves ~70%).</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta7">LuaJIT 2.0.0-beta7 — 2011-05-05</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>ARM port of the LuaJIT interpreter is complete.</li>
|
||||
<li>FFI library: Add <tt>ffi.gc()</tt>, <tt>ffi.metatype()</tt>,
|
||||
<tt>ffi.istype()</tt>.</li>
|
||||
<li>FFI library: Resolve ld script redirection in <tt>ffi.load()</tt>.</li>
|
||||
<li>From Lua 5.2: <tt>package.searchpath()</tt>, <tt>fp:read("*L")</tt>,
|
||||
<tt>load(string)</tt>.</li>
|
||||
<li>From Lua 5.2, disabled by default: empty statement,
|
||||
<tt>table.unpack()</tt>, modified <tt>coroutine.running()</tt>.</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>FFI library: numerous fixes.</li>
|
||||
<li>Fix type mismatches in store-to-load forwarding.</li>
|
||||
<li>Fix error handling within metamethods.</li>
|
||||
<li>Fix <tt>table.maxn()</tt>.</li>
|
||||
<li>Improve accuracy of <tt>x^-k</tt> on x64.</li>
|
||||
<li>Fix code generation for Intel Atom in x64 mode.</li>
|
||||
<li>Fix narrowing of POW.</li>
|
||||
<li>Fix recording of retried fast functions.</li>
|
||||
<li>Fix code generation for <tt>bit.bnot()</tt> and multiplies.</li>
|
||||
<li>Fix error location within cpcall frames.</li>
|
||||
<li>Add workaround for old libgcc unwind bug.</li>
|
||||
<li>Fix <tt>lua_yield()</tt> and <tt>getmetatable(lightuserdata)</tt> on x64.</li>
|
||||
<li>Misc. fixes for PPC/e500 interpreter.</li>
|
||||
<li>Fix stack slot updates for down-recursion.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Add dual-number mode (int/double) for the VM. Enabled for ARM.</li>
|
||||
<li>Improve narrowing of arithmetic operators and <tt>for</tt> loops.</li>
|
||||
<li>Tune loop unrolling heuristics and increase trace recorder limits.</li>
|
||||
<li>Eliminate dead slots in snapshots using bytecode data-flow analysis.</li>
|
||||
<li>Avoid phantom stores to proxy tables.</li>
|
||||
<li>Optimize lookups in empty proxy tables.</li>
|
||||
<li>Improve bytecode optimization of <tt>and</tt>/<tt>or</tt> operators.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta6">LuaJIT 2.0.0-beta6 — 2011-02-11</h2>
|
||||
<ul>
|
||||
<li>New features:
|
||||
<ul>
|
||||
<li>PowerPC/e500v2 port of the LuaJIT interpreter is complete.</li>
|
||||
<li>Various minor features from Lua 5.2: Hex escapes in literals,
|
||||
<tt>'\*'</tt> escape, reversible <tt>string.format("%q",s)</tt>,
|
||||
<tt>"%g"</tt> pattern, <tt>table.sort</tt> checks callbacks,
|
||||
<tt>os.exit(status|true|false[,close])</tt>.</li>
|
||||
<li>Lua 5.2 <tt>__pairs</tt> and <tt>__ipairs</tt> metamethods
|
||||
(disabled by default).</li>
|
||||
<li>Initial release of the FFI library.</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix <tt>string.format()</tt> for non-finite numbers.</li>
|
||||
<li>Fix memory leak when compiled to use the built-in allocator.</li>
|
||||
<li>x86/x64: Fix unnecessary resize in <tt>TSETM</tt> bytecode.</li>
|
||||
<li>Fix various GC issues with traces and <tt>jit.flush()</tt>.</li>
|
||||
<li>x64: Fix fusion of indexes for array references.</li>
|
||||
<li>x86/x64: Fix stack overflow handling for coroutine results.</li>
|
||||
<li>Enable low-2GB memory allocation on FreeBSD/x64.</li>
|
||||
<li>Fix <tt>collectgarbage("count")</tt> result if more than 2GB is in use.</li>
|
||||
<li>Fix parsing of hex floats.</li>
|
||||
<li>x86/x64: Fix loop branch inversion with trailing
|
||||
<tt>HREF+NE/EQ</tt>.</li>
|
||||
<li>Add <tt>jit.os</tt> string.</li>
|
||||
<li><tt>coroutine.create()</tt> permits running C functions, too.</li>
|
||||
<li>Fix OSX build to work with newer ld64 versions.</li>
|
||||
<li>Fix bytecode optimization of <tt>and</tt>/<tt>or</tt> operators.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Emit specialized bytecode for <tt>pairs()</tt>/<tt>next()</tt>.</li>
|
||||
<li>Improve bytecode coalescing of <tt>nil</tt> constants.</li>
|
||||
<li>Compile calls to vararg functions.</li>
|
||||
<li>Compile <tt>select()</tt>.</li>
|
||||
<li>Improve alias analysis, esp. for loads from allocations.</li>
|
||||
<li>Tuning of various compiler heuristics.</li>
|
||||
<li>Refactor and extend IR conversion instructions.</li>
|
||||
<li>x86/x64: Various backend enhancements related to the FFI.</li>
|
||||
<li>Add SPLIT pass to split 64 bit IR instructions for 32 bit CPUs.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta5">LuaJIT 2.0.0-beta5 — 2010-08-24</h2>
|
||||
<ul>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix trace exit dispatch to function headers.</li>
|
||||
<li>Fix Windows and OSX builds with LUAJIT_DISABLE_JIT.</li>
|
||||
<li>Reorganize and fix placement of generated machine code on x64.</li>
|
||||
<li>Fix TNEW in x64 interpreter.</li>
|
||||
<li>Do not eliminate PHIs for values only referenced from side exits.</li>
|
||||
<li>OS-independent canonicalization of strings for non-finite numbers.</li>
|
||||
<li>Fix <tt>string.char()</tt> range check on x64.</li>
|
||||
<li>Fix <tt>tostring()</tt> resolving within <tt>print()</tt>.</li>
|
||||
<li>Fix error handling for <tt>next()</tt>.</li>
|
||||
<li>Fix passing of constant arguments to external calls on x64.</li>
|
||||
<li>Fix interpreter argument check for two-argument SSE math functions.</li>
|
||||
<li>Fix C frame chain corruption caused by <tt>lua_cpcall()</tt>.</li>
|
||||
<li>Fix return from <tt>pcall()</tt> within active hook.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Replace on-trace GC frame syncing with interpreter exit.</li>
|
||||
<li>Improve hash lookup specialization by not removing dead keys during GC.</li>
|
||||
<li>Turn traces into true GC objects.</li>
|
||||
<li>Avoid starting a GC cycle immediately after library init.</li>
|
||||
<li>Add weak guards to improve dead-code elimination.</li>
|
||||
<li>Speed up string interning.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta4">LuaJIT 2.0.0-beta4 — 2010-03-28</h2>
|
||||
<ul>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix precondition for on-trace creation of table keys.</li>
|
||||
<li>Fix <tt>{f()}</tt> on x64 when table is resized.</li>
|
||||
<li>Fix folding of ordered comparisons with same references.</li>
|
||||
<li>Fix snapshot restores for multi-result bytecodes.</li>
|
||||
<li>Fix potential hang when recording bytecode with nested closures.</li>
|
||||
<li>Fix recording of <tt>getmetatable()</tt>, <tt>tonumber()</tt> and bad argument types.</li>
|
||||
<li>Fix SLOAD fusion across returns to lower frames.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Add array bounds check elimination. <tt>-Oabc</tt> is enabled by default.</li>
|
||||
<li>More tuning for x64, e.g. smaller table objects.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta3">LuaJIT 2.0.0-beta3 — 2010-03-07</h2>
|
||||
<ul>
|
||||
<li>LuaJIT x64 port:
|
||||
<ul>
|
||||
<li>Port integrated memory allocator to Linux/x64, Windows/x64 and OSX/x64.</li>
|
||||
<li>Port interpreter and JIT compiler to x64.</li>
|
||||
<li>Port DynASM to x64.</li>
|
||||
<li>Many 32/64 bit cleanups in the VM.</li>
|
||||
<li>Allow building the interpreter with either x87 or SSE2 arithmetics.</li>
|
||||
<li>Add external unwinding and C++ exception interop (default on x64).</li>
|
||||
</ul></li>
|
||||
<li>Correctness and completeness:
|
||||
<ul>
|
||||
<li>Fix constructor bytecode generation for certain conditional values.</li>
|
||||
<li>Fix some cases of ordered string comparisons.</li>
|
||||
<li>Fix <tt>lua_tocfunction()</tt>.</li>
|
||||
<li>Fix cutoff register in JMP bytecode for some conditional expressions.</li>
|
||||
<li>Fix PHI marking algorithm for references from variant slots.</li>
|
||||
<li>Fix <tt>package.cpath</tt> for non-default PREFIX.</li>
|
||||
<li>Fix DWARF2 frame unwind information for interpreter on OSX.</li>
|
||||
<li>Drive the GC forward on string allocations in the parser.</li>
|
||||
<li>Implement call/return hooks (zero-cost if disabled).</li>
|
||||
<li>Implement yield from C hooks.</li>
|
||||
<li>Disable JIT compiler on older non-SSE2 CPUs instead of aborting.</li>
|
||||
</ul></li>
|
||||
<li>Structural and performance enhancements:
|
||||
<ul>
|
||||
<li>Compile recursive code (tail-, up- and down-recursion).</li>
|
||||
<li>Improve heuristics for bytecode penalties and blacklisting.</li>
|
||||
<li>Split CALL/FUNC recording and clean up fast function call semantics.</li>
|
||||
<li>Major redesign of internal function call handling.</li>
|
||||
<li>Improve FOR loop const specialization and integerness checks.</li>
|
||||
<li>Switch to pre-initialized stacks. Avoid frame-clearing.</li>
|
||||
<li>Colocation of prototypes and related data: bytecode, constants, debug info.</li>
|
||||
<li>Cleanup parser and streamline bytecode generation.</li>
|
||||
<li>Add support for weak IR references to register allocator.</li>
|
||||
<li>Switch to compressed, extensible snapshots.</li>
|
||||
<li>Compile returns to frames below the start frame.</li>
|
||||
<li>Improve alias analysis of upvalues using a disambiguation hash value.</li>
|
||||
<li>Compile floor/ceil/trunc to SSE2 helper calls or SSE4.1 instructions.</li>
|
||||
<li>Add generic C call handling to IR and backend.</li>
|
||||
<li>Improve KNUM fuse vs. load heuristics.</li>
|
||||
<li>Compile various <tt>io.*()</tt> functions.</li>
|
||||
<li>Compile <tt>math.sinh()</tt>, <tt>math.cosh()</tt>, <tt>math.tanh()</tt>
|
||||
and <tt>math.random()</tt>.</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta2">LuaJIT 2.0.0-beta2 — 2009-11-09</h2>
|
||||
<ul>
|
||||
<li>Reorganize build system. Build static+shared library on POSIX.</li>
|
||||
<li>Allow C++ exception conversion on all platforms
|
||||
using a wrapper function.</li>
|
||||
<li>Automatically catch C++ exceptions and rethrow Lua error
|
||||
(DWARF2 only).</li>
|
||||
<li>Check for the correct x87 FPU precision at strategic points.</li>
|
||||
<li>Always use wrappers for libm functions.</li>
|
||||
<li>Resurrect metamethod name strings before copying them.</li>
|
||||
<li>Mark current trace, even if compiler is idle.</li>
|
||||
<li>Ensure FILE metatable is created only once.</li>
|
||||
<li>Fix type comparisons when different integer types are involved.</li>
|
||||
<li>Fix <tt>getmetatable()</tt> recording.</li>
|
||||
<li>Fix TDUP with dead keys in template table.</li>
|
||||
<li><tt>jit.flush(tr)</tt> returns status.
|
||||
Prevent manual flush of a trace that's still linked.</li>
|
||||
<li>Improve register allocation heuristics for invariant references.</li>
|
||||
<li>Compile the push/pop variants of <tt>table.insert()</tt> and
|
||||
<tt>table.remove()</tt>.</li>
|
||||
<li>Compatibility with MSVC <tt>link /debug</tt>.</li>
|
||||
<li>Fix <tt>lua_iscfunction()</tt>.</li>
|
||||
<li>Fix <tt>math.random()</tt> when compiled with <tt>-fpic</tt> (OSX).</li>
|
||||
<li>Fix <tt>table.maxn()</tt>.</li>
|
||||
<li>Bump <tt>MACOSX_DEPLOYMENT_TARGET</tt> to <tt>10.4</tt></li>
|
||||
<li><tt>luaL_check*()</tt> and <tt>luaL_opt*()</tt> now support
|
||||
negative arguments, too.<br>
|
||||
This matches the behavior of Lua 5.1, but not the specification.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="LuaJIT-2.0.0-beta1">LuaJIT 2.0.0-beta1 — 2009-10-31</h2>
|
||||
<ul>
|
||||
<li>This is the first public release of LuaJIT 2.0.</li>
|
||||
<li>The whole VM has been rewritten from the ground up, so there's
|
||||
no point in listing differences over earlier versions.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,111 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Contact</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Contact</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
If you want to report bugs, propose fixes or suggest enhancements,
|
||||
please use the
|
||||
<a href="https://github.com/LuaJIT/LuaJIT/issues">GitHub issue tracker</a>.
|
||||
</p>
|
||||
<p>
|
||||
Please send general questions to the
|
||||
<a href="http://luajit.org/list.html"><span class="ext">»</span> LuaJIT mailing list</a>.
|
||||
</p>
|
||||
<p>
|
||||
You can also send any questions you have directly to me:
|
||||
</p>
|
||||
|
||||
<script type="text/javascript">
|
||||
<!--
|
||||
var xS="@-:\" .0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ<abc>defghijklmnopqrstuvwxyz";function xD(s)
|
||||
{var len=s.length;var r="";for(var i=0;i<len;i++)
|
||||
{var c=s.charAt(i);var n=xS.indexOf(c);if(n!=-1)c=xS.charAt(69-n);r+=c;}
|
||||
document.write("<"+"p>"+r+"<"+"/p>\n");}
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
<!--
|
||||
xD("fyZKB8xv\"FJytmz8.KAB0u52D")
|
||||
//--></script>
|
||||
<noscript>
|
||||
<p><img src="img/contact.png" alt="Contact info in image" width="170" height="13">
|
||||
</p>
|
||||
</noscript>
|
||||
|
||||
<h2>Copyright</h2>
|
||||
<p>
|
||||
All documentation is
|
||||
Copyright © 2005-2017 Mike Pall.
|
||||
</p>
|
||||
|
||||
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,189 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Lua/C API Extensions</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Lua/C API Extensions</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 href="ext_jit.html">jit.* Library</a>
|
||||
</li><li>
|
||||
<a class="current" 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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
LuaJIT adds some extensions to the standard Lua/C API. The LuaJIT include
|
||||
directory must be in the compiler search path (<tt>-I<i>path</i></tt>)
|
||||
to be able to include the required header for C code:
|
||||
</p>
|
||||
<pre class="code">
|
||||
#include "luajit.h"
|
||||
</pre>
|
||||
<p>
|
||||
Or for C++ code:
|
||||
</p>
|
||||
<pre class="code">
|
||||
#include "lua.hpp"
|
||||
</pre>
|
||||
|
||||
<h2 id="luaJIT_setmode"><tt>luaJIT_setmode(L, idx, mode)</tt>
|
||||
— Control VM</h2>
|
||||
<p>
|
||||
This is a C API extension to allow control of the VM from C code. The
|
||||
full prototype of <tt>LuaJIT_setmode</tt> is:
|
||||
</p>
|
||||
<pre class="code">
|
||||
LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode);
|
||||
</pre>
|
||||
<p>
|
||||
The returned status is either success (<tt>1</tt>) or failure (<tt>0</tt>).
|
||||
The second argument is either <tt>0</tt> or a stack index (similar to the
|
||||
other Lua/C API functions).
|
||||
</p>
|
||||
<p>
|
||||
The third argument specifies the mode, which is 'or'ed with a flag.
|
||||
The flag can be <tt>LUAJIT_MODE_OFF</tt> to turn a feature on,
|
||||
<tt>LUAJIT_MODE_ON</tt> to turn a feature off, or
|
||||
<tt>LUAJIT_MODE_FLUSH</tt> to flush cached code.
|
||||
</p>
|
||||
<p>
|
||||
The following modes are defined:
|
||||
</p>
|
||||
|
||||
<h3 id="mode_engine"><tt>luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE|flag)</tt></h3>
|
||||
<p>
|
||||
Turn the whole JIT compiler on or off or flush the whole cache of compiled code.
|
||||
</p>
|
||||
|
||||
<h3 id="mode_func"><tt>luaJIT_setmode(L, idx, LUAJIT_MODE_FUNC|flag)</tt><br>
|
||||
<tt>luaJIT_setmode(L, idx, LUAJIT_MODE_ALLFUNC|flag)</tt><br>
|
||||
<tt>luaJIT_setmode(L, idx, LUAJIT_MODE_ALLSUBFUNC|flag)</tt></h3>
|
||||
<p>
|
||||
This sets the mode for the function at the stack index <tt>idx</tt> or
|
||||
the parent of the calling function (<tt>idx = 0</tt>). It either
|
||||
enables JIT compilation for a function, disables it and flushes any
|
||||
already compiled code or only flushes already compiled code. This
|
||||
applies recursively to all sub-functions of the function with
|
||||
<tt>LUAJIT_MODE_ALLFUNC</tt> or only to the sub-functions with
|
||||
<tt>LUAJIT_MODE_ALLSUBFUNC</tt>.
|
||||
</p>
|
||||
|
||||
<h3 id="mode_trace"><tt>luaJIT_setmode(L, trace,<br>
|
||||
LUAJIT_MODE_TRACE|LUAJIT_MODE_FLUSH)</tt></h3>
|
||||
<p>
|
||||
Flushes the specified root trace and all of its side traces from the cache.
|
||||
The code for the trace will be retained as long as there are any other
|
||||
traces which link to it.
|
||||
</p>
|
||||
|
||||
<h3 id="mode_wrapcfunc"><tt>luaJIT_setmode(L, idx, LUAJIT_MODE_WRAPCFUNC|flag)</tt></h3>
|
||||
<p>
|
||||
This mode defines a wrapper function for calls to C functions. If
|
||||
called with <tt>LUAJIT_MODE_ON</tt>, the stack index at <tt>idx</tt>
|
||||
must be a <tt>lightuserdata</tt> object holding a pointer to the wrapper
|
||||
function. From now on all C functions are called through the wrapper
|
||||
function. If called with <tt>LUAJIT_MODE_OFF</tt> this mode is turned
|
||||
off and all C functions are directly called.
|
||||
</p>
|
||||
<p>
|
||||
The wrapper function can be used for debugging purposes or to catch
|
||||
and convert foreign exceptions. But please read the section on
|
||||
<a href="extensions.html#exceptions">C++ exception interoperability</a>
|
||||
first. Recommended usage can be seen in this C++ code excerpt:
|
||||
</p>
|
||||
<pre class="code">
|
||||
#include <exception>
|
||||
#include "lua.hpp"
|
||||
|
||||
// Catch C++ exceptions and convert them to Lua error messages.
|
||||
// Customize as needed for your own exception classes.
|
||||
static int wrap_exceptions(lua_State *L, lua_CFunction f)
|
||||
{
|
||||
try {
|
||||
return f(L); // Call wrapped function and return result.
|
||||
} catch (const char *s) { // Catch and convert exceptions.
|
||||
lua_pushstring(L, s);
|
||||
} catch (std::exception& e) {
|
||||
lua_pushstring(L, e.what());
|
||||
} catch (...) {
|
||||
lua_pushliteral(L, "caught (...)");
|
||||
}
|
||||
return lua_error(L); // Rethrow as a Lua error.
|
||||
}
|
||||
|
||||
static int myinit(lua_State *L)
|
||||
{
|
||||
...
|
||||
// Define wrapper function and enable it.
|
||||
lua_pushlightuserdata(L, (void *)wrap_exceptions);
|
||||
luaJIT_setmode(L, -1, LUAJIT_MODE_WRAPCFUNC|LUAJIT_MODE_ON);
|
||||
lua_pop(L, 1);
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
Note that you can only define <b>a single global wrapper function</b>,
|
||||
so be careful when using this mechanism from multiple C++ modules.
|
||||
Also note that this mechanism is not without overhead.
|
||||
</p>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,332 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>FFI Library</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>FFI Library</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 class="current" 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 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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
|
||||
The FFI library allows <b>calling external C functions</b> and
|
||||
<b>using C data structures</b> from pure Lua code.
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
The FFI library largely obviates the need to write tedious manual
|
||||
Lua/C bindings in C. No need to learn a separate binding language
|
||||
— <b>it parses plain C declarations!</b> These can be
|
||||
cut-n-pasted from C header files or reference manuals. It's up to
|
||||
the task of binding large libraries without the need for dealing with
|
||||
fragile binding generators.
|
||||
|
||||
</p>
|
||||
<p>
|
||||
The FFI library is tightly integrated into LuaJIT (it's not available
|
||||
as a separate module). The code generated by the JIT-compiler for
|
||||
accesses to C data structures from Lua code is on par with the
|
||||
code a C compiler would generate. Calls to C functions can
|
||||
be inlined in JIT-compiled code, unlike calls to functions bound via
|
||||
the classic Lua/C API.
|
||||
</p>
|
||||
<p>
|
||||
This page gives a short introduction to the usage of the FFI library.
|
||||
<em>Please use the FFI sub-topics in the navigation bar to learn more.</em>
|
||||
</p>
|
||||
|
||||
<h2 id="call">Motivating Example: Calling External C Functions</h2>
|
||||
<p>
|
||||
It's really easy to call an external C library function:
|
||||
</p>
|
||||
<pre class="code mark">
|
||||
<span class="codemark">①
|
||||
②
|
||||
|
||||
|
||||
③</span>local ffi = require("ffi")
|
||||
ffi.cdef[[
|
||||
<span style="color:#00a000;">int printf(const char *fmt, ...);</span>
|
||||
]]
|
||||
ffi.C.printf("Hello %s!", "world")
|
||||
</pre>
|
||||
<p>
|
||||
So, let's pick that apart:
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">①</span> Load the FFI library.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">②</span> Add a C declaration
|
||||
for the function. The part inside the double-brackets (in green) is
|
||||
just standard C syntax.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">③</span> Call the named
|
||||
C function — Yes, it's that simple!
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
Actually, what goes on behind the scenes is far from simple: <span
|
||||
style="color:#4040c0;">③</span> makes use of the standard
|
||||
C library namespace <tt>ffi.C</tt>. Indexing this namespace with
|
||||
a symbol name (<tt>"printf"</tt>) automatically binds it to the
|
||||
standard C library. The result is a special kind of object which,
|
||||
when called, runs the <tt>printf</tt> function. The arguments passed
|
||||
to this function are automatically converted from Lua objects to the
|
||||
corresponding C types.
|
||||
</p>
|
||||
<p>
|
||||
Ok, so maybe the use of <tt>printf()</tt> wasn't such a spectacular
|
||||
example. You could have done that with <tt>io.write()</tt> and
|
||||
<tt>string.format()</tt>, too. But you get the idea ...
|
||||
</p>
|
||||
<p>
|
||||
So here's something to pop up a message box on Windows:
|
||||
</p>
|
||||
<pre class="code">
|
||||
local ffi = require("ffi")
|
||||
ffi.cdef[[
|
||||
<span style="color:#00a000;">int MessageBoxA(void *w, const char *txt, const char *cap, int type);</span>
|
||||
]]
|
||||
ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0)
|
||||
</pre>
|
||||
<p>
|
||||
Bing! Again, that was far too easy, no?
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
Compare this with the effort required to bind that function using the
|
||||
classic Lua/C API: create an extra C file, add a C function
|
||||
that retrieves and checks the argument types passed from Lua and calls
|
||||
the actual C function, add a list of module functions and their
|
||||
names, add a <tt>luaopen_*</tt> function and register all module
|
||||
functions, compile and link it into a shared library (DLL), move it to
|
||||
the proper path, add Lua code that loads the module aaaand ... finally
|
||||
call the binding function. Phew!
|
||||
</p>
|
||||
|
||||
<h2 id="cdata">Motivating Example: Using C Data Structures</h2>
|
||||
<p>
|
||||
The FFI library allows you to create and access C data
|
||||
structures. Of course the main use for this is for interfacing with
|
||||
C functions. But they can be used stand-alone, too.
|
||||
</p>
|
||||
<p>
|
||||
Lua is built upon high-level data types. They are flexible, extensible
|
||||
and dynamic. That's why we all love Lua so much. Alas, this can be
|
||||
inefficient for certain tasks, where you'd really want a low-level
|
||||
data type. E.g. a large array of a fixed structure needs to be
|
||||
implemented with a big table holding lots of tiny tables. This imposes
|
||||
both a substantial memory overhead as well as a performance overhead.
|
||||
</p>
|
||||
<p>
|
||||
Here's a sketch of a library that operates on color images plus a
|
||||
simple benchmark. First, the plain Lua version:
|
||||
</p>
|
||||
<pre class="code">
|
||||
local floor = math.floor
|
||||
|
||||
local function image_ramp_green(n)
|
||||
local img = {}
|
||||
local f = 255/(n-1)
|
||||
for i=1,n do
|
||||
img[i] = { red = 0, green = floor((i-1)*f), blue = 0, alpha = 255 }
|
||||
end
|
||||
return img
|
||||
end
|
||||
|
||||
local function image_to_grey(img, n)
|
||||
for i=1,n do
|
||||
local y = floor(0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue)
|
||||
img[i].red = y; img[i].green = y; img[i].blue = y
|
||||
end
|
||||
end
|
||||
|
||||
local N = 400*400
|
||||
local img = image_ramp_green(N)
|
||||
for i=1,1000 do
|
||||
image_to_grey(img, N)
|
||||
end
|
||||
</pre>
|
||||
<p>
|
||||
This creates a table with 160.000 pixels, each of which is a table
|
||||
holding four number values in the range of 0-255. First an image with
|
||||
a green ramp is created (1D for simplicity), then the image is
|
||||
converted to greyscale 1000 times. Yes, that's silly, but I was in
|
||||
need of a simple example ...
|
||||
</p>
|
||||
<p>
|
||||
And here's the FFI version. The modified parts have been marked in
|
||||
bold:
|
||||
</p>
|
||||
<pre class="code mark">
|
||||
<span class="codemark">①
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
②
|
||||
|
||||
③
|
||||
④
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
③
|
||||
⑤</span><b>local ffi = require("ffi")
|
||||
ffi.cdef[[
|
||||
</b><span style="color:#00a000;">typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;</span><b>
|
||||
]]</b>
|
||||
|
||||
local function image_ramp_green(n)
|
||||
<b>local img = ffi.new("rgba_pixel[?]", n)</b>
|
||||
local f = 255/(n-1)
|
||||
for i=<b>0,n-1</b> do
|
||||
<b>img[i].green = i*f</b>
|
||||
<b>img[i].alpha = 255</b>
|
||||
end
|
||||
return img
|
||||
end
|
||||
|
||||
local function image_to_grey(img, n)
|
||||
for i=<b>0,n-1</b> do
|
||||
local y = <b>0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue</b>
|
||||
img[i].red = y; img[i].green = y; img[i].blue = y
|
||||
end
|
||||
end
|
||||
|
||||
local N = 400*400
|
||||
local img = image_ramp_green(N)
|
||||
for i=1,1000 do
|
||||
image_to_grey(img, N)
|
||||
end
|
||||
</pre>
|
||||
<p>
|
||||
Ok, so that wasn't too difficult:
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">①</span> First, load the FFI
|
||||
library and declare the low-level data type. Here we choose a
|
||||
<tt>struct</tt> which holds four byte fields, one for each component
|
||||
of a 4x8 bit RGBA pixel.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">②</span> Creating the data
|
||||
structure with <tt>ffi.new()</tt> is straightforward — the
|
||||
<tt>'?'</tt> is a placeholder for the number of elements of a
|
||||
variable-length array.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">③</span> C arrays are
|
||||
zero-based, so the indexes have to run from <tt>0</tt> to
|
||||
<tt>n-1</tt>. One might want to allocate one more element instead to
|
||||
simplify converting legacy code.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">④</span> Since <tt>ffi.new()</tt>
|
||||
zero-fills the array by default, we only need to set the green and the
|
||||
alpha fields.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">⑤</span> The calls to
|
||||
<tt>math.floor()</tt> can be omitted here, because floating-point
|
||||
numbers are already truncated towards zero when converting them to an
|
||||
integer. This happens implicitly when the number is stored in the
|
||||
fields of each pixel.
|
||||
</p>
|
||||
<p>
|
||||
Now let's have a look at the impact of the changes: first, memory
|
||||
consumption for the image is down from 22 Megabytes to
|
||||
640 Kilobytes (400*400*4 bytes). That's a factor of 35x less! So,
|
||||
yes, tables do have a noticeable overhead. BTW: The original program
|
||||
would consume 40 Megabytes in plain Lua (on x64).
|
||||
</p>
|
||||
<p>
|
||||
Next, performance: the pure Lua version runs in 9.57 seconds (52.9
|
||||
seconds with the Lua interpreter) and the FFI version runs in 0.48
|
||||
seconds on my machine (YMMV). That's a factor of 20x faster (110x
|
||||
faster than the Lua interpreter).
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
The avid reader may notice that converting the pure Lua version over
|
||||
to use array indexes for the colors (<tt>[1]</tt> instead of
|
||||
<tt>.red</tt>, <tt>[2]</tt> instead of <tt>.green</tt> etc.) ought to
|
||||
be more compact and faster. This is certainly true (by a factor of
|
||||
~1.7x). Switching to a struct-of-arrays would help, too.
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
However the resulting code would be less idiomatic and rather
|
||||
error-prone. And it still doesn't get even close to the performance of
|
||||
the FFI version of the code. Also, high-level data structures cannot
|
||||
be easily passed to other C functions, especially I/O functions,
|
||||
without undue conversion penalties.
|
||||
</p>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,570 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>ffi.* API Functions</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
table.abitable { width: 30em; line-height: 1.2; }
|
||||
tr.abihead td { font-weight: bold; }
|
||||
td.abiparam { font-weight: bold; width: 6em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1><tt>ffi.*</tt> API Functions</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 class="current" href="ext_ffi_api.html">ffi.* API</a>
|
||||
</li><li>
|
||||
<a href="ext_ffi_semantics.html">FFI Semantics</a>
|
||||
</li></ul>
|
||||
</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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
This page describes the API functions provided by the FFI library in
|
||||
detail. It's recommended to read through the
|
||||
<a href="ext_ffi.html">introduction</a> and the
|
||||
<a href="ext_ffi_tutorial.html">FFI tutorial</a> first.
|
||||
</p>
|
||||
|
||||
<h2 id="glossary">Glossary</h2>
|
||||
<ul>
|
||||
<li><b>cdecl</b> — An abstract C type declaration (a Lua
|
||||
string).</li>
|
||||
<li><b>ctype</b> — A C type object. This is a special kind of
|
||||
<b>cdata</b> returned by <tt>ffi.typeof()</tt>. It serves as a
|
||||
<b>cdata</b> <a href="#ffi_new">constructor</a> when called.</li>
|
||||
<li><b>cdata</b> — A C data object. It holds a value of the
|
||||
corresponding <b>ctype</b>.</li>
|
||||
<li><b>ct</b> — A C type specification which can be used for
|
||||
most of the API functions. Either a <b>cdecl</b>, a <b>ctype</b> or a
|
||||
<b>cdata</b> serving as a template type.</li>
|
||||
<li><b>cb</b> — A callback object. This is a C data object
|
||||
holding a special function pointer. Calling this function from
|
||||
C code runs an associated Lua function.</li>
|
||||
<li><b>VLA</b> — A variable-length array is declared with a
|
||||
<tt>?</tt> instead of the number of elements, e.g. <tt>"int[?]"</tt>.
|
||||
The number of elements (<tt>nelem</tt>) must be given when it's
|
||||
<a href="#ffi_new">created</a>.</li>
|
||||
<li><b>VLS</b> — A variable-length struct is a <tt>struct</tt> C
|
||||
type where the last element is a <b>VLA</b>. The same rules for
|
||||
declaration and creation apply.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="decl">Declaring and Accessing External Symbols</h2>
|
||||
<p>
|
||||
External symbols must be declared first and can then be accessed by
|
||||
indexing a <a href="ext_ffi_semantics.html#clib">C library
|
||||
namespace</a>, which automatically binds the symbol to a specific
|
||||
library.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_cdef"><tt>ffi.cdef(def)</tt></h3>
|
||||
<p>
|
||||
Adds multiple C declarations for types or external symbols (named
|
||||
variables or functions). <tt>def</tt> must be a Lua string. It's
|
||||
recommended to use the syntactic sugar for string arguments as
|
||||
follows:
|
||||
</p>
|
||||
<pre class="code">
|
||||
ffi.cdef[[
|
||||
<span style="color:#00a000;">typedef struct foo { int a, b; } foo_t; // Declare a struct and typedef.
|
||||
int dofoo(foo_t *f, int n); /* Declare an external C function. */</span>
|
||||
]]
|
||||
</pre>
|
||||
<p>
|
||||
The contents of the string (the part in green above) must be a
|
||||
sequence of
|
||||
<a href="ext_ffi_semantics.html#clang">C declarations</a>,
|
||||
separated by semicolons. The trailing semicolon for a single
|
||||
declaration may be omitted.
|
||||
</p>
|
||||
<p>
|
||||
Please note that external symbols are only <em>declared</em>, but they
|
||||
are <em>not bound</em> to any specific address, yet. Binding is
|
||||
achieved with C library namespaces (see below).
|
||||
</p>
|
||||
<p style="color: #c00000;">
|
||||
C declarations are not passed through a C pre-processor,
|
||||
yet. No pre-processor tokens are allowed, except for
|
||||
<tt>#pragma pack</tt>. Replace <tt>#define</tt> in existing
|
||||
C header files with <tt>enum</tt>, <tt>static const</tt>
|
||||
or <tt>typedef</tt> and/or pass the files through an external
|
||||
C pre-processor (once). Be careful not to include unneeded or
|
||||
redundant declarations from unrelated header files.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_C"><tt>ffi.C</tt></h3>
|
||||
<p>
|
||||
This is the default C library namespace — note the
|
||||
uppercase <tt>'C'</tt>. It binds to the default set of symbols or
|
||||
libraries on the target system. These are more or less the same as a
|
||||
C compiler would offer by default, without specifying extra link
|
||||
libraries.
|
||||
</p>
|
||||
<p>
|
||||
On POSIX systems, this binds to symbols in the default or global
|
||||
namespace. This includes all exported symbols from the executable and
|
||||
any libraries loaded into the global namespace. This includes at least
|
||||
<tt>libc</tt>, <tt>libm</tt>, <tt>libdl</tt> (on Linux),
|
||||
<tt>libgcc</tt> (if compiled with GCC), as well as any exported
|
||||
symbols from the Lua/C API provided by LuaJIT itself.
|
||||
</p>
|
||||
<p>
|
||||
On Windows systems, this binds to symbols exported from the
|
||||
<tt>*.exe</tt>, the <tt>lua51.dll</tt> (i.e. the Lua/C API
|
||||
provided by LuaJIT itself), the C runtime library LuaJIT was linked
|
||||
with (<tt>msvcrt*.dll</tt>), <tt>kernel32.dll</tt>,
|
||||
<tt>user32.dll</tt> and <tt>gdi32.dll</tt>.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_load"><tt>clib = ffi.load(name [,global])</tt></h3>
|
||||
<p>
|
||||
This loads the dynamic library given by <tt>name</tt> and returns
|
||||
a new C library namespace which binds to its symbols. On POSIX
|
||||
systems, if <tt>global</tt> is <tt>true</tt>, the library symbols are
|
||||
loaded into the global namespace, too.
|
||||
</p>
|
||||
<p>
|
||||
If <tt>name</tt> is a path, the library is loaded from this path.
|
||||
Otherwise <tt>name</tt> is canonicalized in a system-dependent way and
|
||||
searched in the default search path for dynamic libraries:
|
||||
</p>
|
||||
<p>
|
||||
On POSIX systems, if the name contains no dot, the extension
|
||||
<tt>.so</tt> is appended. Also, the <tt>lib</tt> prefix is prepended
|
||||
if necessary. So <tt>ffi.load("z")</tt> looks for <tt>"libz.so"</tt>
|
||||
in the default shared library search path.
|
||||
</p>
|
||||
<p>
|
||||
On Windows systems, if the name contains no dot, the extension
|
||||
<tt>.dll</tt> is appended. So <tt>ffi.load("ws2_32")</tt> looks for
|
||||
<tt>"ws2_32.dll"</tt> in the default DLL search path.
|
||||
</p>
|
||||
|
||||
<h2 id="create">Creating cdata Objects</h2>
|
||||
<p>
|
||||
The following API functions create cdata objects (<tt>type()</tt>
|
||||
returns <tt>"cdata"</tt>). All created cdata objects are
|
||||
<a href="ext_ffi_semantics.html#gc">garbage collected</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_new"><tt>cdata = ffi.new(ct [,nelem] [,init...])<br>
|
||||
cdata = <em>ctype</em>([nelem,] [init...])</tt></h3>
|
||||
<p>
|
||||
Creates a cdata object for the given <tt>ct</tt>. VLA/VLS types
|
||||
require the <tt>nelem</tt> argument. The second syntax uses a ctype as
|
||||
a constructor and is otherwise fully equivalent.
|
||||
</p>
|
||||
<p>
|
||||
The cdata object is initialized according to the
|
||||
<a href="ext_ffi_semantics.html#init">rules for initializers</a>,
|
||||
using the optional <tt>init</tt> arguments. Excess initializers cause
|
||||
an error.
|
||||
</p>
|
||||
<p>
|
||||
Performance notice: if you want to create many objects of one kind,
|
||||
parse the cdecl only once and get its ctype with
|
||||
<tt>ffi.typeof()</tt>. Then use the ctype as a constructor repeatedly.
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
Please note that an anonymous <tt>struct</tt> declaration implicitly
|
||||
creates a new and distinguished ctype every time you use it for
|
||||
<tt>ffi.new()</tt>. This is probably <b>not</b> what you want,
|
||||
especially if you create more than one cdata object. Different anonymous
|
||||
<tt>structs</tt> are not considered assignment-compatible by the
|
||||
C standard, even though they may have the same fields! Also, they
|
||||
are considered different types by the JIT-compiler, which may cause an
|
||||
excessive number of traces. It's strongly suggested to either declare
|
||||
a named <tt>struct</tt> or <tt>typedef</tt> with <tt>ffi.cdef()</tt>
|
||||
or to create a single ctype object for an anonymous <tt>struct</tt>
|
||||
with <tt>ffi.typeof()</tt>.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_typeof"><tt>ctype = ffi.typeof(ct)</tt></h3>
|
||||
<p>
|
||||
Creates a ctype object for the given <tt>ct</tt>.
|
||||
</p>
|
||||
<p>
|
||||
This function is especially useful to parse a cdecl only once and then
|
||||
use the resulting ctype object as a <a href="#ffi_new">constructor</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_cast"><tt>cdata = ffi.cast(ct, init)</tt></h3>
|
||||
<p>
|
||||
Creates a scalar cdata object for the given <tt>ct</tt>. The cdata
|
||||
object is initialized with <tt>init</tt> using the "cast" variant of
|
||||
the <a href="ext_ffi_semantics.html#convert">C type conversion
|
||||
rules</a>.
|
||||
</p>
|
||||
<p>
|
||||
This functions is mainly useful to override the pointer compatibility
|
||||
checks or to convert pointers to addresses or vice versa.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_metatype"><tt>ctype = ffi.metatype(ct, metatable)</tt></h3>
|
||||
<p>
|
||||
Creates a ctype object for the given <tt>ct</tt> and associates it with
|
||||
a metatable. Only <tt>struct</tt>/<tt>union</tt> types, complex numbers
|
||||
and vectors are allowed. Other types may be wrapped in a
|
||||
<tt>struct</tt>, if needed.
|
||||
</p>
|
||||
<p>
|
||||
The association with a metatable is permanent and cannot be changed
|
||||
afterwards. Neither the contents of the <tt>metatable</tt> nor the
|
||||
contents of an <tt>__index</tt> table (if any) may be modified
|
||||
afterwards. The associated metatable automatically applies to all uses
|
||||
of this type, no matter how the objects are created or where they
|
||||
originate from. Note that pre-defined operations on types have
|
||||
precedence (e.g. declared field names cannot be overriden).
|
||||
</p>
|
||||
<p>
|
||||
All standard Lua metamethods are implemented. These are called directly,
|
||||
without shortcuts and on any mix of types. For binary operations, the
|
||||
left operand is checked first for a valid ctype metamethod. The
|
||||
<tt>__gc</tt> metamethod only applies to <tt>struct</tt>/<tt>union</tt>
|
||||
types and performs an implicit <a href="#ffi_gc"><tt>ffi.gc()</tt></a>
|
||||
call during creation of an instance.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_gc"><tt>cdata = ffi.gc(cdata, finalizer)</tt></h3>
|
||||
<p>
|
||||
Associates a finalizer with a pointer or aggregate cdata object. The
|
||||
cdata object is returned unchanged.
|
||||
</p>
|
||||
<p>
|
||||
This function allows safe integration of unmanaged resources into the
|
||||
automatic memory management of the LuaJIT garbage collector. Typical
|
||||
usage:
|
||||
</p>
|
||||
<pre class="code">
|
||||
local p = ffi.gc(ffi.C.malloc(n), ffi.C.free)
|
||||
...
|
||||
p = nil -- Last reference to p is gone.
|
||||
-- GC will eventually run finalizer: ffi.C.free(p)
|
||||
</pre>
|
||||
<p>
|
||||
A cdata finalizer works like the <tt>__gc</tt> metamethod for userdata
|
||||
objects: when the last reference to a cdata object is gone, the
|
||||
associated finalizer is called with the cdata object as an argument. The
|
||||
finalizer can be a Lua function or a cdata function or cdata function
|
||||
pointer. An existing finalizer can be removed by setting a <tt>nil</tt>
|
||||
finalizer, e.g. right before explicitly deleting a resource:
|
||||
</p>
|
||||
<pre class="code">
|
||||
ffi.C.free(ffi.gc(p, nil)) -- Manually free the memory.
|
||||
</pre>
|
||||
|
||||
<h2 id="info">C Type Information</h2>
|
||||
<p>
|
||||
The following API functions return information about C types.
|
||||
They are most useful for inspecting cdata objects.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_sizeof"><tt>size = ffi.sizeof(ct [,nelem])</tt></h3>
|
||||
<p>
|
||||
Returns the size of <tt>ct</tt> in bytes. Returns <tt>nil</tt> if
|
||||
the size is not known (e.g. for <tt>"void"</tt> or function types).
|
||||
Requires <tt>nelem</tt> for VLA/VLS types, except for cdata objects.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_alignof"><tt>align = ffi.alignof(ct)</tt></h3>
|
||||
<p>
|
||||
Returns the minimum required alignment for <tt>ct</tt> in bytes.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_offsetof"><tt>ofs [,bpos,bsize] = ffi.offsetof(ct, field)</tt></h3>
|
||||
<p>
|
||||
Returns the offset (in bytes) of <tt>field</tt> relative to the start
|
||||
of <tt>ct</tt>, which must be a <tt>struct</tt>. Additionally returns
|
||||
the position and the field size (in bits) for bit fields.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_istype"><tt>status = ffi.istype(ct, obj)</tt></h3>
|
||||
<p>
|
||||
Returns <tt>true</tt> if <tt>obj</tt> has the C type given by
|
||||
<tt>ct</tt>. Returns <tt>false</tt> otherwise.
|
||||
</p>
|
||||
<p>
|
||||
C type qualifiers (<tt>const</tt> etc.) are ignored. Pointers are
|
||||
checked with the standard pointer compatibility rules, but without any
|
||||
special treatment for <tt>void *</tt>. If <tt>ct</tt> specifies a
|
||||
<tt>struct</tt>/<tt>union</tt>, then a pointer to this type is accepted,
|
||||
too. Otherwise the types must match exactly.
|
||||
</p>
|
||||
<p>
|
||||
Note: this function accepts all kinds of Lua objects for the
|
||||
<tt>obj</tt> argument, but always returns <tt>false</tt> for non-cdata
|
||||
objects.
|
||||
</p>
|
||||
|
||||
<h2 id="util">Utility Functions</h2>
|
||||
|
||||
<h3 id="ffi_errno"><tt>err = ffi.errno([newerr])</tt></h3>
|
||||
<p>
|
||||
Returns the error number set by the last C function call which
|
||||
indicated an error condition. If the optional <tt>newerr</tt> argument
|
||||
is present, the error number is set to the new value and the previous
|
||||
value is returned.
|
||||
</p>
|
||||
<p>
|
||||
This function offers a portable and OS-independent way to get and set the
|
||||
error number. Note that only <em>some</em> C functions set the error
|
||||
number. And it's only significant if the function actually indicated an
|
||||
error condition (e.g. with a return value of <tt>-1</tt> or
|
||||
<tt>NULL</tt>). Otherwise, it may or may not contain any previously set
|
||||
value.
|
||||
</p>
|
||||
<p>
|
||||
You're advised to call this function only when needed and as close as
|
||||
possible after the return of the related C function. The
|
||||
<tt>errno</tt> value is preserved across hooks, memory allocations,
|
||||
invocations of the JIT compiler and other internal VM activity. The same
|
||||
applies to the value returned by <tt>GetLastError()</tt> on Windows, but
|
||||
you need to declare and call it yourself.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_string"><tt>str = ffi.string(ptr [,len])</tt></h3>
|
||||
<p>
|
||||
Creates an interned Lua string from the data pointed to by
|
||||
<tt>ptr</tt>.
|
||||
</p>
|
||||
<p>
|
||||
If the optional argument <tt>len</tt> is missing, <tt>ptr</tt> is
|
||||
converted to a <tt>"char *"</tt> and the data is assumed to be
|
||||
zero-terminated. The length of the string is computed with
|
||||
<tt>strlen()</tt>.
|
||||
</p>
|
||||
<p>
|
||||
Otherwise <tt>ptr</tt> is converted to a <tt>"void *"</tt> and
|
||||
<tt>len</tt> gives the length of the data. The data may contain
|
||||
embedded zeros and need not be byte-oriented (though this may cause
|
||||
endianess issues).
|
||||
</p>
|
||||
<p>
|
||||
This function is mainly useful to convert (temporary)
|
||||
<tt>"const char *"</tt> pointers returned by
|
||||
C functions to Lua strings and store them or pass them to other
|
||||
functions expecting a Lua string. The Lua string is an (interned) copy
|
||||
of the data and bears no relation to the original data area anymore.
|
||||
Lua strings are 8 bit clean and may be used to hold arbitrary,
|
||||
non-character data.
|
||||
</p>
|
||||
<p>
|
||||
Performance notice: it's faster to pass the length of the string, if
|
||||
it's known. E.g. when the length is returned by a C call like
|
||||
<tt>sprintf()</tt>.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_copy"><tt>ffi.copy(dst, src, len)<br>
|
||||
ffi.copy(dst, str)</tt></h3>
|
||||
<p>
|
||||
Copies the data pointed to by <tt>src</tt> to <tt>dst</tt>.
|
||||
<tt>dst</tt> is converted to a <tt>"void *"</tt> and <tt>src</tt>
|
||||
is converted to a <tt>"const void *"</tt>.
|
||||
</p>
|
||||
<p>
|
||||
In the first syntax, <tt>len</tt> gives the number of bytes to copy.
|
||||
Caveat: if <tt>src</tt> is a Lua string, then <tt>len</tt> must not
|
||||
exceed <tt>#src+1</tt>.
|
||||
</p>
|
||||
<p>
|
||||
In the second syntax, the source of the copy must be a Lua string. All
|
||||
bytes of the string <em>plus a zero-terminator</em> are copied to
|
||||
<tt>dst</tt> (i.e. <tt>#src+1</tt> bytes).
|
||||
</p>
|
||||
<p>
|
||||
Performance notice: <tt>ffi.copy()</tt> may be used as a faster
|
||||
(inlinable) replacement for the C library functions
|
||||
<tt>memcpy()</tt>, <tt>strcpy()</tt> and <tt>strncpy()</tt>.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_fill"><tt>ffi.fill(dst, len [,c])</tt></h3>
|
||||
<p>
|
||||
Fills the data pointed to by <tt>dst</tt> with <tt>len</tt> constant
|
||||
bytes, given by <tt>c</tt>. If <tt>c</tt> is omitted, the data is
|
||||
zero-filled.
|
||||
</p>
|
||||
<p>
|
||||
Performance notice: <tt>ffi.fill()</tt> may be used as a faster
|
||||
(inlinable) replacement for the C library function
|
||||
<tt>memset(dst, c, len)</tt>. Please note the different
|
||||
order of arguments!
|
||||
</p>
|
||||
|
||||
<h2 id="target">Target-specific Information</h2>
|
||||
|
||||
<h3 id="ffi_abi"><tt>status = ffi.abi(param)</tt></h3>
|
||||
<p>
|
||||
Returns <tt>true</tt> if <tt>param</tt> (a Lua string) applies for the
|
||||
target ABI (Application Binary Interface). Returns <tt>false</tt>
|
||||
otherwise. The following parameters are currently defined:
|
||||
</p>
|
||||
<table class="abitable">
|
||||
<tr class="abihead">
|
||||
<td class="abiparam">Parameter</td>
|
||||
<td class="abidesc">Description</td>
|
||||
</tr>
|
||||
<tr class="odd separate">
|
||||
<td class="abiparam">32bit</td><td class="abidesc">32 bit architecture</td></tr>
|
||||
<tr class="even">
|
||||
<td class="abiparam">64bit</td><td class="abidesc">64 bit architecture</td></tr>
|
||||
<tr class="odd separate">
|
||||
<td class="abiparam">le</td><td class="abidesc">Little-endian architecture</td></tr>
|
||||
<tr class="even">
|
||||
<td class="abiparam">be</td><td class="abidesc">Big-endian architecture</td></tr>
|
||||
<tr class="odd separate">
|
||||
<td class="abiparam">fpu</td><td class="abidesc">Target has a hardware FPU</td></tr>
|
||||
<tr class="even">
|
||||
<td class="abiparam">softfp</td><td class="abidesc">softfp calling conventions</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="abiparam">hardfp</td><td class="abidesc">hardfp calling conventions</td></tr>
|
||||
<tr class="even separate">
|
||||
<td class="abiparam">eabi</td><td class="abidesc">EABI variant of the standard ABI</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="abiparam">win</td><td class="abidesc">Windows variant of the standard ABI</td></tr>
|
||||
<tr class="even">
|
||||
<td class="abiparam">gc64</td><td class="abidesc">64 bit GC references</td></tr>
|
||||
</table>
|
||||
|
||||
<h3 id="ffi_os"><tt>ffi.os</tt></h3>
|
||||
<p>
|
||||
Contains the target OS name. Same contents as
|
||||
<a href="ext_jit.html#jit_os"><tt>jit.os</tt></a>.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi_arch"><tt>ffi.arch</tt></h3>
|
||||
<p>
|
||||
Contains the target architecture name. Same contents as
|
||||
<a href="ext_jit.html#jit_arch"><tt>jit.arch</tt></a>.
|
||||
</p>
|
||||
|
||||
<h2 id="callback">Methods for Callbacks</h2>
|
||||
<p>
|
||||
The C types for <a href="ext_ffi_semantics.html#callback">callbacks</a>
|
||||
have some extra methods:
|
||||
</p>
|
||||
|
||||
<h3 id="callback_free"><tt>cb:free()</tt></h3>
|
||||
<p>
|
||||
Free the resources associated with a callback. The associated Lua
|
||||
function is unanchored and may be garbage collected. The callback
|
||||
function pointer is no longer valid and must not be called anymore
|
||||
(it may be reused by a subsequently created callback).
|
||||
</p>
|
||||
|
||||
<h3 id="callback_set"><tt>cb:set(func)</tt></h3>
|
||||
<p>
|
||||
Associate a new Lua function with a callback. The C type of the
|
||||
callback and the callback function pointer are unchanged.
|
||||
</p>
|
||||
<p>
|
||||
This method is useful to dynamically switch the receiver of callbacks
|
||||
without creating a new callback each time and registering it again (e.g.
|
||||
with a GUI library).
|
||||
</p>
|
||||
|
||||
<h2 id="extended">Extended Standard Library Functions</h2>
|
||||
<p>
|
||||
The following standard library functions have been extended to work
|
||||
with cdata objects:
|
||||
</p>
|
||||
|
||||
<h3 id="tonumber"><tt>n = tonumber(cdata)</tt></h3>
|
||||
<p>
|
||||
Converts a number cdata object to a <tt>double</tt> and returns it as
|
||||
a Lua number. This is particularly useful for boxed 64 bit
|
||||
integer values. Caveat: this conversion may incur a precision loss.
|
||||
</p>
|
||||
|
||||
<h3 id="tostring"><tt>s = tostring(cdata)</tt></h3>
|
||||
<p>
|
||||
Returns a string representation of the value of 64 bit integers
|
||||
(<tt><b>"</b>nnn<b>LL"</b></tt> or <tt><b>"</b>nnn<b>ULL"</b></tt>) or
|
||||
complex numbers (<tt><b>"</b>re±im<b>i"</b></tt>). Otherwise
|
||||
returns a string representation of the C type of a ctype object
|
||||
(<tt><b>"ctype<</b>type<b>>"</b></tt>) or a cdata object
|
||||
(<tt><b>"cdata<</b>type<b>>: </b>address"</tt>), unless you
|
||||
override it with a <tt>__tostring</tt> metamethod (see
|
||||
<a href="#ffi_metatype"><tt>ffi.metatype()</tt></a>).
|
||||
</p>
|
||||
|
||||
<h3 id="pairs"><tt>iter, obj, start = pairs(cdata)<br>
|
||||
iter, obj, start = ipairs(cdata)<br></tt></h3>
|
||||
<p>
|
||||
Calls the <tt>__pairs</tt> or <tt>__ipairs</tt> metamethod of the
|
||||
corresponding ctype.
|
||||
</p>
|
||||
|
||||
<h2 id="literals">Extensions to the Lua Parser</h2>
|
||||
<p>
|
||||
The parser for Lua source code treats numeric literals with the
|
||||
suffixes <tt>LL</tt> or <tt>ULL</tt> as signed or unsigned 64 bit
|
||||
integers. Case doesn't matter, but uppercase is recommended for
|
||||
readability. It handles decimal (<tt>42LL</tt>), hexadecimal
|
||||
(<tt>0x2aLL</tt>) and binary (<tt>0b101010LL</tt>) literals.
|
||||
</p>
|
||||
<p>
|
||||
The imaginary part of complex numbers can be specified by suffixing
|
||||
number literals with <tt>i</tt> or <tt>I</tt>, e.g. <tt>12.5i</tt>.
|
||||
Caveat: you'll need to use <tt>1i</tt> to get an imaginary part with
|
||||
the value one, since <tt>i</tt> itself still refers to a variable
|
||||
named <tt>i</tt>.
|
||||
</p>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,603 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>FFI Tutorial</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
table.idiomtable { font-size: 90%; line-height: 1.2; }
|
||||
table.idiomtable tt { font-size: 100%; }
|
||||
table.idiomtable td { vertical-align: top; }
|
||||
tr.idiomhead td { font-weight: bold; }
|
||||
td.idiomlua b { font-weight: normal; color: #2142bf; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>FFI Tutorial</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 class="current" 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 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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
This page is intended to give you an overview of the features of the FFI
|
||||
library by presenting a few use cases and guidelines.
|
||||
</p>
|
||||
<p>
|
||||
This page makes no attempt to explain all of the FFI library, though.
|
||||
You'll want to have a look at the <a href="ext_ffi_api.html">ffi.* API
|
||||
function reference</a> and the <a href="ext_ffi_semantics.html">FFI
|
||||
semantics</a> to learn more.
|
||||
</p>
|
||||
|
||||
<h2 id="load">Loading the FFI Library</h2>
|
||||
<p>
|
||||
The FFI library is built into LuaJIT by default, but it's not loaded
|
||||
and initialized by default. The suggested way to use the FFI library
|
||||
is to add the following to the start of every Lua file that needs one
|
||||
of its functions:
|
||||
</p>
|
||||
<pre class="code">
|
||||
local ffi = require("ffi")
|
||||
</pre>
|
||||
<p>
|
||||
Please note this doesn't define an <tt>ffi</tt> variable in the table
|
||||
of globals — you really need to use the local variable. The
|
||||
<tt>require</tt> function ensures the library is only loaded once.
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
Note: If you want to experiment with the FFI from the interactive prompt
|
||||
of the command line executable, omit the <tt>local</tt>, as it doesn't
|
||||
preserve local variables across lines.
|
||||
</p>
|
||||
|
||||
<h2 id="sleep">Accessing Standard System Functions</h2>
|
||||
<p>
|
||||
The following code explains how to access standard system functions.
|
||||
We slowly print two lines of dots by sleeping for 10 milliseconds
|
||||
after each dot:
|
||||
</p>
|
||||
<pre class="code mark">
|
||||
<span class="codemark">
|
||||
①
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
②
|
||||
③
|
||||
④
|
||||
|
||||
|
||||
|
||||
⑤
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
⑥</span>local ffi = require("ffi")
|
||||
ffi.cdef[[
|
||||
<span style="color:#00a000;">void Sleep(int ms);
|
||||
int poll(struct pollfd *fds, unsigned long nfds, int timeout);</span>
|
||||
]]
|
||||
|
||||
local sleep
|
||||
if ffi.os == "Windows" then
|
||||
function sleep(s)
|
||||
ffi.C.Sleep(s*1000)
|
||||
end
|
||||
else
|
||||
function sleep(s)
|
||||
ffi.C.poll(nil, 0, s*1000)
|
||||
end
|
||||
end
|
||||
|
||||
for i=1,160 do
|
||||
io.write("."); io.flush()
|
||||
sleep(0.01)
|
||||
end
|
||||
io.write("\n")
|
||||
</pre>
|
||||
<p>
|
||||
Here's the step-by-step explanation:
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">①</span> This defines the
|
||||
C library functions we're going to use. The part inside the
|
||||
double-brackets (in green) is just standard C syntax. You can
|
||||
usually get this info from the C header files or the
|
||||
documentation provided by each C library or C compiler.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">②</span> The difficulty we're
|
||||
facing here, is that there are different standards to choose from.
|
||||
Windows has a simple <tt>Sleep()</tt> function. On other systems there
|
||||
are a variety of functions available to achieve sub-second sleeps, but
|
||||
with no clear consensus. Thankfully <tt>poll()</tt> can be used for
|
||||
this task, too, and it's present on most non-Windows systems. The
|
||||
check for <tt>ffi.os</tt> makes sure we use the Windows-specific
|
||||
function only on Windows systems.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">③</span> Here we're wrapping the
|
||||
call to the C function in a Lua function. This isn't strictly
|
||||
necessary, but it's helpful to deal with system-specific issues only
|
||||
in one part of the code. The way we're wrapping it ensures the check
|
||||
for the OS is only done during initialization and not for every call.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">④</span> A more subtle point is
|
||||
that we defined our <tt>sleep()</tt> function (for the sake of this
|
||||
example) as taking the number of seconds, but accepting fractional
|
||||
seconds. Multiplying this by 1000 gets us milliseconds, but that still
|
||||
leaves it a Lua number, which is a floating-point value. Alas, the
|
||||
<tt>Sleep()</tt> function only accepts an integer value. Luckily for
|
||||
us, the FFI library automatically performs the conversion when calling
|
||||
the function (truncating the FP value towards zero, like in C).
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
Some readers will notice that <tt>Sleep()</tt> is part of
|
||||
<tt>KERNEL32.DLL</tt> and is also a <tt>stdcall</tt> function. So how
|
||||
can this possibly work? The FFI library provides the <tt>ffi.C</tt>
|
||||
default C library namespace, which allows calling functions from
|
||||
the default set of libraries, like a C compiler would. Also, the
|
||||
FFI library automatically detects <tt>stdcall</tt> functions, so you
|
||||
don't need to declare them as such.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">⑤</span> The <tt>poll()</tt>
|
||||
function takes a couple more arguments we're not going to use. You can
|
||||
simply use <tt>nil</tt> to pass a <tt>NULL</tt> pointer and <tt>0</tt>
|
||||
for the <tt>nfds</tt> parameter. Please note that the
|
||||
number <tt>0</tt> <em>does not convert to a pointer value</em>,
|
||||
unlike in C++. You really have to pass pointers to pointer arguments
|
||||
and numbers to number arguments.
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
The page on <a href="ext_ffi_semantics.html">FFI semantics</a> has all
|
||||
of the gory details about
|
||||
<a href="ext_ffi_semantics.html#convert">conversions between Lua
|
||||
objects and C types</a>. For the most part you don't have to deal
|
||||
with this, as it's performed automatically and it's carefully designed
|
||||
to bridge the semantic differences between Lua and C.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">⑥</span> Now that we have defined
|
||||
our own <tt>sleep()</tt> function, we can just call it from plain Lua
|
||||
code. That wasn't so bad, huh? Turning these boring animated dots into
|
||||
a fascinating best-selling game is left as an exercise for the reader.
|
||||
:-)
|
||||
</p>
|
||||
|
||||
<h2 id="zlib">Accessing the zlib Compression Library</h2>
|
||||
<p>
|
||||
The following code shows how to access the <a
|
||||
href="http://zlib.net/">zlib</a> compression library from Lua code.
|
||||
We'll define two convenience wrapper functions that take a string and
|
||||
compress or uncompress it to another string:
|
||||
</p>
|
||||
<pre class="code mark">
|
||||
<span class="codemark">
|
||||
①
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
②
|
||||
|
||||
|
||||
③
|
||||
|
||||
④
|
||||
|
||||
|
||||
⑤
|
||||
|
||||
|
||||
⑥
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
⑦</span>local ffi = require("ffi")
|
||||
ffi.cdef[[
|
||||
<span style="color:#00a000;">unsigned long compressBound(unsigned long sourceLen);
|
||||
int compress2(uint8_t *dest, unsigned long *destLen,
|
||||
const uint8_t *source, unsigned long sourceLen, int level);
|
||||
int uncompress(uint8_t *dest, unsigned long *destLen,
|
||||
const uint8_t *source, unsigned long sourceLen);</span>
|
||||
]]
|
||||
local zlib = ffi.load(ffi.os == "Windows" and "zlib1" or "z")
|
||||
|
||||
local function compress(txt)
|
||||
local n = zlib.compressBound(#txt)
|
||||
local buf = ffi.new("uint8_t[?]", n)
|
||||
local buflen = ffi.new("unsigned long[1]", n)
|
||||
local res = zlib.compress2(buf, buflen, txt, #txt, 9)
|
||||
assert(res == 0)
|
||||
return ffi.string(buf, buflen[0])
|
||||
end
|
||||
|
||||
local function uncompress(comp, n)
|
||||
local buf = ffi.new("uint8_t[?]", n)
|
||||
local buflen = ffi.new("unsigned long[1]", n)
|
||||
local res = zlib.uncompress(buf, buflen, comp, #comp)
|
||||
assert(res == 0)
|
||||
return ffi.string(buf, buflen[0])
|
||||
end
|
||||
|
||||
-- Simple test code.
|
||||
local txt = string.rep("abcd", 1000)
|
||||
print("Uncompressed size: ", #txt)
|
||||
local c = compress(txt)
|
||||
print("Compressed size: ", #c)
|
||||
local txt2 = uncompress(c, #txt)
|
||||
assert(txt2 == txt)
|
||||
</pre>
|
||||
<p>
|
||||
Here's the step-by-step explanation:
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">①</span> This defines some of the
|
||||
C functions provided by zlib. For the sake of this example, some
|
||||
type indirections have been reduced and it uses the pre-defined
|
||||
fixed-size integer types, while still adhering to the zlib API/ABI.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">②</span> This loads the zlib shared
|
||||
library. On POSIX systems it's named <tt>libz.so</tt> and usually
|
||||
comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any
|
||||
missing standard prefixes/suffixes, we can simply load the
|
||||
<tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and
|
||||
you'll have to download it first from the
|
||||
<a href="http://zlib.net/"><span class="ext">»</span> zlib site</a>. The check for
|
||||
<tt>ffi.os</tt> makes sure we pass the right name to
|
||||
<tt>ffi.load()</tt>.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">③</span> First, the maximum size of
|
||||
the compression buffer is obtained by calling the
|
||||
<tt>zlib.compressBound</tt> function with the length of the
|
||||
uncompressed string. The next line allocates a byte buffer of this
|
||||
size. The <tt>[?]</tt> in the type specification indicates a
|
||||
variable-length array (VLA). The actual number of elements of this
|
||||
array is given as the 2nd argument to <tt>ffi.new()</tt>.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">④</span> This may look strange at
|
||||
first, but have a look at the declaration of the <tt>compress2</tt>
|
||||
function from zlib: the destination length is defined as a pointer!
|
||||
This is because you pass in the maximum buffer size and get back the
|
||||
actual length that was used.
|
||||
</p>
|
||||
<p>
|
||||
In C you'd pass in the address of a local variable
|
||||
(<tt>&buflen</tt>). But since there's no address-of operator in
|
||||
Lua, we'll just pass in a one-element array. Conveniently it can be
|
||||
initialized with the maximum buffer size in one step. Calling the
|
||||
actual <tt>zlib.compress2</tt> function is then straightforward.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">⑤</span> We want to return the
|
||||
compressed data as a Lua string, so we'll use <tt>ffi.string()</tt>.
|
||||
It needs a pointer to the start of the data and the actual length. The
|
||||
length has been returned in the <tt>buflen</tt> array, so we'll just
|
||||
get it from there.
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
Note that since the function returns now, the <tt>buf</tt> and
|
||||
<tt>buflen</tt> variables will eventually be garbage collected. This
|
||||
is fine, because <tt>ffi.string()</tt> has copied the contents to a
|
||||
newly created (interned) Lua string. If you plan to call this function
|
||||
lots of times, consider reusing the buffers and/or handing back the
|
||||
results in buffers instead of strings. This will reduce the overhead
|
||||
for garbage collection and string interning.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">⑥</span> The <tt>uncompress</tt>
|
||||
functions does the exact opposite of the <tt>compress</tt> function.
|
||||
The compressed data doesn't include the size of the original string,
|
||||
so this needs to be passed in. Otherwise no surprises here.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">⑦</span> The code, that makes use
|
||||
of the functions we just defined, is just plain Lua code. It doesn't
|
||||
need to know anything about the LuaJIT FFI — the convenience
|
||||
wrapper functions completely hide it.
|
||||
</p>
|
||||
<p>
|
||||
One major advantage of the LuaJIT FFI is that you are now able to
|
||||
write those wrappers <em>in Lua</em>. And at a fraction of the time it
|
||||
would cost you to create an extra C module using the Lua/C API.
|
||||
Many of the simpler C functions can probably be used directly
|
||||
from your Lua code, without any wrappers.
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
Side note: the zlib API uses the <tt>long</tt> type for passing
|
||||
lengths and sizes around. But all those zlib functions actually only
|
||||
deal with 32 bit values. This is an unfortunate choice for a
|
||||
public API, but may be explained by zlib's history — we'll just
|
||||
have to deal with it.
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
First, you should know that a <tt>long</tt> is a 64 bit type e.g.
|
||||
on POSIX/x64 systems, but a 32 bit type on Windows/x64 and on
|
||||
32 bit systems. Thus a <tt>long</tt> result can be either a plain
|
||||
Lua number or a boxed 64 bit integer cdata object, depending on
|
||||
the target system.
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
Ok, so the <tt>ffi.*</tt> functions generally accept cdata objects
|
||||
wherever you'd want to use a number. That's why we get a away with
|
||||
passing <tt>n</tt> to <tt>ffi.string()</tt> above. But other Lua
|
||||
library functions or modules don't know how to deal with this. So for
|
||||
maximum portability one needs to use <tt>tonumber()</tt> on returned
|
||||
<tt>long</tt> results before passing them on. Otherwise the
|
||||
application might work on some systems, but would fail in a POSIX/x64
|
||||
environment.
|
||||
</p>
|
||||
|
||||
<h2 id="metatype">Defining Metamethods for a C Type</h2>
|
||||
<p>
|
||||
The following code explains how to define metamethods for a C type.
|
||||
We define a simple point type and add some operations to it:
|
||||
</p>
|
||||
<pre class="code mark">
|
||||
<span class="codemark">
|
||||
①
|
||||
|
||||
|
||||
|
||||
②
|
||||
|
||||
③
|
||||
|
||||
④
|
||||
|
||||
|
||||
|
||||
⑤
|
||||
|
||||
⑥</span>local ffi = require("ffi")
|
||||
ffi.cdef[[
|
||||
<span style="color:#00a000;">typedef struct { double x, y; } point_t;</span>
|
||||
]]
|
||||
|
||||
local point
|
||||
local mt = {
|
||||
__add = function(a, b) return point(a.x+b.x, a.y+b.y) end,
|
||||
__len = function(a) return math.sqrt(a.x*a.x + a.y*a.y) end,
|
||||
__index = {
|
||||
area = function(a) return a.x*a.x + a.y*a.y end,
|
||||
},
|
||||
}
|
||||
point = ffi.metatype("point_t", mt)
|
||||
|
||||
local a = point(3, 4)
|
||||
print(a.x, a.y) --> 3 4
|
||||
print(#a) --> 5
|
||||
print(a:area()) --> 25
|
||||
local b = a + point(0.5, 8)
|
||||
print(#b) --> 12.5
|
||||
</pre>
|
||||
<p>
|
||||
Here's the step-by-step explanation:
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">①</span> This defines the C type for a
|
||||
two-dimensional point object.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">②</span> We have to declare the variable
|
||||
holding the point constructor first, because it's used inside of a
|
||||
metamethod.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">③</span> Let's define an <tt>__add</tt>
|
||||
metamethod which adds the coordinates of two points and creates a new
|
||||
point object. For simplicity, this function assumes that both arguments
|
||||
are points. But it could be any mix of objects, if at least one operand
|
||||
is of the required type (e.g. adding a point plus a number or vice
|
||||
versa). Our <tt>__len</tt> metamethod returns the distance of a point to
|
||||
the origin.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">④</span> If we run out of operators, we can
|
||||
define named methods, too. Here the <tt>__index</tt> table defines an
|
||||
<tt>area</tt> function. For custom indexing needs, one might want to
|
||||
define <tt>__index</tt> and <tt>__newindex</tt> <em>functions</em> instead.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">⑤</span> This associates the metamethods with
|
||||
our C type. This only needs to be done once. For convenience, a
|
||||
constructor is returned by
|
||||
<a href="ext_ffi_api.html#ffi_metatype"><tt>ffi.metatype()</tt></a>.
|
||||
We're not required to use it, though. The original C type can still
|
||||
be used e.g. to create an array of points. The metamethods automatically
|
||||
apply to any and all uses of this type.
|
||||
</p>
|
||||
<p>
|
||||
Please note that the association with a metatable is permanent and
|
||||
<b>the metatable must not be modified afterwards!</b> Ditto for the
|
||||
<tt>__index</tt> table.
|
||||
</p>
|
||||
<p>
|
||||
<span class="mark">⑥</span> Here are some simple usage examples
|
||||
for the point type and their expected results. The pre-defined
|
||||
operations (such as <tt>a.x</tt>) can be freely mixed with the newly
|
||||
defined metamethods. Note that <tt>area</tt> is a method and must be
|
||||
called with the Lua syntax for methods: <tt>a:area()</tt>, not
|
||||
<tt>a.area()</tt>.
|
||||
</p>
|
||||
<p>
|
||||
The C type metamethod mechanism is most useful when used in
|
||||
conjunction with C libraries that are written in an object-oriented
|
||||
style. Creators return a pointer to a new instance and methods take an
|
||||
instance pointer as the first argument. Sometimes you can just point
|
||||
<tt>__index</tt> to the library namespace and <tt>__gc</tt> to the
|
||||
destructor and you're done. But often enough you'll want to add
|
||||
convenience wrappers, e.g. to return actual Lua strings or when
|
||||
returning multiple values.
|
||||
</p>
|
||||
<p>
|
||||
Some C libraries only declare instance pointers as an opaque
|
||||
<tt>void *</tt> type. In this case you can use a fake type for all
|
||||
declarations, e.g. a pointer to a named (incomplete) struct will do:
|
||||
<tt>typedef struct foo_type *foo_handle</tt>. The C side doesn't
|
||||
know what you declare with the LuaJIT FFI, but as long as the underlying
|
||||
types are compatible, everything still works.
|
||||
</p>
|
||||
|
||||
<h2 id="idioms">Translating C Idioms</h2>
|
||||
<p>
|
||||
Here's a list of common C idioms and their translation to the
|
||||
LuaJIT FFI:
|
||||
</p>
|
||||
<table class="idiomtable">
|
||||
<tr class="idiomhead">
|
||||
<td class="idiomdesc">Idiom</td>
|
||||
<td class="idiomc">C code</td>
|
||||
<td class="idiomlua">Lua code</td>
|
||||
</tr>
|
||||
<tr class="odd separate">
|
||||
<td class="idiomdesc">Pointer dereference<br><tt>int *p;</tt></td><td class="idiomc"><tt>x = *p;<br>*p = y;</tt></td><td class="idiomlua"><tt>x = <b>p[0]</b><br><b>p[0]</b> = y</tt></td></tr>
|
||||
<tr class="even">
|
||||
<td class="idiomdesc">Pointer indexing<br><tt>int i, *p;</tt></td><td class="idiomc"><tt>x = p[i];<br>p[i+1] = y;</tt></td><td class="idiomlua"><tt>x = p[i]<br>p[i+1] = y</tt></td></tr>
|
||||
<tr class="odd">
|
||||
<td class="idiomdesc">Array indexing<br><tt>int i, a[];</tt></td><td class="idiomc"><tt>x = a[i];<br>a[i+1] = y;</tt></td><td class="idiomlua"><tt>x = a[i]<br>a[i+1] = y</tt></td></tr>
|
||||
<tr class="even separate">
|
||||
<td class="idiomdesc"><tt>struct</tt>/<tt>union</tt> dereference<br><tt>struct foo s;</tt></td><td class="idiomc"><tt>x = s.field;<br>s.field = y;</tt></td><td class="idiomlua"><tt>x = s.field<br>s.field = y</tt></td></tr>
|
||||
<tr class="odd">
|
||||
<td class="idiomdesc"><tt>struct</tt>/<tt>union</tt> pointer deref.<br><tt>struct foo *sp;</tt></td><td class="idiomc"><tt>x = sp->field;<br>sp->field = y;</tt></td><td class="idiomlua"><tt>x = <b>s.field</b><br><b>s.field</b> = y</tt></td></tr>
|
||||
<tr class="even separate">
|
||||
<td class="idiomdesc">Pointer arithmetic<br><tt>int i, *p;</tt></td><td class="idiomc"><tt>x = p + i;<br>y = p - i;</tt></td><td class="idiomlua"><tt>x = p + i<br>y = p - i</tt></td></tr>
|
||||
<tr class="odd">
|
||||
<td class="idiomdesc">Pointer difference<br><tt>int *p1, *p2;</tt></td><td class="idiomc"><tt>x = p1 - p2;</tt></td><td class="idiomlua"><tt>x = p1 - p2</tt></td></tr>
|
||||
<tr class="even">
|
||||
<td class="idiomdesc">Array element pointer<br><tt>int i, a[];</tt></td><td class="idiomc"><tt>x = &a[i];</tt></td><td class="idiomlua"><tt>x = <b>a+i</b></tt></td></tr>
|
||||
<tr class="odd">
|
||||
<td class="idiomdesc">Cast pointer to address<br><tt>int *p;</tt></td><td class="idiomc"><tt>x = (intptr_t)p;</tt></td><td class="idiomlua"><tt>x = <b>tonumber(<br> ffi.cast("intptr_t",<br> p))</b></tt></td></tr>
|
||||
<tr class="even separate">
|
||||
<td class="idiomdesc">Functions with outargs<br><tt>void foo(int *inoutlen);</tt></td><td class="idiomc"><tt>int len = x;<br>foo(&len);<br>y = len;</tt></td><td class="idiomlua"><tt><b>local len =<br> ffi.new("int[1]", x)<br>foo(len)<br>y = len[0]</b></tt></td></tr>
|
||||
<tr class="odd">
|
||||
<td class="idiomdesc"><a href="ext_ffi_semantics.html#convert_vararg">Vararg conversions</a><br><tt>int printf(char *fmt, ...);</tt></td><td class="idiomc"><tt>printf("%g", 1.0);<br>printf("%d", 1);<br> </tt></td><td class="idiomlua"><tt>printf("%g", 1);<br>printf("%d",<br> <b>ffi.new("int", 1)</b>)</tt></td></tr>
|
||||
</table>
|
||||
|
||||
<h2 id="cache">To Cache or Not to Cache</h2>
|
||||
<p>
|
||||
It's a common Lua idiom to cache library functions in local variables
|
||||
or upvalues, e.g.:
|
||||
</p>
|
||||
<pre class="code">
|
||||
local byte, char = string.byte, string.char
|
||||
local function foo(x)
|
||||
return char(byte(x)+1)
|
||||
end
|
||||
</pre>
|
||||
<p>
|
||||
This replaces several hash-table lookups with a (faster) direct use of
|
||||
a local or an upvalue. This is less important with LuaJIT, since the
|
||||
JIT compiler optimizes hash-table lookups a lot and is even able to
|
||||
hoist most of them out of the inner loops. It can't eliminate
|
||||
<em>all</em> of them, though, and it saves some typing for often-used
|
||||
functions. So there's still a place for this, even with LuaJIT.
|
||||
</p>
|
||||
<p>
|
||||
The situation is a bit different with C function calls via the
|
||||
FFI library. The JIT compiler has special logic to eliminate <em>all
|
||||
of the lookup overhead</em> for functions resolved from a
|
||||
<a href="ext_ffi_semantics.html#clib">C library namespace</a>!
|
||||
Thus it's not helpful and actually counter-productive to cache
|
||||
individual C functions like this:
|
||||
</p>
|
||||
<pre class="code">
|
||||
local <b>funca</b>, <b>funcb</b> = ffi.C.funca, ffi.C.funcb -- <span style="color:#c00000;">Not helpful!</span>
|
||||
local function foo(x, n)
|
||||
for i=1,n do <b>funcb</b>(<b>funca</b>(x, i), 1) end
|
||||
end
|
||||
</pre>
|
||||
<p>
|
||||
This turns them into indirect calls and generates bigger and slower
|
||||
machine code. Instead you'll want to cache the namespace itself and
|
||||
rely on the JIT compiler to eliminate the lookups:
|
||||
</p>
|
||||
<pre class="code">
|
||||
local <b>C</b> = ffi.C -- <span style="color:#00a000;">Instead use this!</span>
|
||||
local function foo(x, n)
|
||||
for i=1,n do <b>C.funcb</b>(<b>C.funca</b>(x, i), 1) end
|
||||
end
|
||||
</pre>
|
||||
<p>
|
||||
This generates both shorter and faster code. So <b>don't cache
|
||||
C functions</b>, but <b>do</b> cache namespaces! Most often the
|
||||
namespace is already in a local variable at an outer scope, e.g. from
|
||||
<tt>local lib = ffi.load(...)</tt>. Note that copying
|
||||
it to a local variable in the function scope is unnecessary.
|
||||
</p>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,201 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>jit.* Library</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1><tt>jit.*</tt> Library</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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_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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
The functions in this built-in module control the behavior of the JIT
|
||||
compiler engine. Note that JIT-compilation is fully automatic —
|
||||
you probably won't need to use any of the following functions unless
|
||||
you have special needs.
|
||||
</p>
|
||||
|
||||
<h3 id="jit_onoff"><tt>jit.on()<br>
|
||||
jit.off()</tt></h3>
|
||||
<p>
|
||||
Turns the whole JIT compiler on (default) or off.
|
||||
</p>
|
||||
<p>
|
||||
These functions are typically used with the command line options
|
||||
<tt>-j on</tt> or <tt>-j off</tt>.
|
||||
</p>
|
||||
|
||||
<h3 id="jit_flush"><tt>jit.flush()</tt></h3>
|
||||
<p>
|
||||
Flushes the whole cache of compiled code.
|
||||
</p>
|
||||
|
||||
<h3 id="jit_onoff_func"><tt>jit.on(func|true [,true|false])<br>
|
||||
jit.off(func|true [,true|false])<br>
|
||||
jit.flush(func|true [,true|false])</tt></h3>
|
||||
<p>
|
||||
<tt>jit.on</tt> enables JIT compilation for a Lua function (this is
|
||||
the default).
|
||||
</p>
|
||||
<p>
|
||||
<tt>jit.off</tt> disables JIT compilation for a Lua function and
|
||||
flushes any already compiled code from the code cache.
|
||||
</p>
|
||||
<p>
|
||||
<tt>jit.flush</tt> flushes the code, but doesn't affect the
|
||||
enable/disable status.
|
||||
</p>
|
||||
<p>
|
||||
The current function, i.e. the Lua function calling this library
|
||||
function, can also be specified by passing <tt>true</tt> as the first
|
||||
argument.
|
||||
</p>
|
||||
<p>
|
||||
If the second argument is <tt>true</tt>, JIT compilation is also
|
||||
enabled, disabled or flushed recursively for all sub-functions of a
|
||||
function. With <tt>false</tt> only the sub-functions are affected.
|
||||
</p>
|
||||
<p>
|
||||
The <tt>jit.on</tt> and <tt>jit.off</tt> functions only set a flag
|
||||
which is checked when the function is about to be compiled. They do
|
||||
not trigger immediate compilation.
|
||||
</p>
|
||||
<p>
|
||||
Typical usage is <tt>jit.off(true, true)</tt> in the main chunk
|
||||
of a module to turn off JIT compilation for the whole module for
|
||||
debugging purposes.
|
||||
</p>
|
||||
|
||||
<h3 id="jit_flush_tr"><tt>jit.flush(tr)</tt></h3>
|
||||
<p>
|
||||
Flushes the root trace, specified by its number, and all of its side
|
||||
traces from the cache. The code for the trace will be retained as long
|
||||
as there are any other traces which link to it.
|
||||
</p>
|
||||
|
||||
<h3 id="jit_status"><tt>status, ... = jit.status()</tt></h3>
|
||||
<p>
|
||||
Returns the current status of the JIT compiler. The first result is
|
||||
either <tt>true</tt> or <tt>false</tt> if the JIT compiler is turned
|
||||
on or off. The remaining results are strings for CPU-specific features
|
||||
and enabled optimizations.
|
||||
</p>
|
||||
|
||||
<h3 id="jit_version"><tt>jit.version</tt></h3>
|
||||
<p>
|
||||
Contains the LuaJIT version string.
|
||||
</p>
|
||||
|
||||
<h3 id="jit_version_num"><tt>jit.version_num</tt></h3>
|
||||
<p>
|
||||
Contains the version number of the LuaJIT core. Version xx.yy.zz
|
||||
is represented by the decimal number xxyyzz.
|
||||
</p>
|
||||
|
||||
<h3 id="jit_os"><tt>jit.os</tt></h3>
|
||||
<p>
|
||||
Contains the target OS name:
|
||||
"Windows", "Linux", "OSX", "BSD", "POSIX" or "Other".
|
||||
</p>
|
||||
|
||||
<h3 id="jit_arch"><tt>jit.arch</tt></h3>
|
||||
<p>
|
||||
Contains the target architecture name:
|
||||
"x86", "x64", "arm", "arm64", "ppc", "mips" or "mips64".
|
||||
</p>
|
||||
|
||||
<h2 id="jit_opt"><tt>jit.opt.*</tt> — JIT compiler optimization control</h2>
|
||||
<p>
|
||||
This sub-module provides the backend for the <tt>-O</tt> command line
|
||||
option.
|
||||
</p>
|
||||
<p>
|
||||
You can also use it programmatically, e.g.:
|
||||
</p>
|
||||
<pre class="code">
|
||||
jit.opt.start(2) -- same as -O2
|
||||
jit.opt.start("-dce")
|
||||
jit.opt.start("hotloop=10", "hotexit=2")
|
||||
</pre>
|
||||
<p>
|
||||
Unlike in LuaJIT 1.x, the module is built-in and
|
||||
<b>optimization is turned on by default!</b>
|
||||
It's no longer necessary to run <tt>require("jit.opt").start()</tt>,
|
||||
which was one of the ways to enable optimization.
|
||||
</p>
|
||||
|
||||
<h2 id="jit_util"><tt>jit.util.*</tt> — JIT compiler introspection</h2>
|
||||
<p>
|
||||
This sub-module holds functions to introspect the bytecode, generated
|
||||
traces, the IR and the generated machine code. The functionality
|
||||
provided by this module is still in flux and therefore undocumented.
|
||||
</p>
|
||||
<p>
|
||||
The debug modules <tt>-jbc</tt>, <tt>-jv</tt> and <tt>-jdump</tt> make
|
||||
extensive use of these functions. Please check out their source code,
|
||||
if you want to know more.
|
||||
</p>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,365 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Profiler</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Profiler</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 href="ext_jit.html">jit.* Library</a>
|
||||
</li><li>
|
||||
<a href="ext_c_api.html">Lua/C API</a>
|
||||
</li><li>
|
||||
<a class="current" href="ext_profiler.html">Profiler</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
LuaJIT has an integrated statistical profiler with very low overhead. It
|
||||
allows sampling the currently executing stack and other parameters in
|
||||
regular intervals.
|
||||
</p>
|
||||
<p>
|
||||
The integrated profiler can be accessed from three levels:
|
||||
</p>
|
||||
<ul>
|
||||
<li>The <a href="#hl_profiler">bundled high-level profiler</a>, invoked by the
|
||||
<a href="#j_p"><tt>-jp</tt></a> command line option.</li>
|
||||
<li>A <a href="#ll_lua_api">low-level Lua API</a> to control the profiler.</li>
|
||||
<li>A <a href="#ll_c_api">low-level C API</a> to control the profiler.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="hl_profiler">High-Level Profiler</h2>
|
||||
<p>
|
||||
The bundled high-level profiler offers basic profiling functionality. It
|
||||
generates simple textual summaries or source code annotations. It can be
|
||||
accessed with the <a href="#j_p"><tt>-jp</tt></a> command line option
|
||||
or from Lua code by loading the underlying <tt>jit.p</tt> module.
|
||||
</p>
|
||||
<p>
|
||||
To cut to the chase — run this to get a CPU usage profile by
|
||||
function name:
|
||||
</p>
|
||||
<pre class="code">
|
||||
luajit -jp myapp.lua
|
||||
</pre>
|
||||
<p>
|
||||
It's <em>not</em> a stated goal of the bundled profiler to add every
|
||||
possible option or to cater for special profiling needs. The low-level
|
||||
profiler APIs are documented below. They may be used by third-party
|
||||
authors to implement advanced functionality, e.g. IDE integration or
|
||||
graphical profilers.
|
||||
</p>
|
||||
<p>
|
||||
Note: Sampling works for both interpreted and JIT-compiled code. The
|
||||
results for JIT-compiled code may sometimes be surprising. LuaJIT
|
||||
heavily optimizes and inlines Lua code — there's no simple
|
||||
one-to-one correspondence between source code lines and the sampled
|
||||
machine code.
|
||||
</p>
|
||||
|
||||
<h3 id="j_p"><tt>-jp=[options[,output]]</tt></h3>
|
||||
<p>
|
||||
The <tt>-jp</tt> command line option starts the high-level profiler.
|
||||
When the application run by the command line terminates, the profiler
|
||||
stops and writes the results to <tt>stdout</tt> or to the specified
|
||||
<tt>output</tt> file.
|
||||
</p>
|
||||
<p>
|
||||
The <tt>options</tt> argument specifies how the profiling is to be
|
||||
performed:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>f</tt> — Stack dump: function name, otherwise module:line.
|
||||
This is the default mode.</li>
|
||||
<li><tt>F</tt> — Stack dump: ditto, but dump module:name.</li>
|
||||
<li><tt>l</tt> — Stack dump: module:line.</li>
|
||||
<li><tt><number></tt> — stack dump depth (callee ←
|
||||
caller). Default: 1.</li>
|
||||
<li><tt>-<number></tt> — Inverse stack dump depth (caller
|
||||
→ callee).</li>
|
||||
<li><tt>s</tt> — Split stack dump after first stack level. Implies
|
||||
depth ≥ 2 or depth ≤ -2.</li>
|
||||
<li><tt>p</tt> — Show full path for module names.</li>
|
||||
<li><tt>v</tt> — Show VM states.</li>
|
||||
<li><tt>z</tt> — Show <a href="#jit_zone">zones</a>.</li>
|
||||
<li><tt>r</tt> — Show raw sample counts. Default: show percentages.</li>
|
||||
<li><tt>a</tt> — Annotate excerpts from source code files.</li>
|
||||
<li><tt>A</tt> — Annotate complete source code files.</li>
|
||||
<li><tt>G</tt> — Produce raw output suitable for graphical tools.</li>
|
||||
<li><tt>m<number></tt> — Minimum sample percentage to be shown.
|
||||
Default: 3%.</li>
|
||||
<li><tt>i<number></tt> — Sampling interval in milliseconds.
|
||||
Default: 10ms.<br>
|
||||
Note: The actual sampling precision is OS-dependent.</li>
|
||||
</ul>
|
||||
<p>
|
||||
The default output for <tt>-jp</tt> is a list of the most CPU consuming
|
||||
spots in the application. Increasing the stack dump depth with (say)
|
||||
<tt>-jp=2</tt> may help to point out the main callers or callees of
|
||||
hotspots. But sample aggregation is still flat per unique stack dump.
|
||||
</p>
|
||||
<p>
|
||||
To get a two-level view (split view) of callers/callees, use
|
||||
<tt>-jp=s</tt> or <tt>-jp=-s</tt>. The percentages shown for the second
|
||||
level are relative to the first level.
|
||||
</p>
|
||||
<p>
|
||||
To see how much time is spent in each line relative to a function, use
|
||||
<tt>-jp=fl</tt>.
|
||||
</p>
|
||||
<p>
|
||||
To see how much time is spent in different VM states or
|
||||
<a href="#jit_zone">zones</a>, use <tt>-jp=v</tt> or <tt>-jp=z</tt>.
|
||||
</p>
|
||||
<p>
|
||||
Combinations of <tt>v/z</tt> with <tt>f/F/l</tt> produce two-level
|
||||
views, e.g. <tt>-jp=vf</tt> or <tt>-jp=fv</tt>. This shows the time
|
||||
spent in a VM state or zone vs. hotspots. This can be used to answer
|
||||
questions like "Which time consuming functions are only interpreted?" or
|
||||
"What's the garbage collector overhead for a specific function?".
|
||||
</p>
|
||||
<p>
|
||||
Multiple options can be combined — but not all combinations make
|
||||
sense, see above. E.g. <tt>-jp=3si4m1</tt> samples three stack levels
|
||||
deep in 4ms intervals and shows a split view of the CPU consuming
|
||||
functions and their callers with a 1% threshold.
|
||||
</p>
|
||||
<p>
|
||||
Source code annotations produced by <tt>-jp=a</tt> or <tt>-jp=A</tt> are
|
||||
always flat and at the line level. Obviously, the source code files need
|
||||
to be readable by the profiler script.
|
||||
</p>
|
||||
<p>
|
||||
The high-level profiler can also be started and stopped from Lua code with:
|
||||
</p>
|
||||
<pre class="code">
|
||||
require("jit.p").start(options, output)
|
||||
...
|
||||
require("jit.p").stop()
|
||||
</pre>
|
||||
|
||||
<h3 id="jit_zone"><tt>jit.zone</tt> — Zones</h3>
|
||||
<p>
|
||||
Zones can be used to provide information about different parts of an
|
||||
application to the high-level profiler. E.g. a game could make use of an
|
||||
<tt>"AI"</tt> zone, a <tt>"PHYS"</tt> zone, etc. Zones are hierarchical,
|
||||
organized as a stack.
|
||||
</p>
|
||||
<p>
|
||||
The <tt>jit.zone</tt> module needs to be loaded explicitly:
|
||||
</p>
|
||||
<pre class="code">
|
||||
local zone = require("jit.zone")
|
||||
</pre>
|
||||
<ul>
|
||||
<li><tt>zone("name")</tt> pushes a named zone to the zone stack.</li>
|
||||
<li><tt>zone()</tt> pops the current zone from the zone stack and
|
||||
returns its name.</li>
|
||||
<li><tt>zone:get()</tt> returns the current zone name or <tt>nil</tt>.</li>
|
||||
<li><tt>zone:flush()</tt> flushes the zone stack.</li>
|
||||
</ul>
|
||||
<p>
|
||||
To show the time spent in each zone use <tt>-jp=z</tt>. To show the time
|
||||
spent relative to hotspots use e.g. <tt>-jp=zf</tt> or <tt>-jp=fz</tt>.
|
||||
</p>
|
||||
|
||||
<h2 id="ll_lua_api">Low-level Lua API</h2>
|
||||
<p>
|
||||
The <tt>jit.profile</tt> module gives access to the low-level API of the
|
||||
profiler from Lua code. This module needs to be loaded explicitly:
|
||||
<pre class="code">
|
||||
local profile = require("jit.profile")
|
||||
</pre>
|
||||
<p>
|
||||
This module can be used to implement your own higher-level profiler.
|
||||
A typical profiling run starts the profiler, captures stack dumps in
|
||||
the profiler callback, adds them to a hash table to aggregate the number
|
||||
of samples, stops the profiler and then analyzes all of the captured
|
||||
stack dumps. Other parameters can be sampled in the profiler callback,
|
||||
too. But it's important not to spend too much time in the callback,
|
||||
since this may skew the statistics.
|
||||
</p>
|
||||
|
||||
<h3 id="profile_start"><tt>profile.start(mode, cb)</tt>
|
||||
— Start profiler</h3>
|
||||
<p>
|
||||
This function starts the profiler. The <tt>mode</tt> argument is a
|
||||
string holding options:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>f</tt> — Profile with precision down to the function level.</li>
|
||||
<li><tt>l</tt> — Profile with precision down to the line level.</li>
|
||||
<li><tt>i<number></tt> — Sampling interval in milliseconds (default
|
||||
10ms).</br>
|
||||
Note: The actual sampling precision is OS-dependent.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
The <tt>cb</tt> argument is a callback function which is called with
|
||||
three arguments: <tt>(thread, samples, vmstate)</tt>. The callback is
|
||||
called on a separate coroutine, the <tt>thread</tt> argument is the
|
||||
state that holds the stack to sample for profiling. Note: do
|
||||
<em>not</em> modify the stack of that state or call functions on it.
|
||||
</p>
|
||||
<p>
|
||||
<tt>samples</tt> gives the number of accumulated samples since the last
|
||||
callback (usually 1).
|
||||
</p>
|
||||
<p>
|
||||
<tt>vmstate</tt> holds the VM state at the time the profiling timer
|
||||
triggered. This may or may not correspond to the state of the VM when
|
||||
the profiling callback is called. The state is either <tt>'N'</tt>
|
||||
native (compiled) code, <tt>'I'</tt> interpreted code, <tt>'C'</tt>
|
||||
C code, <tt>'G'</tt> the garbage collector, or <tt>'J'</tt> the JIT
|
||||
compiler.
|
||||
</p>
|
||||
|
||||
<h3 id="profile_stop"><tt>profile.stop()</tt>
|
||||
— Stop profiler</h3>
|
||||
<p>
|
||||
This function stops the profiler.
|
||||
</p>
|
||||
|
||||
<h3 id="profile_dump"><tt>dump = profile.dumpstack([thread,] fmt, depth)</tt>
|
||||
— Dump stack </h3>
|
||||
<p>
|
||||
This function allows taking stack dumps in an efficient manner. It
|
||||
returns a string with a stack dump for the <tt>thread</tt> (coroutine),
|
||||
formatted according to the <tt>fmt</tt> argument:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>p</tt> — Preserve the full path for module names. Otherwise
|
||||
only the file name is used.</li>
|
||||
<li><tt>f</tt> — Dump the function name if it can be derived. Otherwise
|
||||
use module:line.</li>
|
||||
<li><tt>F</tt> — Ditto, but dump module:name.</li>
|
||||
<li><tt>l</tt> — Dump module:line.</li>
|
||||
<li><tt>Z</tt> — Zap the following characters for the last dumped
|
||||
frame.</li>
|
||||
<li>All other characters are added verbatim to the output string.</li>
|
||||
</ul>
|
||||
<p>
|
||||
The <tt>depth</tt> argument gives the number of frames to dump, starting
|
||||
at the topmost frame of the thread. A negative number dumps the frames in
|
||||
inverse order.
|
||||
</p>
|
||||
<p>
|
||||
The first example prints a list of the current module names and line
|
||||
numbers of up to 10 frames in separate lines. The second example prints
|
||||
semicolon-separated function names for all frames (up to 100) in inverse
|
||||
order:
|
||||
</p>
|
||||
<pre class="code">
|
||||
print(profile.dumpstack(thread, "l\n", 10))
|
||||
print(profile.dumpstack(thread, "lZ;", -100))
|
||||
</pre>
|
||||
|
||||
<h2 id="ll_c_api">Low-level C API</h2>
|
||||
<p>
|
||||
The profiler can be controlled directly from C code, e.g. for
|
||||
use by IDEs. The declarations are in <tt>"luajit.h"</tt> (see
|
||||
<a href="ext_c_api.html">Lua/C API</a> extensions).
|
||||
</p>
|
||||
|
||||
<h3 id="luaJIT_profile_start"><tt>luaJIT_profile_start(L, mode, cb, data)</tt>
|
||||
— Start profiler</h3>
|
||||
<p>
|
||||
This function starts the profiler. <a href="#profile_start">See
|
||||
above</a> for a description of the <tt>mode</tt> argument.
|
||||
</p>
|
||||
<p>
|
||||
The <tt>cb</tt> argument is a callback function with the following
|
||||
declaration:
|
||||
</p>
|
||||
<pre class="code">
|
||||
typedef void (*luaJIT_profile_callback)(void *data, lua_State *L,
|
||||
int samples, int vmstate);
|
||||
</pre>
|
||||
<p>
|
||||
<tt>data</tt> is available for use by the callback. <tt>L</tt> is the
|
||||
state that holds the stack to sample for profiling. Note: do
|
||||
<em>not</em> modify this stack or call functions on this stack —
|
||||
use a separate coroutine for this purpose. <a href="#profile_start">See
|
||||
above</a> for a description of <tt>samples</tt> and <tt>vmstate</tt>.
|
||||
</p>
|
||||
|
||||
<h3 id="luaJIT_profile_stop"><tt>luaJIT_profile_stop(L)</tt>
|
||||
— Stop profiler</h3>
|
||||
<p>
|
||||
This function stops the profiler.
|
||||
</p>
|
||||
|
||||
<h3 id="luaJIT_profile_dumpstack"><tt>p = luaJIT_profile_dumpstack(L, fmt, depth, len)</tt>
|
||||
— Dump stack </h3>
|
||||
<p>
|
||||
This function allows taking stack dumps in an efficient manner.
|
||||
<a href="#profile_dump">See above</a> for a description of <tt>fmt</tt>
|
||||
and <tt>depth</tt>.
|
||||
</p>
|
||||
<p>
|
||||
This function returns a <tt>const char *</tt> pointing to a
|
||||
private string buffer of the profiler. The <tt>int *len</tt>
|
||||
argument returns the length of the output string. The buffer is
|
||||
overwritten on the next call and deallocated when the profiler stops.
|
||||
You either need to consume the content immediately or copy it for later
|
||||
use.
|
||||
</p>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,482 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Extensions</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
table.exc {
|
||||
line-height: 1.2;
|
||||
}
|
||||
tr.exchead td {
|
||||
font-weight: bold;
|
||||
}
|
||||
td.excplatform {
|
||||
width: 48%;
|
||||
}
|
||||
td.exccompiler {
|
||||
width: 29%;
|
||||
}
|
||||
td.excinterop {
|
||||
width: 23%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Extensions</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 class="current" 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 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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
LuaJIT is fully upwards-compatible with Lua 5.1. It supports all
|
||||
<a href="http://www.lua.org/manual/5.1/manual.html#5"><span class="ext">»</span> standard Lua
|
||||
library functions</a> and the full set of
|
||||
<a href="http://www.lua.org/manual/5.1/manual.html#3"><span class="ext">»</span> Lua/C API
|
||||
functions</a>.
|
||||
</p>
|
||||
<p>
|
||||
LuaJIT is also fully ABI-compatible to Lua 5.1 at the linker/dynamic
|
||||
loader level. This means you can compile a C module against the
|
||||
standard Lua headers and load the same shared library from either Lua
|
||||
or LuaJIT.
|
||||
</p>
|
||||
<p>
|
||||
LuaJIT extends the standard Lua VM with new functionality and adds
|
||||
several extension modules. Please note this page is only about
|
||||
<em>functional</em> enhancements and not about performance enhancements,
|
||||
such as the optimized VM, the faster interpreter or the JIT compiler.
|
||||
</p>
|
||||
|
||||
<h2 id="modules">Extensions Modules</h2>
|
||||
<p>
|
||||
LuaJIT comes with several built-in extension modules:
|
||||
</p>
|
||||
|
||||
<h3 id="bit"><tt>bit.*</tt> — Bitwise operations</h3>
|
||||
<p>
|
||||
LuaJIT supports all bitwise operations as defined by
|
||||
<a href="http://bitop.luajit.org"><span class="ext">»</span> Lua BitOp</a>:
|
||||
</p>
|
||||
<pre class="code">
|
||||
bit.tobit bit.tohex bit.bnot bit.band bit.bor bit.bxor
|
||||
bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap
|
||||
</pre>
|
||||
<p>
|
||||
This module is a LuaJIT built-in — you don't need to download or
|
||||
install Lua BitOp. The Lua BitOp site has full documentation for all
|
||||
<a href="http://bitop.luajit.org/api.html"><span class="ext">»</span> Lua BitOp API functions</a>.
|
||||
The FFI adds support for
|
||||
<a href="ext_ffi_semantics.html#cdata_arith">64 bit bitwise operations</a>,
|
||||
using the same API functions.
|
||||
</p>
|
||||
<p>
|
||||
Please make sure to <tt>require</tt> the module before using any of
|
||||
its functions:
|
||||
</p>
|
||||
<pre class="code">
|
||||
local bit = require("bit")
|
||||
</pre>
|
||||
<p>
|
||||
An already installed Lua BitOp module is ignored by LuaJIT.
|
||||
This way you can use bit operations from both Lua and LuaJIT on a
|
||||
shared installation.
|
||||
</p>
|
||||
|
||||
<h3 id="ffi"><tt>ffi.*</tt> — FFI library</h3>
|
||||
<p>
|
||||
The <a href="ext_ffi.html">FFI library</a> allows calling external
|
||||
C functions and the use of C data structures from pure Lua
|
||||
code.
|
||||
</p>
|
||||
|
||||
<h3 id="jit"><tt>jit.*</tt> — JIT compiler control</h3>
|
||||
<p>
|
||||
The functions in this module
|
||||
<a href="ext_jit.html">control the behavior of the JIT compiler engine</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="c_api">C API extensions</h3>
|
||||
<p>
|
||||
LuaJIT adds some
|
||||
<a href="ext_c_api.html">extra functions to the Lua/C API</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="profiler">Profiler</h3>
|
||||
<p>
|
||||
LuaJIT has an <a href="ext_profiler.html">integrated profiler</a>.
|
||||
</p>
|
||||
|
||||
<h2 id="library">Enhanced Standard Library Functions</h2>
|
||||
|
||||
<h3 id="xpcall"><tt>xpcall(f, err [,args...])</tt> passes arguments</h3>
|
||||
<p>
|
||||
Unlike the standard implementation in Lua 5.1, <tt>xpcall()</tt>
|
||||
passes any arguments after the error function to the function
|
||||
which is called in a protected context.
|
||||
</p>
|
||||
|
||||
<h3 id="load"><tt>loadfile()</tt> etc. handle UTF-8 source code</h3>
|
||||
<p>
|
||||
Non-ASCII characters are handled transparently by the Lua source code parser.
|
||||
This allows the use of UTF-8 characters in identifiers and strings.
|
||||
A UTF-8 BOM is skipped at the start of the source code.
|
||||
</p>
|
||||
|
||||
<h3 id="tostring"><tt>tostring()</tt> etc. canonicalize NaN and ±Inf</h3>
|
||||
<p>
|
||||
All number-to-string conversions consistently convert non-finite numbers
|
||||
to the same strings on all platforms. NaN results in <tt>"nan"</tt>,
|
||||
positive infinity results in <tt>"inf"</tt> and negative infinity results
|
||||
in <tt>"-inf"</tt>.
|
||||
</p>
|
||||
|
||||
<h3 id="tonumber"><tt>tonumber()</tt> etc. use builtin string to number conversion</h3>
|
||||
<p>
|
||||
All string-to-number conversions consistently convert integer and
|
||||
floating-point inputs in decimal, hexadecimal and binary on all platforms.
|
||||
<tt>strtod()</tt> is <em>not</em> used anymore, which avoids numerous
|
||||
problems with poor C library implementations. The builtin conversion
|
||||
function provides full precision according to the IEEE-754 standard, it
|
||||
works independently of the current locale and it supports hex floating-point
|
||||
numbers (e.g. <tt>0x1.5p-3</tt>).
|
||||
</p>
|
||||
|
||||
<h3 id="string_dump"><tt>string.dump(f [,strip])</tt> generates portable bytecode</h3>
|
||||
<p>
|
||||
An extra argument has been added to <tt>string.dump()</tt>. If set to
|
||||
<tt>true</tt>, 'stripped' bytecode without debug information is
|
||||
generated. This speeds up later bytecode loading and reduces memory
|
||||
usage. See also the
|
||||
<a href="running.html#opt_b"><tt>-b</tt> command line option</a>.
|
||||
</p>
|
||||
<p>
|
||||
The generated bytecode is portable and can be loaded on any architecture
|
||||
that LuaJIT supports, independent of word size or endianess. However the
|
||||
bytecode compatibility versions must match. Bytecode stays compatible
|
||||
for dot releases (x.y.0 → x.y.1), but may change with major or
|
||||
minor releases (2.0 → 2.1) or between any beta release. Foreign
|
||||
bytecode (e.g. from Lua 5.1) is incompatible and cannot be loaded.
|
||||
</p>
|
||||
<p>
|
||||
Note: <tt>LJ_GC64</tt> mode requires a different frame layout, which implies
|
||||
a different, incompatible bytecode format for ports that use this mode (e.g.
|
||||
ARM64 or MIPS64) or when explicitly enabled for x64. This may be rectified
|
||||
in the future.
|
||||
</p>
|
||||
|
||||
<h3 id="table_new"><tt>table.new(narray, nhash)</tt> allocates a pre-sized table</h3>
|
||||
<p>
|
||||
An extra library function <tt>table.new()</tt> can be made available via
|
||||
<tt>require("table.new")</tt>. This creates a pre-sized table, just like
|
||||
the C API equivalent <tt>lua_createtable()</tt>. This is useful for big
|
||||
tables if the final table size is known and automatic table resizing is
|
||||
too expensive.
|
||||
</p>
|
||||
|
||||
<h3 id="table_clear"><tt>table.clear(tab)</tt> clears a table</h3>
|
||||
<p>
|
||||
An extra library function <tt>table.clear()</tt> can be made available
|
||||
via <tt>require("table.clear")</tt>. This clears all keys and values
|
||||
from a table, but preserves the allocated array/hash sizes. This is
|
||||
useful when a table, which is linked from multiple places, needs to be
|
||||
cleared and/or when recycling a table for use by the same context. This
|
||||
avoids managing backlinks, saves an allocation and the overhead of
|
||||
incremental array/hash part growth.
|
||||
</p>
|
||||
<p>
|
||||
Please note this function is meant for very specific situations. In most
|
||||
cases it's better to replace the (usually single) link with a new table
|
||||
and let the GC do its work.
|
||||
</p>
|
||||
|
||||
<h3 id="math_random">Enhanced PRNG for <tt>math.random()</tt></h3>
|
||||
<p>
|
||||
LuaJIT uses a Tausworthe PRNG with period 2^223 to implement
|
||||
<tt>math.random()</tt> and <tt>math.randomseed()</tt>. The quality of
|
||||
the PRNG results is much superior compared to the standard Lua
|
||||
implementation which uses the platform-specific ANSI rand().
|
||||
</p>
|
||||
<p>
|
||||
The PRNG generates the same sequences from the same seeds on all
|
||||
platforms and makes use of all bits in the seed argument.
|
||||
<tt>math.random()</tt> without arguments generates 52 pseudo-random bits
|
||||
for every call. The result is uniformly distributed between 0.0 and 1.0.
|
||||
It's correctly scaled up and rounded for <tt>math.random(n [,m])</tt> to
|
||||
preserve uniformity.
|
||||
</p>
|
||||
|
||||
<h3 id="io"><tt>io.*</tt> functions handle 64 bit file offsets</h3>
|
||||
<p>
|
||||
The file I/O functions in the standard <tt>io.*</tt> library handle
|
||||
64 bit file offsets. In particular this means it's possible
|
||||
to open files larger than 2 Gigabytes and to reposition or obtain
|
||||
the current file position for offsets beyond 2 GB
|
||||
(<tt>fp:seek()</tt> method).
|
||||
</p>
|
||||
|
||||
<h3 id="debug_meta"><tt>debug.*</tt> functions identify metamethods</h3>
|
||||
<p>
|
||||
<tt>debug.getinfo()</tt> and <tt>lua_getinfo()</tt> also return information
|
||||
about invoked metamethods. The <tt>namewhat</tt> field is set to
|
||||
<tt>"metamethod"</tt> and the <tt>name</tt> field has the name of
|
||||
the corresponding metamethod (e.g. <tt>"__index"</tt>).
|
||||
</p>
|
||||
|
||||
<h2 id="resumable">Fully Resumable VM</h2>
|
||||
<p>
|
||||
The LuaJIT VM is fully resumable. This means you can yield from a
|
||||
coroutine even across contexts, where this would not possible with
|
||||
the standard Lua 5.1 VM: e.g. you can yield across <tt>pcall()</tt>
|
||||
and <tt>xpcall()</tt>, across iterators and across metamethods.
|
||||
</p>
|
||||
|
||||
<h2 id="lua52">Extensions from Lua 5.2</h2>
|
||||
<p>
|
||||
LuaJIT supports some language and library extensions from Lua 5.2.
|
||||
Features that are unlikely to break existing code are unconditionally
|
||||
enabled:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>goto</tt> and <tt>::labels::</tt>.</li>
|
||||
<li>Hex escapes <tt>'\x3F'</tt> and <tt>'\*'</tt> escape in strings.</li>
|
||||
<li><tt>load(string|reader [, chunkname [,mode [,env]]])</tt>.</li>
|
||||
<li><tt>loadstring()</tt> is an alias for <tt>load()</tt>.</li>
|
||||
<li><tt>loadfile(filename [,mode [,env]])</tt>.</li>
|
||||
<li><tt>math.log(x [,base])</tt>.</li>
|
||||
<li><tt>string.rep(s, n [,sep])</tt>.</li>
|
||||
<li><tt>string.format()</tt>: <tt>%q</tt> reversible.
|
||||
<tt>%s</tt> checks <tt>__tostring</tt>.
|
||||
<tt>%a</tt> and <tt>"%A</tt> added.</li>
|
||||
<li>String matching pattern <tt>%g</tt> added.</li>
|
||||
<li><tt>io.read("*L")</tt>.</li>
|
||||
<li><tt>io.lines()</tt> and <tt>file:lines()</tt> process
|
||||
<tt>io.read()</tt> options.</li>
|
||||
<li><tt>os.exit(status|true|false [,close])</tt>.</li>
|
||||
<li><tt>package.searchpath(name, path [, sep [, rep]])</tt>.</li>
|
||||
<li><tt>package.loadlib(name, "*")</tt>.</li>
|
||||
<li><tt>debug.getinfo()</tt> returns <tt>nparams</tt> and <tt>isvararg</tt>
|
||||
for option <tt>"u"</tt>.</li>
|
||||
<li><tt>debug.getlocal()</tt> accepts function instead of level.</li>
|
||||
<li><tt>debug.getlocal()</tt> and <tt>debug.setlocal()</tt> accept negative
|
||||
indexes for varargs.</li>
|
||||
<li><tt>debug.getupvalue()</tt> and <tt>debug.setupvalue()</tt> handle
|
||||
C functions.</li>
|
||||
<li><tt>debug.upvalueid()</tt> and <tt>debug.upvaluejoin()</tt>.</li>
|
||||
<li>Lua/C API extensions:
|
||||
<tt>lua_version()</tt>
|
||||
<tt>lua_upvalueid()</tt>
|
||||
<tt>lua_upvaluejoin()</tt>
|
||||
<tt>lua_loadx()</tt>
|
||||
<tt>lua_copy()</tt>
|
||||
<tt>lua_tonumberx()</tt>
|
||||
<tt>lua_tointegerx()</tt>
|
||||
<tt>luaL_fileresult()</tt>
|
||||
<tt>luaL_execresult()</tt>
|
||||
<tt>luaL_loadfilex()</tt>
|
||||
<tt>luaL_loadbufferx()</tt>
|
||||
<tt>luaL_traceback()</tt>
|
||||
<tt>luaL_setfuncs()</tt>
|
||||
<tt>luaL_pushmodule()</tt>
|
||||
<tt>luaL_newlibtable()</tt>
|
||||
<tt>luaL_newlib()</tt>
|
||||
<tt>luaL_testudata()</tt>
|
||||
<tt>luaL_setmetatable()</tt>
|
||||
</li>
|
||||
<li>Command line option <tt>-E</tt>.</li>
|
||||
<li>Command line checks <tt>__tostring</tt> for errors.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Other features are only enabled, if LuaJIT is built with
|
||||
<tt>-DLUAJIT_ENABLE_LUA52COMPAT</tt>:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>goto</tt> is a keyword and not a valid variable name anymore.</li>
|
||||
<li><tt>break</tt> can be placed anywhere. Empty statements (<tt>;;</tt>)
|
||||
are allowed.</li>
|
||||
<li><tt>__lt</tt>, <tt>__le</tt> are invoked for mixed types.</li>
|
||||
<li><tt>__len</tt> for tables. <tt>rawlen()</tt> library function.</li>
|
||||
<li><tt>pairs()</tt> and <tt>ipairs()</tt> check for <tt>__pairs</tt> and
|
||||
<tt>__ipairs</tt>.</li>
|
||||
<li><tt>coroutine.running()</tt> returns two results.</li>
|
||||
<li><tt>table.pack()</tt> and <tt>table.unpack()</tt>
|
||||
(same as <tt>unpack()</tt>).</li>
|
||||
<li><tt>io.write()</tt> and <tt>file:write()</tt> return file handle
|
||||
instead of <tt>true</tt>.</li>
|
||||
<li><tt>os.execute()</tt> and <tt>pipe:close()</tt> return detailed
|
||||
exit status.</li>
|
||||
<li><tt>debug.setmetatable()</tt> returns object.</li>
|
||||
<li><tt>debug.getuservalue()</tt> and <tt>debug.setuservalue()</tt>.</li>
|
||||
<li>Remove <tt>math.mod()</tt>, <tt>string.gfind()</tt>.</li>
|
||||
<li><tt>package.searchers</tt>.</li>
|
||||
<li><tt>module()</tt> returns the module table.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Note: this provides only partial compatibility with Lua 5.2 at the
|
||||
language and Lua library level. LuaJIT is API+ABI-compatible with
|
||||
Lua 5.1, which prevents implementing features that would otherwise
|
||||
break the Lua/C API and ABI (e.g. <tt>_ENV</tt>).
|
||||
</p>
|
||||
|
||||
<h2 id="lua53">Extensions from Lua 5.3</h2>
|
||||
<p>
|
||||
LuaJIT supports some extensions from Lua 5.3:
|
||||
<ul>
|
||||
<li>Unicode escape <tt>'\u{XX...}'</tt> embeds the UTF-8 encoding in string literals.</li>
|
||||
<li>The argument table <tt>arg</tt> can be read (and modified) by <tt>LUA_INIT</tt> and <tt>-e</tt> chunks.</li>
|
||||
<li><tt>io.read()</tt> and <tt>file:read()</tt> accept formats with or without a leading <tt>*</tt>.</li>
|
||||
<li><tt>table.move(a1, f, e, t [,a2])</tt>.</li>
|
||||
<li><tt>coroutine.isyieldable()</tt>.</li>
|
||||
<li>Lua/C API extensions:
|
||||
<tt>lua_isyieldable()</tt>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="exceptions">C++ Exception Interoperability</h2>
|
||||
<p>
|
||||
LuaJIT has built-in support for interoperating with C++ exceptions.
|
||||
The available range of features depends on the target platform and
|
||||
the toolchain used to compile LuaJIT:
|
||||
</p>
|
||||
<table class="exc">
|
||||
<tr class="exchead">
|
||||
<td class="excplatform">Platform</td>
|
||||
<td class="exccompiler">Compiler</td>
|
||||
<td class="excinterop">Interoperability</td>
|
||||
</tr>
|
||||
<tr class="odd separate">
|
||||
<td class="excplatform">POSIX/x64, DWARF2 unwinding</td>
|
||||
<td class="exccompiler">GCC 4.3+, Clang</td>
|
||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="excplatform">ARM <tt>-DLUAJIT_UNWIND_EXTERNAL</tt></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="excinterop"><b style="color: #c06000;">Limited</b></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="excplatform">Windows/x64</td>
|
||||
<td class="exccompiler">MSVC or WinSDK</td>
|
||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td class="excplatform">Windows/x86</td>
|
||||
<td class="exccompiler">Any</td>
|
||||
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="excplatform">Other platforms</td>
|
||||
<td class="exccompiler">Other compilers</td>
|
||||
<td class="excinterop"><b style="color: #a00000;">No</b></td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>
|
||||
<b style="color: #00a000;">Full interoperability</b> means:
|
||||
</p>
|
||||
<ul>
|
||||
<li>C++ exceptions can be caught on the Lua side with <tt>pcall()</tt>,
|
||||
<tt>lua_pcall()</tt> etc.</li>
|
||||
<li>C++ exceptions will be converted to the generic Lua error
|
||||
<tt>"C++ exception"</tt>, unless you use the
|
||||
<a href="ext_c_api.html#mode_wrapcfunc">C call wrapper</a> feature.</li>
|
||||
<li>It's safe to throw C++ exceptions across non-protected Lua frames
|
||||
on the C stack. The contents of the C++ exception object
|
||||
pass through unmodified.</li>
|
||||
<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>
|
||||
<li>Throwing Lua errors across C++ frames is safe. C++ destructors
|
||||
will be called.</li>
|
||||
</ul>
|
||||
<p>
|
||||
<b style="color: #c06000;">Limited interoperability</b> means:
|
||||
</p>
|
||||
<ul>
|
||||
<li>C++ exceptions can be caught on the Lua side with <tt>pcall()</tt>,
|
||||
<tt>lua_pcall()</tt> etc.</li>
|
||||
<li>C++ exceptions will be converted to the generic Lua error
|
||||
<tt>"C++ exception"</tt>, unless you use the
|
||||
<a href="ext_c_api.html#mode_wrapcfunc">C call wrapper</a> feature.</li>
|
||||
<li>C++ exceptions will be caught by non-protected Lua frames and
|
||||
are rethrown as a generic Lua error. The C++ exception object will
|
||||
be destroyed.</li>
|
||||
<li>Lua errors <b>cannot</b> be caught on the C++ side.</li>
|
||||
<li>Throwing Lua errors across C++ frames will <b>not</b> call
|
||||
C++ destructors.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b style="color: #a00000;">No interoperability</b> means:
|
||||
</p>
|
||||
<ul>
|
||||
<li>It's <b>not</b> safe to throw C++ exceptions across Lua frames.</li>
|
||||
<li>C++ exceptions <b>cannot</b> be caught on the Lua side.</li>
|
||||
<li>Lua errors <b>cannot</b> be caught on the C++ side.</li>
|
||||
<li>Throwing Lua errors across C++ frames will <b>not</b> call
|
||||
C++ destructors.</li>
|
||||
</ul>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,186 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Frequently Asked Questions (FAQ)</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
dd { margin-left: 1.5em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Frequently Asked Questions (FAQ)</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a class="current" href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<dl>
|
||||
<dt>Q: Where can I learn more about LuaJIT and Lua?</dt>
|
||||
<dd>
|
||||
<ul style="padding: 0;">
|
||||
<li>The <a href="http://luajit.org/list.html"><span class="ext">»</span> LuaJIT mailing list</a> focuses on topics
|
||||
related to LuaJIT.</li>
|
||||
<li>The <a href="http://wiki.luajit.org/"><span class="ext">»</span> LuaJIT wiki</a> gathers community
|
||||
resources about LuaJIT.</li>
|
||||
<li>News about Lua itself can be found at the
|
||||
<a href="http://www.lua.org/lua-l.html"><span class="ext">»</span> Lua mailing list</a>.
|
||||
The mailing list archives are worth checking out for older postings
|
||||
about LuaJIT.</li>
|
||||
<li>The <a href="http://lua.org"><span class="ext">»</span> main Lua.org site</a> has complete
|
||||
<a href="http://www.lua.org/docs.html"><span class="ext">»</span> documentation</a> of the language
|
||||
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>
|
||||
has information about diverse topics.</li>
|
||||
</ul>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Q: Where can I learn more about the compiler technology used by LuaJIT?</dt>
|
||||
<dd>
|
||||
I'm planning to write more documentation about the internals of LuaJIT.
|
||||
In the meantime, please use the following Google Scholar searches
|
||||
to find relevant papers:<br>
|
||||
Search for: <a href="http://scholar.google.com/scholar?q=Trace+Compiler"><span class="ext">»</span> Trace Compiler</a><br>
|
||||
Search for: <a href="http://scholar.google.com/scholar?q=JIT+Compiler"><span class="ext">»</span> JIT Compiler</a><br>
|
||||
Search for: <a href="http://scholar.google.com/scholar?q=Dynamic+Language+Optimizations"><span class="ext">»</span> Dynamic Language Optimizations</a><br>
|
||||
Search for: <a href="http://scholar.google.com/scholar?q=SSA+Form"><span class="ext">»</span> SSA Form</a><br>
|
||||
Search for: <a href="http://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://article.gmane.org/gmane.comp.lang.lua.general/58908"><span class="ext">»</span> innovative features in LuaJIT</a>.<br>
|
||||
And, you know, reading the source is of course the only way to enlightenment. :-)
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Q: Why do I get this error: "attempt to index global 'arg' (a nil value)"?<br>
|
||||
Q: My vararg functions fail after switching to LuaJIT!</dt>
|
||||
<dd>LuaJIT is compatible to the Lua 5.1 language standard. It doesn't
|
||||
support the implicit <tt>arg</tt> parameter for old-style vararg
|
||||
functions from Lua 5.0.<br>Please convert your code to the
|
||||
<a href="http://www.lua.org/manual/5.1/manual.html#2.5.9"><span class="ext">»</span> Lua 5.1
|
||||
vararg syntax</a>.</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<dt>Q: Why do I get this error: "bad FPU precision"?<br>
|
||||
<dt>Q: I get weird behavior after initializing Direct3D.<br>
|
||||
<dt>Q: Some FPU operations crash after I load a Delphi DLL.<br>
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
DirectX/Direct3D (up to version 9) sets the x87 FPU to single-precision
|
||||
mode by default. This violates the Windows ABI and interferes with the
|
||||
operation of many programs — LuaJIT is affected, too. Please make
|
||||
sure you always use the <tt>D3DCREATE_FPU_PRESERVE</tt> flag when
|
||||
initializing Direct3D.<br>
|
||||
|
||||
Direct3D version 10 or higher do not show this behavior anymore.
|
||||
Consider testing your application with older versions, too.<br>
|
||||
|
||||
Similarly, the Borland/Delphi runtime modifies the FPU control word and
|
||||
enables FP exceptions. Of course this violates the Windows ABI, too.
|
||||
Please check the Delphi docs for the Set8087CW method.
|
||||
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<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
|
||||
currently ignored by compiled code (this will eventually be fixed). If
|
||||
your program is running in a tight loop and never falls back to the
|
||||
interpreter, the debug hook never runs and can't throw the
|
||||
"interrupted!" error.<br> In the meantime you have to press Ctrl-C
|
||||
twice to get stop your program. That's similar to when it's stuck
|
||||
running inside a C function under the Lua interpreter.</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<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>
|
||||
<dt>Q: Lua runs everywhere. Why doesn't LuaJIT support my CPU?</dt>
|
||||
<dd>Because it's a compiler — it needs to generate native
|
||||
machine code. This means the code generator must be ported to each
|
||||
architecture. And the fast interpreter is written in assembler and
|
||||
must be ported, too. This is quite an undertaking.<br>
|
||||
The <a href="install.html">install documentation</a> shows the supported
|
||||
architectures. Other architectures will follow based on sufficient user
|
||||
demand and/or sponsoring.</dd>
|
||||
</dl>
|
||||
|
||||
<dl>
|
||||
<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>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,692 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Installation</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
table.compat {
|
||||
line-height: 1.2;
|
||||
font-size: 80%;
|
||||
}
|
||||
table.compat td {
|
||||
border: 1px solid #bfcfff;
|
||||
height: 2.5em;
|
||||
}
|
||||
table.compat tr.compathead td {
|
||||
font-weight: bold;
|
||||
border-bottom: 2px solid #bfcfff;
|
||||
}
|
||||
tr.compathead td.compatos {
|
||||
vertical-align: top;
|
||||
}
|
||||
table.compat td.compatcpu {
|
||||
width: 18%;
|
||||
border-right: 2px solid #bfcfff;
|
||||
}
|
||||
td.compatos {
|
||||
width: 21%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
td.compatno {
|
||||
background-color: #d0d0d0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Installation</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a class="current" 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 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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
LuaJIT is only distributed as a source package. This page explains
|
||||
how to build and install LuaJIT with different operating systems
|
||||
and C compilers.
|
||||
</p>
|
||||
<p>
|
||||
For the impatient (on POSIX systems):
|
||||
</p>
|
||||
<pre class="code">
|
||||
make && sudo make install
|
||||
</pre>
|
||||
<p>
|
||||
LuaJIT currently builds out-of-the box on most systems.
|
||||
Here's the compatibility matrix for the supported combinations of
|
||||
operating systems, CPUs and compilers:
|
||||
</p>
|
||||
<table class="compat">
|
||||
<tr class="compathead">
|
||||
<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">*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="#windows">Windows<br>XP/Vista/7</a></td>
|
||||
</tr>
|
||||
<tr class="odd separate">
|
||||
<td class="compatcpu">x86 (32 bit)</td>
|
||||
<td class="compatos">GCC 4.2+</td>
|
||||
<td class="compatos">GCC 4.2+</td>
|
||||
<td class="compatos">XCode 5.0+<br>Clang</td>
|
||||
<td class="compatos">MSVC, MSVC/EE<br>WinSDK<br>MinGW, Cygwin</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="compatcpu">x64 (64 bit)</td>
|
||||
<td class="compatos">GCC 4.2+</td>
|
||||
<td class="compatos">GCC 4.2+<br>ORBIS (<a href="#ps4">PS4</a>)</td>
|
||||
<td class="compatos">XCode 5.0+<br>Clang</td>
|
||||
<td class="compatos">MSVC + SDK v7.0<br>WinSDK v7.0<br>Durango (<a href="#xboxone">Xbox One</a>)</td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td class="compatcpu"><a href="#cross2">ARMv5+<br>ARM9E+</a></td>
|
||||
<td class="compatos">GCC 4.2+</td>
|
||||
<td class="compatos">GCC 4.2+<br>PSP2 (<a href="#psvita">PS VITA</a>)</td>
|
||||
<td class="compatos">XCode 5.0+<br>Clang</td>
|
||||
<td class="compatos compatno"> </td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="compatcpu"><a href="#cross2">ARM64</a></td>
|
||||
<td class="compatos">GCC 4.8+</td>
|
||||
<td class="compatos compatno"> </td>
|
||||
<td class="compatos">XCode 6.0+<br>Clang 3.5+</td>
|
||||
<td class="compatos compatno"> </td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td class="compatcpu"><a href="#cross2">PPC</a></td>
|
||||
<td class="compatos">GCC 4.3+</td>
|
||||
<td class="compatos">GCC 4.3+<br>GCC 4.1 (<a href="#ps3">PS3</a>)</td>
|
||||
<td class="compatos compatno"> </td>
|
||||
<td class="compatos">XEDK (<a href="#xbox360">Xbox 360</a>)</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td class="compatcpu"><a href="#cross2">MIPS32<br>MIPS64</a></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>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h2>Configuring LuaJIT</h2>
|
||||
<p>
|
||||
The standard configuration should work fine for most installations.
|
||||
Usually there is no need to tweak the settings. The following files
|
||||
hold all user-configurable settings:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>src/luaconf.h</tt> sets some configuration variables.</li>
|
||||
<li><tt>Makefile</tt> has settings for <b>installing</b> LuaJIT (POSIX
|
||||
only).</li>
|
||||
<li><tt>src/Makefile</tt> has settings for <b>compiling</b> LuaJIT
|
||||
under POSIX, MinGW or Cygwin.</li>
|
||||
<li><tt>src/msvcbuild.bat</tt> has settings for compiling LuaJIT with
|
||||
MSVC or WinSDK.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Please read the instructions given in these files, before changing
|
||||
any settings.
|
||||
</p>
|
||||
<p>
|
||||
LuaJIT on x64 currently uses 32 bit GC objects by default.
|
||||
<tt>LJ_GC64</tt> mode may be explicitly enabled:
|
||||
add <tt>XCFLAGS=-DLUAJIT_ENABLE_GC64</tt> to the make command or run
|
||||
<tt>msvcbuild gc64</tt> for MSVC/WinSDK. Please check the note
|
||||
about the <a href="extensions.html#string_dump">bytecode format</a>
|
||||
differences, too.
|
||||
</p>
|
||||
|
||||
<h2 id="posix">POSIX Systems (Linux, OSX, *BSD etc.)</h2>
|
||||
<h3>Prerequisites</h3>
|
||||
<p>
|
||||
Depending on your distribution, you may need to install a package for
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
Download the current source package of LuaJIT (pick the .tar.gz),
|
||||
if you haven't already done so. 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:
|
||||
</p>
|
||||
<pre class="code">
|
||||
tar zxf LuaJIT-2.0.5.tar.gz
|
||||
cd LuaJIT-2.0.5</pre>
|
||||
<h3>Building LuaJIT</h3>
|
||||
<p>
|
||||
The supplied Makefiles try to auto-detect the settings needed for your
|
||||
operating system and your compiler. They need to be run with GNU Make,
|
||||
which is probably the default on your system, anyway. Simply run:
|
||||
</p>
|
||||
<pre class="code">
|
||||
make
|
||||
</pre>
|
||||
<p>
|
||||
This always builds a native binary, depending on the host OS
|
||||
you're running this command on. Check the section on
|
||||
<a href="#cross">cross-compilation</a> for more options.
|
||||
</p>
|
||||
<p>
|
||||
By default, modules are only searched under the prefix <tt>/usr/local</tt>.
|
||||
You can add an extra prefix to the search paths by appending the
|
||||
<tt>PREFIX</tt> option, e.g.:
|
||||
</p>
|
||||
<pre class="code">
|
||||
make PREFIX=/home/myself/lj2
|
||||
</pre>
|
||||
<p>
|
||||
Note for OSX: if the <tt>MACOSX_DEPLOYMENT_TARGET</tt> environment
|
||||
variable is not set, then it's forced to <tt>10.4</tt>.
|
||||
</p>
|
||||
<h3>Installing LuaJIT</h3>
|
||||
<p>
|
||||
The top-level Makefile installs LuaJIT by default under
|
||||
<tt>/usr/local</tt>, i.e. the executable ends up in
|
||||
<tt>/usr/local/bin</tt> and so on. You need root privileges
|
||||
to write to this path. So, assuming sudo is installed on your system,
|
||||
run the following command and enter your sudo password:
|
||||
</p>
|
||||
<pre class="code">
|
||||
sudo make install
|
||||
</pre>
|
||||
<p>
|
||||
Otherwise specify the directory prefix as an absolute path, e.g.:
|
||||
</p>
|
||||
<pre class="code">
|
||||
make install PREFIX=/home/myself/lj2
|
||||
</pre>
|
||||
<p>
|
||||
Obviously the prefixes given during build and installation need to be the same.
|
||||
</p>
|
||||
|
||||
<h2 id="windows">Windows Systems</h2>
|
||||
<h3>Prerequisites</h3>
|
||||
<p>
|
||||
Either install one of the open source SDKs
|
||||
(<a href="http://mingw.org/"><span class="ext">»</span> MinGW</a> or
|
||||
<a href="http://www.cygwin.com/"><span class="ext">»</span> Cygwin</a>), which come with a modified
|
||||
GCC plus the required development headers.
|
||||
</p>
|
||||
<p>
|
||||
Or install Microsoft's Visual C++ (MSVC). The freely downloadable
|
||||
<a href="http://www.microsoft.com/Express/VC/"><span class="ext">»</span> Express Edition</a>
|
||||
works just fine, but only contains an x86 compiler.
|
||||
</p>
|
||||
<p>
|
||||
The freely downloadable
|
||||
<a href="http://msdn.microsoft.com/en-us/windowsserver/bb980924.aspx"><span class="ext">»</span> Windows SDK</a>
|
||||
only comes with command line tools, but this is all you need to build LuaJIT.
|
||||
It contains x86 and x64 compilers.
|
||||
</p>
|
||||
<p>
|
||||
Next, download the source package and unpack it using an archive manager
|
||||
(e.g. the Windows Explorer) to a directory of your choice.
|
||||
</p>
|
||||
<h3>Building with MSVC</h3>
|
||||
<p>
|
||||
Open a "Visual Studio .NET Command Prompt", <tt>cd</tt> to the
|
||||
directory where you've unpacked the sources and run these commands:
|
||||
</p>
|
||||
<pre class="code">
|
||||
cd src
|
||||
msvcbuild
|
||||
</pre>
|
||||
<p>
|
||||
Then follow the installation instructions below.
|
||||
</p>
|
||||
<h3>Building with the Windows SDK</h3>
|
||||
<p>
|
||||
Open a "Windows SDK Command Shell" and select the x86 compiler:
|
||||
</p>
|
||||
<pre class="code">
|
||||
setenv /release /x86
|
||||
</pre>
|
||||
<p>
|
||||
Or select the x64 compiler:
|
||||
</p>
|
||||
<pre class="code">
|
||||
setenv /release /x64
|
||||
</pre>
|
||||
<p>
|
||||
Then <tt>cd</tt> to the directory where you've unpacked the sources
|
||||
and run these commands:
|
||||
</p>
|
||||
<pre class="code">
|
||||
cd src
|
||||
msvcbuild
|
||||
</pre>
|
||||
<p>
|
||||
Then follow the installation instructions below.
|
||||
</p>
|
||||
<h3>Building with MinGW or Cygwin</h3>
|
||||
<p>
|
||||
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
|
||||
you've unpacked the sources and run this command for MinGW:
|
||||
</p>
|
||||
<pre class="code">
|
||||
mingw32-make
|
||||
</pre>
|
||||
<p>
|
||||
Or this command for Cygwin:
|
||||
</p>
|
||||
<pre class="code">
|
||||
make
|
||||
</pre>
|
||||
<p>
|
||||
Then follow the installation instructions below.
|
||||
</p>
|
||||
<h3>Installing LuaJIT</h3>
|
||||
<p>
|
||||
Copy <tt>luajit.exe</tt> and <tt>lua51.dll</tt> (built in the <tt>src</tt>
|
||||
directory) to a newly created directory (any location is ok).
|
||||
Add <tt>lua</tt> and <tt>lua\jit</tt> directories below it and copy
|
||||
all Lua files from the <tt>src\jit</tt> directory of the distribution
|
||||
to the latter directory.
|
||||
</p>
|
||||
<p>
|
||||
There are no hardcoded
|
||||
absolute path names — all modules are loaded relative to the
|
||||
directory where <tt>luajit.exe</tt> is installed
|
||||
(see <tt>src/luaconf.h</tt>).
|
||||
</p>
|
||||
|
||||
<h2 id="cross">Cross-compiling LuaJIT</h2>
|
||||
<p>
|
||||
First, let's clear up some terminology:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Host: This is your development system, usually based on a x64 or x86 CPU.</li>
|
||||
<li>Target: This is the target system you want LuaJIT to run on, e.g. Android/ARM.</li>
|
||||
<li>Toolchain: This comprises a C compiler, linker, assembler and a matching C library.</li>
|
||||
<li>Host (or system) toolchain: This is the toolchain used to build native binaries for your host system.</li>
|
||||
<li>Cross-compile toolchain: This is the toolchain used to build binaries for the target system. They can only be run on the target system.</li>
|
||||
</ul>
|
||||
<p>
|
||||
The GNU Makefile-based build system allows cross-compiling on any host
|
||||
for any supported target:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Yes, you need a toolchain for both your host <em>and</em> your target!</li>
|
||||
<li>Both host and target architectures must have the same pointer size.</li>
|
||||
<li>E.g. if you want to cross-compile to a 32 bit target on a 64 bit host, you need to install the multilib development package (e.g. <tt>libc6-dev-i386</tt> on Debian/Ubuntu) and build a 32 bit host part (<tt>HOST_CC="gcc -m32"</tt>).</li>
|
||||
<li>64 bit targets always require compilation on a 64 bit host.</li>
|
||||
</ul>
|
||||
<p>
|
||||
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:
|
||||
</p>
|
||||
<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>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>
|
||||
</ul>
|
||||
<p>
|
||||
Here are some examples where host and target have the same CPU:
|
||||
</p>
|
||||
<pre class="code">
|
||||
# Cross-compile to a 32 bit binary on a multilib x64 OS
|
||||
make CC="gcc -m32"
|
||||
|
||||
# Cross-compile on Debian/Ubuntu for Windows (mingw32 package)
|
||||
make HOST_CC="gcc -m32" CROSS=i586-mingw32msvc- TARGET_SYS=Windows
|
||||
</pre>
|
||||
<p id="cross2">
|
||||
The <tt>CROSS</tt> prefix allows specifying a standard GNU cross-compile
|
||||
toolchain (Binutils, GCC and a matching libc). The prefix may vary
|
||||
depending on the <tt>--target</tt> the toolchain was built for (note the
|
||||
<tt>CROSS</tt> prefix has a trailing <tt>"-"</tt>). The examples below
|
||||
use the canonical toolchain triplets for Linux.
|
||||
</p>
|
||||
<p>
|
||||
Since there's often no easy way to detect CPU features at runtime, it's
|
||||
important to compile with the proper CPU or architecture settings:
|
||||
</o>
|
||||
<ul>
|
||||
<li>The best way to get consistent results is to specify the correct settings when building the toolchain yourself.</li>
|
||||
<li>For a pre-built, generic toolchain add <tt>-mcpu=...</tt> or <tt>-march=...</tt> and other necessary flags to <tt>TARGET_CFLAGS</tt>.</li>
|
||||
<li>For ARM it's important to have the correct <tt>-mfloat-abi=...</tt> setting, too. Otherwise LuaJIT may not run at the full performance of your target CPU.</li>
|
||||
<li>For MIPS it's important to select a supported ABI (o32 on MIPS32, n64 on MIPS64) and consistently compile your project either with hard-float or soft-float compiler settings.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Here are some examples for targets with a different CPU than the host:
|
||||
</p>
|
||||
<pre class="code">
|
||||
# ARM soft-float
|
||||
make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
|
||||
TARGET_CFLAGS="-mfloat-abi=soft"
|
||||
|
||||
# ARM soft-float ABI with VFP (example for Cortex-A9)
|
||||
make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabi- \
|
||||
TARGET_CFLAGS="-mcpu=cortex-a9 -mfloat-abi=softfp"
|
||||
|
||||
# ARM hard-float ABI with VFP (armhf, most modern toolchains)
|
||||
make HOST_CC="gcc -m32" CROSS=arm-linux-gnueabihf-
|
||||
|
||||
# ARM64
|
||||
make CROSS=aarch64-linux-
|
||||
|
||||
# PPC
|
||||
make HOST_CC="gcc -m32" CROSS=powerpc-linux-gnu-
|
||||
|
||||
# MIPS32 big-endian
|
||||
make HOST_CC="gcc -m32" CROSS=mips-linux-
|
||||
# MIPS32 little-endian
|
||||
make HOST_CC="gcc -m32" CROSS=mipsel-linux-
|
||||
|
||||
# MIPS64 big-endian
|
||||
make CROSS=mips-linux- TARGET_CFLAGS="-mips64r2 -mabi=64"
|
||||
# MIPS64 little-endian
|
||||
make CROSS=mipsel-linux- TARGET_CFLAGS="-mips64r2 -mabi=64"
|
||||
</pre>
|
||||
<p>
|
||||
You can cross-compile for <b id="android">Android</b> using the <a href="https://developer.android.com/ndk/index.html">Android NDK</a>.
|
||||
The environment variables need to match the install locations and the
|
||||
desired target platform. E.g. Android 4.0 corresponds to ABI level 14.
|
||||
For details check the folder <tt>docs</tt> in the NDK directory.
|
||||
</p>
|
||||
<p>
|
||||
Only a few common variations for the different CPUs, ABIs and platforms
|
||||
are listed. Please use your own judgement for which combination you want
|
||||
to build/deploy or which lowest common denominator you want to pick:
|
||||
</p>
|
||||
<pre class="code">
|
||||
# Android/ARM, armeabi (ARMv5TE soft-float), Android 2.2+ (Froyo)
|
||||
NDK=/opt/android/ndk
|
||||
NDKABI=8
|
||||
NDKVER=$NDK/toolchains/arm-linux-androideabi-4.9
|
||||
NDKP=$NDKVER/prebuilt/linux-x86/bin/arm-linux-androideabi-
|
||||
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm"
|
||||
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF"
|
||||
|
||||
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.0+ (ICS)
|
||||
NDK=/opt/android/ndk
|
||||
NDKABI=14
|
||||
NDKVER=$NDK/toolchains/arm-linux-androideabi-4.9
|
||||
NDKP=$NDKVER/prebuilt/linux-x86/bin/arm-linux-androideabi-
|
||||
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-arm"
|
||||
NDKARCH="-march=armv7-a -mfloat-abi=softfp -Wl,--fix-cortex-a8"
|
||||
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF $NDKARCH"
|
||||
|
||||
# Android/MIPS, mipsel (MIPS32R1 hard-float), Android 4.0+ (ICS)
|
||||
NDK=/opt/android/ndk
|
||||
NDKABI=14
|
||||
NDKVER=$NDK/toolchains/mipsel-linux-android-4.9
|
||||
NDKP=$NDKVER/prebuilt/linux-x86/bin/mipsel-linux-android-
|
||||
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-mips"
|
||||
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF"
|
||||
|
||||
# Android/x86, x86 (i686 SSE3), Android 4.0+ (ICS)
|
||||
NDK=/opt/android/ndk
|
||||
NDKABI=14
|
||||
NDKVER=$NDK/toolchains/x86-4.9
|
||||
NDKP=$NDKVER/prebuilt/linux-x86/bin/i686-linux-android-
|
||||
NDKF="--sysroot $NDK/platforms/android-$NDKABI/arch-x86"
|
||||
make HOST_CC="gcc -m32" CROSS=$NDKP TARGET_FLAGS="$NDKF"
|
||||
</pre>
|
||||
<p>
|
||||
You can cross-compile for <b id="ios">iOS 3.0+</b> (iPhone/iPad) using the <a href="http://developer.apple.com/devcenter/ios/index.action"><span class="ext">»</span> iOS SDK</a>:
|
||||
</p>
|
||||
<p style="font-size: 8pt;">
|
||||
Note: <b>the JIT compiler is disabled for iOS</b>, because regular iOS Apps
|
||||
are not allowed to generate code at runtime. You'll only get the performance
|
||||
of the LuaJIT interpreter on iOS. This is still faster than plain Lua, but
|
||||
much slower than the JIT compiler. Please complain to Apple, not me.
|
||||
Or use Android. :-p
|
||||
</p>
|
||||
<pre class="code">
|
||||
# iOS/ARM (32 bit)
|
||||
ISDKP=$(xcrun --sdk iphoneos --show-sdk-path)
|
||||
ICC=$(xcrun --sdk iphoneos --find clang)
|
||||
ISDKF="-arch armv7 -isysroot $ISDKP"
|
||||
make DEFAULT_CC=clang HOST_CC="clang -m32 -arch i386" \
|
||||
CROSS="$(dirname $ICC)/" TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS
|
||||
|
||||
# iOS/ARM64
|
||||
ISDKP=$(xcrun --sdk iphoneos --show-sdk-path)
|
||||
ICC=$(xcrun --sdk iphoneos --find clang)
|
||||
ISDKF="-arch arm64 -isysroot $ISDKP"
|
||||
make DEFAULT_CC=clang CROSS="$(dirname $ICC)/" \
|
||||
TARGET_FLAGS="$ISDKF" TARGET_SYS=iOS
|
||||
</pre>
|
||||
|
||||
<h3 id="consoles">Cross-compiling for consoles</h3>
|
||||
<p>
|
||||
Building LuaJIT for consoles requires both a supported host compiler
|
||||
(x86 or x64) and a cross-compiler (to PPC or ARM) from the official
|
||||
console SDK.
|
||||
</p>
|
||||
<p>
|
||||
Due to restrictions on consoles, the JIT compiler is disabled and only
|
||||
the fast interpreter is built. This is still faster than plain Lua,
|
||||
but much slower than the JIT compiler. The FFI is disabled, too, since
|
||||
it's not very useful in such an environment.
|
||||
</p>
|
||||
<p>
|
||||
The following commands build a static library <tt>libluajit.a</tt>,
|
||||
which can be linked against your game, just like the Lua library.
|
||||
</p>
|
||||
<p>
|
||||
To cross-compile for <b id="ps3">PS3</b> from a Linux host (requires
|
||||
32 bit GCC, i.e. multilib Linux/x64) or a Windows host (requires
|
||||
32 bit MinGW), run this command:
|
||||
</p>
|
||||
<pre class="code">
|
||||
make HOST_CC="gcc -m32" CROSS=ppu-lv2-
|
||||
</pre>
|
||||
<p>
|
||||
To cross-compile for <b id="ps4">PS4</b> from a Windows host,
|
||||
open a "Visual Studio .NET Command Prompt" (64 bit host compiler),
|
||||
<tt>cd</tt> to the directory where you've unpacked the sources and
|
||||
run the following commands:
|
||||
</p>
|
||||
<pre class="code">
|
||||
cd src
|
||||
ps4build
|
||||
</pre>
|
||||
<p>
|
||||
To cross-compile for <b id="psvita">PS Vita</b> from a Windows host,
|
||||
open a "Visual Studio .NET Command Prompt" (32 bit host compiler),
|
||||
<tt>cd</tt> to the directory where you've unpacked the sources and
|
||||
run the following commands:
|
||||
</p>
|
||||
<pre class="code">
|
||||
cd src
|
||||
psvitabuild
|
||||
</pre>
|
||||
<p>
|
||||
To cross-compile for <b id="xbox360">Xbox 360</b> from a Windows host,
|
||||
open a "Visual Studio .NET Command Prompt" (32 bit host compiler),
|
||||
<tt>cd</tt> to the directory where you've unpacked the sources and run
|
||||
the following commands:
|
||||
</p>
|
||||
<pre class="code">
|
||||
cd src
|
||||
xedkbuild
|
||||
</pre>
|
||||
<p>
|
||||
To cross-compile for <b id="xboxone">Xbox One</b> from a Windows host,
|
||||
open a "Visual Studio .NET Command Prompt" (64 bit host compiler),
|
||||
<tt>cd</tt> to the directory where you've unpacked the sources and run
|
||||
the following commands:
|
||||
</p>
|
||||
<pre class="code">
|
||||
cd src
|
||||
xb1build
|
||||
</pre>
|
||||
|
||||
<h2 id="embed">Embedding LuaJIT</h2>
|
||||
<p>
|
||||
LuaJIT is API-compatible with Lua 5.1. If you've already embedded Lua
|
||||
into your application, you probably don't need to do anything to switch
|
||||
to LuaJIT, except link with a different library:
|
||||
</p>
|
||||
<ul>
|
||||
<li>It's strongly suggested to build LuaJIT separately using the supplied
|
||||
build system. Please do <em>not</em> attempt to integrate the individual
|
||||
source files into your build tree. You'll most likely get the internal build
|
||||
dependencies wrong or mess up the compiler flags. Treat LuaJIT like any
|
||||
other external library and link your application with either the dynamic
|
||||
or static library, depending on your needs.</li>
|
||||
<li>If you want to load C modules compiled for plain Lua
|
||||
with <tt>require()</tt>, you need to make sure the public symbols
|
||||
(e.g. <tt>lua_pushnumber</tt>) are exported, too:
|
||||
<ul><li>On POSIX systems you can either link to the shared library
|
||||
or link the static library into your application. In the latter case
|
||||
you'll need to export all public symbols from your main executable
|
||||
(e.g. <tt>-Wl,-E</tt> on Linux) and add the external dependencies
|
||||
(e.g. <tt>-lm -ldl</tt> on Linux).</li>
|
||||
<li>Since Windows symbols are bound to a specific DLL name, you need to
|
||||
link to the <tt>lua51.dll</tt> created by the LuaJIT build (do not rename
|
||||
the DLL). You may link LuaJIT statically on Windows only if you don't
|
||||
intend to load Lua/C modules at runtime.
|
||||
</li></ul>
|
||||
</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>
|
||||
<p>Additional hints for initializing LuaJIT using the C API functions:</p>
|
||||
<ul>
|
||||
<li>Here's a
|
||||
<a href="http://lua-users.org/wiki/SimpleLuaApiExample"><span class="ext">»</span> simple example</a>
|
||||
for embedding Lua or LuaJIT into your application.</li>
|
||||
<li>Make sure you use <tt>luaL_newstate</tt>. Avoid using
|
||||
<tt>lua_newstate</tt>, since this uses the (slower) default memory
|
||||
allocator from your system (no support for this on x64).</li>
|
||||
<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>
|
||||
<li>To change or extend the list of standard libraries to load, copy
|
||||
<tt>src/lib_init.c</tt> to your project and modify it accordingly.
|
||||
Make sure the <tt>jit</tt> library is loaded or the JIT compiler
|
||||
will not be activated.</li>
|
||||
<li>The <tt>bit.*</tt> module for bitwise operations
|
||||
is already built-in. There's no need to statically link
|
||||
<a href="http://bitop.luajit.org/"><span class="ext">»</span> Lua BitOp</a> to your application.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="distro">Hints for Distribution Maintainers</h2>
|
||||
<p>
|
||||
The LuaJIT build system has extra provisions for the needs of most
|
||||
POSIX-based distributions. If you're a package maintainer for
|
||||
a distribution, <em>please</em> make use of these features and
|
||||
avoid patching, subverting, autotoolizing or messing up the build system
|
||||
in unspeakable ways.
|
||||
</p>
|
||||
<p>
|
||||
There should be absolutely no need to patch <tt>luaconf.h</tt> or any
|
||||
of the Makefiles. And please do not hand-pick files for your packages —
|
||||
simply use whatever <tt>make install</tt> creates. There's a reason
|
||||
for all of the files <em>and</em> directories it creates.
|
||||
</p>
|
||||
<p>
|
||||
The build system uses GNU make and auto-detects most settings based on
|
||||
the host you're building it on. This should work fine for native builds,
|
||||
even when sandboxed. You may need to pass some of the following flags to
|
||||
<em>both</em> the <tt>make</tt> and the <tt>make install</tt> command lines
|
||||
for a regular distribution build:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>PREFIX</tt> overrides the installation path and should usually
|
||||
be set to <tt>/usr</tt>. Setting this also changes the module paths and
|
||||
the paths needed to locate the shared library.</li>
|
||||
<li><tt>DESTDIR</tt> is an absolute path which allows you to install
|
||||
to a shadow tree instead of the root tree of the build system.</li>
|
||||
<li><tt>MULTILIB</tt> sets the architecture-specific library path component
|
||||
for multilib systems. The default is <tt>lib</tt>.</li>
|
||||
<li>Have a look at the top-level <tt>Makefile</tt> and <tt>src/Makefile</tt>
|
||||
for additional variables to tweak. The following variables <em>may</em> be
|
||||
overridden, but it's <em>not</em> recommended, except for special needs
|
||||
like cross-builds:
|
||||
<tt>BUILDMODE, CC, HOST_CC, STATIC_CC, DYNAMIC_CC, CFLAGS, HOST_CFLAGS,
|
||||
TARGET_CFLAGS, LDFLAGS, HOST_LDFLAGS, TARGET_LDFLAGS, TARGET_SHLDFLAGS,
|
||||
TARGET_FLAGS, LIBS, HOST_LIBS, TARGET_LIBS, CROSS, HOST_SYS, TARGET_SYS
|
||||
</tt></li>
|
||||
</ul>
|
||||
<p>
|
||||
The build system has a special target for an amalgamated build, i.e.
|
||||
<tt>make amalg</tt>. This compiles the LuaJIT core as one huge C file
|
||||
and allows GCC to generate faster and shorter code. Alas, this requires
|
||||
lots of memory during the build. This may be a problem for some users,
|
||||
that's why it's not enabled by default. But it shouldn't be a problem for
|
||||
most build farms. It's recommended that binary distributions use this
|
||||
target for their LuaJIT builds.
|
||||
</p>
|
||||
<p>
|
||||
The tl;dr version of the above:
|
||||
</p>
|
||||
<pre class="code">
|
||||
make amalg PREFIX=/usr && \
|
||||
make install PREFIX=/usr DESTDIR=/tmp/buildroot
|
||||
</pre>
|
||||
<p>
|
||||
Finally, if you encounter any difficulties, please
|
||||
<a href="contact.html">contact me</a> first, instead of releasing a broken
|
||||
package onto unsuspecting users. Because they'll usually gonna complain
|
||||
to me (the upstream) and not you (the package maintainer), anyway.
|
||||
</p>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,236 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>LuaJIT</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
<meta name="description" content="LuaJIT is a Just-In-Time (JIT) compiler for the Lua language.">
|
||||
<style type="text/css">
|
||||
table.feature {
|
||||
width: inherit;
|
||||
line-height: 1.2;
|
||||
margin: 0;
|
||||
}
|
||||
table.feature td {
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
vertical-align: middle;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border: 4px solid #e6ecff;
|
||||
border-radius: 12px;
|
||||
}
|
||||
table.os td {
|
||||
background: #7080d0;
|
||||
background-image: linear-gradient(#4060c0 10%, #b0b0ff 95%);
|
||||
background-image: -moz-linear-gradient(#4060c0 10%, #b0b0ff 95%);
|
||||
background-image: -webkit-linear-gradient(#4060c0 10%, #b0b0ff 95%);
|
||||
background-image: -o-linear-gradient(#4060c0 10%, #b0b0ff 95%);
|
||||
background-image: -ms-linear-gradient(#4060c0 10%, #b0b0ff 95%);
|
||||
}
|
||||
table.os1 td {
|
||||
color: #ffff80;
|
||||
}
|
||||
table.os2 td {
|
||||
color: #ffa040;
|
||||
}
|
||||
table.os3 td {
|
||||
color: #40ffff;
|
||||
}
|
||||
table.compiler td {
|
||||
color: #2080ff;
|
||||
background: #62bf41;
|
||||
background-image: linear-gradient(#62bf41 10%, #b0ffb0 95%);
|
||||
background-image: -moz-linear-gradient(#62bf41 10%, #b0ffb0 95%);
|
||||
background-image: -webkit-linear-gradient(#62bf41 10%, #b0ffb0 95%);
|
||||
background-image: -o-linear-gradient(#62bf41 10%, #b0ffb0 95%);
|
||||
background-image: -ms-linear-gradient(#62bf41 10%, #b0ffb0 95%);
|
||||
}
|
||||
table.cpu td {
|
||||
color: #ffff00;
|
||||
background: #cf7251;
|
||||
background-image: linear-gradient(#bf6241 10%, #ffb0b0 95%);
|
||||
background-image: -moz-linear-gradient(#bf6241 10%, #ffb0b0 95%);
|
||||
background-image: -webkit-linear-gradient(#bf6241 10%, #ffb0b0 95%);
|
||||
background-image: -o-linear-gradient(#bf6241 10%, #ffb0b0 95%);
|
||||
background-image: -ms-linear-gradient(#bf6241 10%, #ffb0b0 95%);
|
||||
}
|
||||
table.fcompat td {
|
||||
color: #2060e0;
|
||||
background: #61cfcf;
|
||||
background-image: linear-gradient(#41bfbf 10%, #b0ffff 95%);
|
||||
background-image: -moz-linear-gradient(#41bfbf 10%, #b0ffff 95%);
|
||||
background-image: -webkit-linear-gradient(#41bfbf 10%, #b0ffff 95%);
|
||||
background-image: -o-linear-gradient(#41bfbf 10%, #b0ffff 95%);
|
||||
background-image: -ms-linear-gradient(#41bfbf 10%, #b0ffff 95%);
|
||||
}
|
||||
table.stats td {
|
||||
color: #ffffff;
|
||||
background: #a0a0a0;
|
||||
background-image: linear-gradient(#808080 10%, #d0d0d0 95%);
|
||||
background-image: -moz-linear-gradient(#808080 10%, #d0d0d0 95%);
|
||||
background-image: -webkit-linear-gradient(#808080 10%, #d0d0d0 95%);
|
||||
background-image: -o-linear-gradient(#808080 10%, #d0d0d0 95%);
|
||||
background-image: -ms-linear-gradient(#808080 10%, #d0d0d0 95%);
|
||||
}
|
||||
table.stats td.speed {
|
||||
color: #ff4020;
|
||||
}
|
||||
table.stats td.kb {
|
||||
color: #ffff80;
|
||||
background: #808080;
|
||||
background-image: linear-gradient(#606060 10%, #c0c0c0 95%);
|
||||
background-image: -moz-linear-gradient(#606060 10%, #c0c0c0 95%);
|
||||
background-image: -webkit-linear-gradient(#606060 10%, #c0c0c0 95%);
|
||||
background-image: -o-linear-gradient(#606060 10%, #c0c0c0 95%);
|
||||
background-image: -ms-linear-gradient(#606060 10%, #c0c0c0 95%);
|
||||
}
|
||||
table.feature small {
|
||||
font-size: 50%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>LuaJIT</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a class="current" href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
LuaJIT is a <b>Just-In-Time Compiler</b> (JIT) for the
|
||||
<a href="http://www.lua.org/"><span class="ext">»</span> Lua</a> programming language.
|
||||
Lua is a powerful, dynamic and light-weight programming language.
|
||||
It may be embedded or used as a general-purpose, stand-alone language.
|
||||
</p>
|
||||
<p>
|
||||
LuaJIT is Copyright © 2005-2017 Mike Pall, released under the
|
||||
<a href="http://www.opensource.org/licenses/mit-license.php"><span class="ext">»</span> MIT open source license</a>.
|
||||
</p>
|
||||
<p>
|
||||
</p>
|
||||
|
||||
<h2>Compatibility</h2>
|
||||
<table class="feature os os1">
|
||||
<tr><td>Windows</td><td>Linux</td><td>BSD</td><td>OSX</td><td>POSIX</td></tr>
|
||||
</table>
|
||||
<table class="feature os os2">
|
||||
<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td></tr>
|
||||
</table>
|
||||
<table class="feature os os3">
|
||||
<tr><td>PS3</td><td>PS4</td><td>PS Vita</td><td>Xbox 360</td><td>Xbox One</td></tr>
|
||||
</table>
|
||||
<table class="feature compiler">
|
||||
<tr><td>GCC</td><td>Clang<br>LLVM</td><td>MSVC</td></tr>
|
||||
</table>
|
||||
<table class="feature cpu">
|
||||
<tr><td>x86<br>x64</td><td>ARM<br>ARM64</td><td>PPC</td><td>MIPS32<br>MIPS64</td></tr>
|
||||
</table>
|
||||
<table class="feature fcompat">
|
||||
<tr><td>Lua 5.1<br>API+ABI</td><td>+ JIT</td><td>+ BitOp</td><td>+ FFI</td><td>Drop-in<br>DLL/.so</td></tr>
|
||||
</table>
|
||||
|
||||
<h2>Overview</h2>
|
||||
<table class="feature stats">
|
||||
<tr>
|
||||
<td class="speed">3x<br>- 100x</td>
|
||||
<td class="kb">115 <small>KB</small><br>VM</td>
|
||||
<td class="kb">90 <small>KB</small><br>JIT</td>
|
||||
<td class="kloc">63 <small>KLOC</small><br>C</td>
|
||||
<td class="kloc">24 <small>KLOC</small><br>ASM</td>
|
||||
<td class="kloc">11 <small>KLOC</small><br>Lua</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p style="margin-top: 1em;">
|
||||
LuaJIT has been successfully used as a <b>scripting middleware</b> in
|
||||
games, appliances, network and graphics apps, numerical simulations,
|
||||
trading platforms and many other specialty applications. It scales from
|
||||
embedded devices, smartphones, desktops up to server farms. It combines
|
||||
high flexibility with <a href="http://luajit.org/performance.html"><span class="ext">»</span> high performance</a>
|
||||
and an unmatched <b>low memory footprint</b>.
|
||||
</p>
|
||||
<p>
|
||||
LuaJIT has been in continuous development since 2005. It's widely
|
||||
considered to be <b>one of the fastest dynamic language
|
||||
implementations</b>. It has outperformed other dynamic languages on many
|
||||
cross-language benchmarks since its first release — often by a
|
||||
substantial margin.
|
||||
</p>
|
||||
<p>
|
||||
For <b>LuaJIT 2.0</b>, the whole VM has been rewritten from the ground up
|
||||
and relentlessly optimized for performance. It combines a <b>high-speed
|
||||
interpreter</b>, written in assembler, with a <b>state-of-the-art JIT
|
||||
compiler</b>.
|
||||
</p>
|
||||
<p>
|
||||
An innovative <b>trace compiler</b> is integrated with advanced,
|
||||
SSA-based optimizations and highly tuned code generation backends.
|
||||
A substantial reduction of the overhead associated with dynamic languages
|
||||
allows it to break into the performance range traditionally reserved for
|
||||
offline, static language compilers.
|
||||
</p>
|
||||
|
||||
<h2>More ...</h2>
|
||||
<p>
|
||||
Please select a sub-topic in the navigation bar to learn more about LuaJIT.
|
||||
</p>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,309 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Running LuaJIT</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
table.opt {
|
||||
line-height: 1.2;
|
||||
}
|
||||
tr.opthead td {
|
||||
font-weight: bold;
|
||||
}
|
||||
td.flag_name {
|
||||
width: 4em;
|
||||
}
|
||||
td.flag_level {
|
||||
width: 2em;
|
||||
text-align: center;
|
||||
}
|
||||
td.param_name {
|
||||
width: 6em;
|
||||
}
|
||||
td.param_default {
|
||||
width: 4em;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Running LuaJIT</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://luajit.org/download.html">Download <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="install.html">Installation</a>
|
||||
</li><li>
|
||||
<a class="current" 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 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>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
LuaJIT has only a single stand-alone executable, called <tt>luajit</tt> on
|
||||
POSIX systems or <tt>luajit.exe</tt> on Windows. It can be used to run simple
|
||||
Lua statements or whole Lua applications from the command line. It has an
|
||||
interactive mode, too.
|
||||
</p>
|
||||
|
||||
<h2 id="options">Command Line Options</h2>
|
||||
<p>
|
||||
The <tt>luajit</tt> stand-alone executable is just a slightly modified
|
||||
version of the regular <tt>lua</tt> stand-alone executable.
|
||||
It supports the same basic options, too. <tt>luajit -h</tt>
|
||||
prints a short list of the available options. Please have a look at the
|
||||
<a href="http://www.lua.org/manual/5.1/manual.html#6"><span class="ext">»</span> Lua manual</a>
|
||||
for details.
|
||||
</p>
|
||||
<p>
|
||||
LuaJIT has some additional options:
|
||||
</p>
|
||||
|
||||
<h3 id="opt_b"><tt>-b[options] input output</tt></h3>
|
||||
<p>
|
||||
This option saves or lists bytecode. The following additional options
|
||||
are accepted:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>-l</tt> — Only list bytecode.</li>
|
||||
<li><tt>-s</tt> — Strip debug info (this is the default).</li>
|
||||
<li><tt>-g</tt> — Keep debug info.</li>
|
||||
<li><tt>-n name</tt> — Set module name (default: auto-detect from input name)</li>
|
||||
<li><tt>-t type</tt> — Set output file type (default: auto-detect from output name).</li>
|
||||
<li><tt>-a arch</tt> — Override architecture for object files (default: native).</li>
|
||||
<li><tt>-o os</tt> — Override OS for object files (default: native).</li>
|
||||
<li><tt>-e chunk</tt> — Use chunk string as input.</li>
|
||||
<li><tt>-</tt> (a single minus sign) — Use stdin as input and/or stdout as output.</li>
|
||||
</ul>
|
||||
<p>
|
||||
The output file type is auto-detected from the extension of the output
|
||||
file name:
|
||||
</p>
|
||||
<ul>
|
||||
<li><tt>c</tt> — C source file, exported bytecode data.</li>
|
||||
<li><tt>h</tt> — C header file, static bytecode data.</li>
|
||||
<li><tt>obj</tt> or <tt>o</tt> — Object file, exported bytecode data
|
||||
(OS- and architecture-specific).</li>
|
||||
<li><tt>raw</tt> or any other extension — Raw bytecode file (portable).
|
||||
</ul>
|
||||
<p>
|
||||
Notes:
|
||||
</p>
|
||||
<ul>
|
||||
<li>See also <a href="extensions.html#string_dump">string.dump()</a>
|
||||
for information on bytecode portability and compatibility.</li>
|
||||
<li>A file in raw bytecode format is auto-detected and can be loaded like
|
||||
any Lua source file. E.g. directly from the command line or with
|
||||
<tt>loadfile()</tt>, <tt>dofile()</tt> etc.</li>
|
||||
<li>To statically embed the bytecode of a module in your application,
|
||||
generate an object file and just link it with your application.</li>
|
||||
<li>On most ELF-based systems (e.g. Linux) you need to explicitly export the
|
||||
global symbols when linking your application, e.g. with: <tt>-Wl,-E</tt></li>
|
||||
<li><tt>require()</tt> tries to load embedded bytecode data from exported
|
||||
symbols (in <tt>*.exe</tt> or <tt>lua51.dll</tt> on Windows) and from
|
||||
shared libraries in <tt>package.cpath</tt>.</li>
|
||||
</ul>
|
||||
<p>
|
||||
Typical usage examples:
|
||||
</p>
|
||||
<pre class="code">
|
||||
luajit -b test.lua test.out # Save bytecode to test.out
|
||||
luajit -bg test.lua test.out # Keep debug info
|
||||
luajit -be "print('hello world')" test.out # Save cmdline script
|
||||
|
||||
luajit -bl test.lua # List to stdout
|
||||
luajit -bl test.lua test.txt # List to test.txt
|
||||
luajit -ble "print('hello world')" # List cmdline script
|
||||
|
||||
luajit -b test.lua test.obj # Generate object file
|
||||
# Link test.obj with your application and load it with require("test")
|
||||
</pre>
|
||||
|
||||
<h3 id="opt_j"><tt>-j cmd[=arg[,arg...]]</tt></h3>
|
||||
<p>
|
||||
This option performs a LuaJIT control command or activates one of the
|
||||
loadable extension modules. The command is first looked up in the
|
||||
<tt>jit.*</tt> library. If no matching function is found, a module
|
||||
named <tt>jit.<cmd></tt> is loaded and the <tt>start()</tt>
|
||||
function of the module is called with the specified arguments (if
|
||||
any). The space between <tt>-j</tt> and <tt>cmd</tt> is optional.
|
||||
</p>
|
||||
<p>
|
||||
Here are the available LuaJIT control commands:
|
||||
</p>
|
||||
<ul>
|
||||
<li id="j_on"><tt>-jon</tt> — Turns the JIT compiler on (default).</li>
|
||||
<li id="j_off"><tt>-joff</tt> — Turns the JIT compiler off (only use the interpreter).</li>
|
||||
<li id="j_flush"><tt>-jflush</tt> — Flushes the whole cache of compiled code.</li>
|
||||
<li id="j_v"><tt>-jv</tt> — Shows verbose information about the progress of the JIT compiler.</li>
|
||||
<li id="j_dump"><tt>-jdump</tt> — Dumps the code and structures used in various compiler stages.</li>
|
||||
<li id="j_p"><tt>-jp</tt> — Start the <a href="ext_profiler.html">integrated profiler</a>.</li>
|
||||
</ul>
|
||||
<p>
|
||||
The <tt>-jv</tt> and <tt>-jdump</tt> commands are extension modules
|
||||
written in Lua. They are mainly used for debugging the JIT compiler
|
||||
itself. For a description of their options and output format, please
|
||||
read the comment block at the start of their 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
|
||||
this is <tt>/usr/local/share/luajit-2.0.5/jit</tt> on POSIX
|
||||
systems.
|
||||
</p>
|
||||
|
||||
<h3 id="opt_O"><tt>-O[level]</tt><br>
|
||||
<tt>-O[+]flag</tt> <tt>-O-flag</tt><br>
|
||||
<tt>-Oparam=value</tt></h3>
|
||||
<p>
|
||||
This options allows fine-tuned control of the optimizations used by
|
||||
the JIT compiler. This is mainly intended for debugging LuaJIT itself.
|
||||
Please note that the JIT compiler is extremely fast (we are talking
|
||||
about the microsecond to millisecond range). Disabling optimizations
|
||||
doesn't have any visible impact on its overhead, but usually generates
|
||||
code that runs slower.
|
||||
</p>
|
||||
<p>
|
||||
The first form sets an optimization level — this enables a
|
||||
specific mix of optimization flags. <tt>-O0</tt> turns off all
|
||||
optimizations and higher numbers enable more optimizations. Omitting
|
||||
the level (i.e. just <tt>-O</tt>) sets the default optimization level,
|
||||
which is <tt>-O3</tt> in the current version.
|
||||
</p>
|
||||
<p>
|
||||
The second form adds or removes individual optimization flags.
|
||||
The third form sets a parameter for the VM or the JIT compiler
|
||||
to a specific value.
|
||||
</p>
|
||||
<p>
|
||||
You can either use this option multiple times (like <tt>-Ocse
|
||||
-O-dce -Ohotloop=10</tt>) or separate several settings with a comma
|
||||
(like <tt>-O+cse,-dce,hotloop=10</tt>). The settings are applied from
|
||||
left to right and later settings override earlier ones. You can freely
|
||||
mix the three forms, but note that setting an optimization level
|
||||
overrides all earlier flags.
|
||||
</p>
|
||||
<p>
|
||||
Here are the available flags and at what optimization levels they
|
||||
are enabled:
|
||||
</p>
|
||||
<table class="opt">
|
||||
<tr class="opthead">
|
||||
<td class="flag_name">Flag</td>
|
||||
<td class="flag_level">-O1</td>
|
||||
<td class="flag_level">-O2</td>
|
||||
<td class="flag_level">-O3</td>
|
||||
<td class="flag_desc"> </td>
|
||||
</tr>
|
||||
<tr class="odd separate">
|
||||
<td class="flag_name">fold</td><td class="flag_level">•</td><td class="flag_level">•</td><td class="flag_level">•</td><td class="flag_desc">Constant Folding, Simplifications and Reassociation</td></tr>
|
||||
<tr class="even">
|
||||
<td class="flag_name">cse</td><td class="flag_level">•</td><td class="flag_level">•</td><td class="flag_level">•</td><td class="flag_desc">Common-Subexpression Elimination</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="flag_name">dce</td><td class="flag_level">•</td><td class="flag_level">•</td><td class="flag_level">•</td><td class="flag_desc">Dead-Code Elimination</td></tr>
|
||||
<tr class="even">
|
||||
<td class="flag_name">narrow</td><td class="flag_level"> </td><td class="flag_level">•</td><td class="flag_level">•</td><td class="flag_desc">Narrowing of numbers to integers</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="flag_name">loop</td><td class="flag_level"> </td><td class="flag_level">•</td><td class="flag_level">•</td><td class="flag_desc">Loop Optimizations (code hoisting)</td></tr>
|
||||
<tr class="even">
|
||||
<td class="flag_name">fwd</td><td class="flag_level"> </td><td class="flag_level"> </td><td class="flag_level">•</td><td class="flag_desc">Load Forwarding (L2L) and Store Forwarding (S2L)</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="flag_name">dse</td><td class="flag_level"> </td><td class="flag_level"> </td><td class="flag_level">•</td><td class="flag_desc">Dead-Store Elimination</td></tr>
|
||||
<tr class="even">
|
||||
<td class="flag_name">abc</td><td class="flag_level"> </td><td class="flag_level"> </td><td class="flag_level">•</td><td class="flag_desc">Array Bounds Check Elimination</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="flag_name">sink</td><td class="flag_level"> </td><td class="flag_level"> </td><td class="flag_level">•</td><td class="flag_desc">Allocation/Store Sinking</td></tr>
|
||||
<tr class="even">
|
||||
<td class="flag_name">fuse</td><td class="flag_level"> </td><td class="flag_level"> </td><td class="flag_level">•</td><td class="flag_desc">Fusion of operands into instructions</td></tr>
|
||||
</table>
|
||||
<p>
|
||||
Here are the parameters and their default settings:
|
||||
</p>
|
||||
<table class="opt">
|
||||
<tr class="opthead">
|
||||
<td class="param_name">Parameter</td>
|
||||
<td class="param_default">Default</td>
|
||||
<td class="param_desc"> </td>
|
||||
</tr>
|
||||
<tr class="odd separate">
|
||||
<td class="param_name">maxtrace</td><td class="param_default">1000</td><td class="param_desc">Max. number of traces in the cache</td></tr>
|
||||
<tr class="even">
|
||||
<td class="param_name">maxrecord</td><td class="param_default">4000</td><td class="param_desc">Max. number of recorded IR instructions</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="param_name">maxirconst</td><td class="param_default">500</td><td class="param_desc">Max. number of IR constants of a trace</td></tr>
|
||||
<tr class="even">
|
||||
<td class="param_name">maxside</td><td class="param_default">100</td><td class="param_desc">Max. number of side traces of a root trace</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="param_name">maxsnap</td><td class="param_default">500</td><td class="param_desc">Max. number of snapshots for a trace</td></tr>
|
||||
<tr class="even separate">
|
||||
<td class="param_name">hotloop</td><td class="param_default">56</td><td class="param_desc">Number of iterations to detect a hot loop or hot call</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="param_name">hotexit</td><td class="param_default">10</td><td class="param_desc">Number of taken exits to start a side trace</td></tr>
|
||||
<tr class="even">
|
||||
<td class="param_name">tryside</td><td class="param_default">4</td><td class="param_desc">Number of attempts to compile a side trace</td></tr>
|
||||
<tr class="odd separate">
|
||||
<td class="param_name">instunroll</td><td class="param_default">4</td><td class="param_desc">Max. unroll factor for instable loops</td></tr>
|
||||
<tr class="even">
|
||||
<td class="param_name">loopunroll</td><td class="param_default">15</td><td class="param_desc">Max. unroll factor for loop ops in side traces</td></tr>
|
||||
<tr class="odd">
|
||||
<td class="param_name">callunroll</td><td class="param_default">3</td><td class="param_desc">Max. unroll factor for pseudo-recursive calls</td></tr>
|
||||
<tr class="even">
|
||||
<td class="param_name">recunroll</td><td class="param_default">2</td><td class="param_desc">Min. unroll factor for true recursion</td></tr>
|
||||
<tr class="odd separate">
|
||||
<td class="param_name">sizemcode</td><td class="param_default">32</td><td class="param_desc">Size of each machine code area in KBytes (Windows: 64K)</td></tr>
|
||||
<tr class="even">
|
||||
<td class="param_name">maxmcode</td><td class="param_default">512</td><td class="param_desc">Max. total size of all machine code areas in KBytes</td></tr>
|
||||
</table>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,123 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Status</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="Author" content="Mike Pall">
|
||||
<meta name="Copyright" content="Copyright (C) 2005-2017, Mike Pall">
|
||||
<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">
|
||||
ul li { padding-bottom: 0.3em; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="site">
|
||||
<a href="http://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
|
||||
</div>
|
||||
<div id="head">
|
||||
<h1>Status</h1>
|
||||
</div>
|
||||
<div id="nav">
|
||||
<ul><li>
|
||||
<a href="luajit.html">LuaJIT</a>
|
||||
<ul><li>
|
||||
<a href="http://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 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 class="current" href="status.html">Status</a>
|
||||
<ul><li>
|
||||
<a href="changes.html">Changes</a>
|
||||
</li></ul>
|
||||
</li><li>
|
||||
<a href="faq.html">FAQ</a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/performance.html">Performance <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://wiki.luajit.org/">Wiki <span class="ext">»</span></a>
|
||||
</li><li>
|
||||
<a href="http://luajit.org/list.html">Mailing List <span class="ext">»</span></a>
|
||||
</li></ul>
|
||||
</div>
|
||||
<div id="main">
|
||||
<p>
|
||||
<span style="color: #0000c0;">LuaJIT 2.0</span> is the current
|
||||
<span style="color: #0000c0;">stable branch</span>. This branch is in
|
||||
feature-freeze — new features will only be added to LuaJIT 2.1.
|
||||
</p>
|
||||
|
||||
<h2>Current Status</h2>
|
||||
<p>
|
||||
LuaJIT ought to run all Lua 5.1-compatible source code just fine.
|
||||
It's considered a serious bug if the VM crashes or produces unexpected
|
||||
results — please report this.
|
||||
</p>
|
||||
<p>
|
||||
Known incompatibilities and issues in LuaJIT 2.0:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
There are some differences in <b>implementation-defined</b> behavior.
|
||||
These either have a good reason, are arbitrary design choices
|
||||
or are due to quirks in the VM. The latter cases may get fixed if a
|
||||
demonstrable need is shown.
|
||||
</li>
|
||||
<li>
|
||||
The Lua <b>debug API</b> is missing a couple of features (return
|
||||
hooks for non-Lua functions) and shows slightly different behavior
|
||||
in LuaJIT (no per-coroutine hooks, no tail call counting).
|
||||
</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>
|
||||
<li>
|
||||
LuaJIT on 64 bit systems provides a <b>limited range</b> of 47 bits for the
|
||||
<b>legacy <tt>lightuserdata</tt></b> data type.
|
||||
This is only relevant on x64 systems which use the negative part of the
|
||||
virtual address space in user mode, e.g. Solaris/x64, and on ARM64 systems
|
||||
configured with a 48 bit or 52 bit VA.
|
||||
Avoid using <tt>lightuserdata</tt> to hold pointers that may point outside
|
||||
of that range, e.g. variables on the stack. In general, avoid this data
|
||||
type for new code and replace it with (much more performant) FFI bindings.
|
||||
FFI cdata pointers can address the full 64 bit range.
|
||||
</li>
|
||||
</ul>
|
||||
<br class="flush">
|
||||
</div>
|
||||
<div id="foot">
|
||||
<hr class="hide">
|
||||
Copyright © 2005-2017 Mike Pall
|
||||
<span class="noprint">
|
||||
·
|
||||
<a href="contact.html">Contact</a>
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** DynASM ARM encoding engine.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
------------------------------------------------------------------------------
|
||||
-- DynASM ARM module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
@ -9,9 +9,9 @@
|
|||
local _info = {
|
||||
arch = "arm",
|
||||
description = "DynASM ARM module",
|
||||
version = "1.3.0",
|
||||
vernum = 10300,
|
||||
release = "2011-05-05",
|
||||
version = "1.4.0",
|
||||
vernum = 10400,
|
||||
release = "2015-10-18",
|
||||
author = "Mike Pall",
|
||||
license = "MIT",
|
||||
}
|
||||
|
|
|
@ -0,0 +1,518 @@
|
|||
/*
|
||||
** DynASM ARM64 encoding engine.
|
||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define DASM_ARCH "arm64"
|
||||
|
||||
#ifndef DASM_EXTERN
|
||||
#define DASM_EXTERN(a,b,c,d) 0
|
||||
#endif
|
||||
|
||||
/* Action definitions. */
|
||||
enum {
|
||||
DASM_STOP, DASM_SECTION, DASM_ESC, DASM_REL_EXT,
|
||||
/* The following actions need a buffer position. */
|
||||
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
|
||||
/* The following actions also have an argument. */
|
||||
DASM_REL_PC, DASM_LABEL_PC,
|
||||
DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
|
||||
DASM__MAX
|
||||
};
|
||||
|
||||
/* Maximum number of section buffer positions for a single dasm_put() call. */
|
||||
#define DASM_MAXSECPOS 25
|
||||
|
||||
/* DynASM encoder status codes. Action list offset or number are or'ed in. */
|
||||
#define DASM_S_OK 0x00000000
|
||||
#define DASM_S_NOMEM 0x01000000
|
||||
#define DASM_S_PHASE 0x02000000
|
||||
#define DASM_S_MATCH_SEC 0x03000000
|
||||
#define DASM_S_RANGE_I 0x11000000
|
||||
#define DASM_S_RANGE_SEC 0x12000000
|
||||
#define DASM_S_RANGE_LG 0x13000000
|
||||
#define DASM_S_RANGE_PC 0x14000000
|
||||
#define DASM_S_RANGE_REL 0x15000000
|
||||
#define DASM_S_UNDEF_LG 0x21000000
|
||||
#define DASM_S_UNDEF_PC 0x22000000
|
||||
|
||||
/* Macros to convert positions (8 bit section + 24 bit index). */
|
||||
#define DASM_POS2IDX(pos) ((pos)&0x00ffffff)
|
||||
#define DASM_POS2BIAS(pos) ((pos)&0xff000000)
|
||||
#define DASM_SEC2POS(sec) ((sec)<<24)
|
||||
#define DASM_POS2SEC(pos) ((pos)>>24)
|
||||
#define DASM_POS2PTR(D, pos) (D->sections[DASM_POS2SEC(pos)].rbuf + (pos))
|
||||
|
||||
/* Action list type. */
|
||||
typedef const unsigned int *dasm_ActList;
|
||||
|
||||
/* Per-section structure. */
|
||||
typedef struct dasm_Section {
|
||||
int *rbuf; /* Biased buffer pointer (negative section bias). */
|
||||
int *buf; /* True buffer pointer. */
|
||||
size_t bsize; /* Buffer size in bytes. */
|
||||
int pos; /* Biased buffer position. */
|
||||
int epos; /* End of biased buffer position - max single put. */
|
||||
int ofs; /* Byte offset into section. */
|
||||
} dasm_Section;
|
||||
|
||||
/* Core structure holding the DynASM encoding state. */
|
||||
struct dasm_State {
|
||||
size_t psize; /* Allocated size of this structure. */
|
||||
dasm_ActList actionlist; /* Current actionlist pointer. */
|
||||
int *lglabels; /* Local/global chain/pos ptrs. */
|
||||
size_t lgsize;
|
||||
int *pclabels; /* PC label chains/pos ptrs. */
|
||||
size_t pcsize;
|
||||
void **globals; /* Array of globals (bias -10). */
|
||||
dasm_Section *section; /* Pointer to active section. */
|
||||
size_t codesize; /* Total size of all code sections. */
|
||||
int maxsection; /* 0 <= sectionidx < maxsection. */
|
||||
int status; /* Status code. */
|
||||
dasm_Section sections[1]; /* All sections. Alloc-extended. */
|
||||
};
|
||||
|
||||
/* The size of the core structure depends on the max. number of sections. */
|
||||
#define DASM_PSZ(ms) (sizeof(dasm_State)+(ms-1)*sizeof(dasm_Section))
|
||||
|
||||
|
||||
/* Initialize DynASM state. */
|
||||
void dasm_init(Dst_DECL, int maxsection)
|
||||
{
|
||||
dasm_State *D;
|
||||
size_t psz = 0;
|
||||
int i;
|
||||
Dst_REF = NULL;
|
||||
DASM_M_GROW(Dst, struct dasm_State, Dst_REF, psz, DASM_PSZ(maxsection));
|
||||
D = Dst_REF;
|
||||
D->psize = psz;
|
||||
D->lglabels = NULL;
|
||||
D->lgsize = 0;
|
||||
D->pclabels = NULL;
|
||||
D->pcsize = 0;
|
||||
D->globals = NULL;
|
||||
D->maxsection = maxsection;
|
||||
for (i = 0; i < maxsection; i++) {
|
||||
D->sections[i].buf = NULL; /* Need this for pass3. */
|
||||
D->sections[i].rbuf = D->sections[i].buf - DASM_SEC2POS(i);
|
||||
D->sections[i].bsize = 0;
|
||||
D->sections[i].epos = 0; /* Wrong, but is recalculated after resize. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Free DynASM state. */
|
||||
void dasm_free(Dst_DECL)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
for (i = 0; i < D->maxsection; i++)
|
||||
if (D->sections[i].buf)
|
||||
DASM_M_FREE(Dst, D->sections[i].buf, D->sections[i].bsize);
|
||||
if (D->pclabels) DASM_M_FREE(Dst, D->pclabels, D->pcsize);
|
||||
if (D->lglabels) DASM_M_FREE(Dst, D->lglabels, D->lgsize);
|
||||
DASM_M_FREE(Dst, D, D->psize);
|
||||
}
|
||||
|
||||
/* Setup global label array. Must be called before dasm_setup(). */
|
||||
void dasm_setupglobal(Dst_DECL, void **gl, unsigned int maxgl)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
D->globals = gl - 10; /* Negative bias to compensate for locals. */
|
||||
DASM_M_GROW(Dst, int, D->lglabels, D->lgsize, (10+maxgl)*sizeof(int));
|
||||
}
|
||||
|
||||
/* Grow PC label array. Can be called after dasm_setup(), too. */
|
||||
void dasm_growpc(Dst_DECL, unsigned int maxpc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
size_t osz = D->pcsize;
|
||||
DASM_M_GROW(Dst, int, D->pclabels, D->pcsize, maxpc*sizeof(int));
|
||||
memset((void *)(((unsigned char *)D->pclabels)+osz), 0, D->pcsize-osz);
|
||||
}
|
||||
|
||||
/* Setup encoder. */
|
||||
void dasm_setup(Dst_DECL, const void *actionlist)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int i;
|
||||
D->actionlist = (dasm_ActList)actionlist;
|
||||
D->status = DASM_S_OK;
|
||||
D->section = &D->sections[0];
|
||||
memset((void *)D->lglabels, 0, D->lgsize);
|
||||
if (D->pclabels) memset((void *)D->pclabels, 0, D->pcsize);
|
||||
for (i = 0; i < D->maxsection; i++) {
|
||||
D->sections[i].pos = DASM_SEC2POS(i);
|
||||
D->sections[i].ofs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) { \
|
||||
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
|
||||
#define CKPL(kind, st) \
|
||||
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
|
||||
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#define CKPL(kind, st) ((void)0)
|
||||
#endif
|
||||
|
||||
static int dasm_imm12(unsigned int n)
|
||||
{
|
||||
if ((n >> 12) == 0)
|
||||
return n;
|
||||
else if ((n & 0xff000fff) == 0)
|
||||
return (n >> 12) | 0x1000;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int dasm_ffs(unsigned long long x)
|
||||
{
|
||||
int n = -1;
|
||||
while (x) { x >>= 1; n++; }
|
||||
return n;
|
||||
}
|
||||
|
||||
static int dasm_imm13(int lo, int hi)
|
||||
{
|
||||
int inv = 0, w = 64, s = 0xfff, xa, xb;
|
||||
unsigned long long n = (((unsigned long long)hi) << 32) | (unsigned int)lo;
|
||||
unsigned long long m = 1ULL, a, b, c;
|
||||
if (n & 1) { n = ~n; inv = 1; }
|
||||
a = n & -n; b = (n+a)&-(n+a); c = (n+a-b)&-(n+a-b);
|
||||
xa = dasm_ffs(a); xb = dasm_ffs(b);
|
||||
if (c) {
|
||||
w = dasm_ffs(c) - xa;
|
||||
if (w == 32) m = 0x0000000100000001UL;
|
||||
else if (w == 16) m = 0x0001000100010001UL;
|
||||
else if (w == 8) m = 0x0101010101010101UL;
|
||||
else if (w == 4) m = 0x1111111111111111UL;
|
||||
else if (w == 2) m = 0x5555555555555555UL;
|
||||
else return -1;
|
||||
s = (-2*w & 0x3f) - 1;
|
||||
} else if (!a) {
|
||||
return -1;
|
||||
} else if (xb == -1) {
|
||||
xb = 64;
|
||||
}
|
||||
if ((b-a) * m != n) return -1;
|
||||
if (inv) {
|
||||
return ((w - xb) << 6) | (s+w+xa-xb);
|
||||
} else {
|
||||
return ((w - xa) << 6) | (s+xb-xa);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pass 1: Store actions and args, link branches/labels, estimate offsets. */
|
||||
void dasm_put(Dst_DECL, int start, ...)
|
||||
{
|
||||
va_list ap;
|
||||
dasm_State *D = Dst_REF;
|
||||
dasm_ActList p = D->actionlist + start;
|
||||
dasm_Section *sec = D->section;
|
||||
int pos = sec->pos, ofs = sec->ofs;
|
||||
int *b;
|
||||
|
||||
if (pos >= sec->epos) {
|
||||
DASM_M_GROW(Dst, int, sec->buf, sec->bsize,
|
||||
sec->bsize + 2*DASM_MAXSECPOS*sizeof(int));
|
||||
sec->rbuf = sec->buf - DASM_POS2BIAS(pos);
|
||||
sec->epos = (int)sec->bsize/sizeof(int) - DASM_MAXSECPOS+DASM_POS2BIAS(pos);
|
||||
}
|
||||
|
||||
b = sec->rbuf;
|
||||
b[pos++] = start;
|
||||
|
||||
va_start(ap, start);
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
if (action >= DASM__MAX) {
|
||||
ofs += 4;
|
||||
} else {
|
||||
int *pl, n = action >= DASM_REL_PC ? va_arg(ap, int) : 0;
|
||||
switch (action) {
|
||||
case DASM_STOP: goto stop;
|
||||
case DASM_SECTION:
|
||||
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
|
||||
D->section = &D->sections[n]; goto stop;
|
||||
case DASM_ESC: p++; ofs += 4; break;
|
||||
case DASM_REL_EXT: break;
|
||||
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
|
||||
case DASM_REL_LG:
|
||||
n = (ins & 2047) - 10; pl = D->lglabels + n;
|
||||
/* Bkwd rel or global. */
|
||||
if (n >= 0) { CK(n>=10||*pl<0, RANGE_LG); CKPL(lg, LG); goto putrel; }
|
||||
pl += 10; n = *pl;
|
||||
if (n < 0) n = 0; /* Start new chain for fwd rel if label exists. */
|
||||
goto linkrel;
|
||||
case DASM_REL_PC:
|
||||
pl = D->pclabels + n; CKPL(pc, PC);
|
||||
putrel:
|
||||
n = *pl;
|
||||
if (n < 0) { /* Label exists. Get label pos and store it. */
|
||||
b[pos] = -n;
|
||||
} else {
|
||||
linkrel:
|
||||
b[pos] = n; /* Else link to rel chain, anchored at label. */
|
||||
*pl = pos;
|
||||
}
|
||||
pos++;
|
||||
break;
|
||||
case DASM_LABEL_LG:
|
||||
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
|
||||
case DASM_LABEL_PC:
|
||||
pl = D->pclabels + n; CKPL(pc, PC);
|
||||
putlabel:
|
||||
n = *pl; /* n > 0: Collapse rel chain and replace with label pos. */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = pos;
|
||||
}
|
||||
*pl = -pos; /* Label exists now. */
|
||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||
break;
|
||||
case DASM_IMM:
|
||||
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
|
||||
n >>= ((ins>>10)&31);
|
||||
#ifdef DASM_CHECKS
|
||||
if ((ins & 0x8000))
|
||||
CK(((n + (1<<(((ins>>5)&31)-1)))>>((ins>>5)&31)) == 0, RANGE_I);
|
||||
else
|
||||
CK((n>>((ins>>5)&31)) == 0, RANGE_I);
|
||||
#endif
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMM6:
|
||||
CK((n >> 6) == 0, RANGE_I);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMM12:
|
||||
CK(dasm_imm12((unsigned int)n) != -1, RANGE_I);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMM13W:
|
||||
CK(dasm_imm13(n, n) != -1, RANGE_I);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMM13X: {
|
||||
int m = va_arg(ap, int);
|
||||
CK(dasm_imm13(n, m) != -1, RANGE_I);
|
||||
b[pos++] = n;
|
||||
b[pos++] = m;
|
||||
break;
|
||||
}
|
||||
case DASM_IMML: {
|
||||
#ifdef DASM_CHECKS
|
||||
int scale = (p[-2] >> 30);
|
||||
CK((!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ||
|
||||
(unsigned int)(n+256) < 512, RANGE_I);
|
||||
#endif
|
||||
b[pos++] = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stop:
|
||||
va_end(ap);
|
||||
sec->pos = pos;
|
||||
sec->ofs = ofs;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Pass 2: Link sections, shrink aligns, fix label offsets. */
|
||||
int dasm_link(Dst_DECL, size_t *szp)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
int secnum;
|
||||
int ofs = 0;
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
*szp = 0;
|
||||
if (D->status != DASM_S_OK) return D->status;
|
||||
{
|
||||
int pc;
|
||||
for (pc = 0; pc*sizeof(int) < D->pcsize; pc++)
|
||||
if (D->pclabels[pc] > 0) return DASM_S_UNDEF_PC|pc;
|
||||
}
|
||||
#endif
|
||||
|
||||
{ /* Handle globals not defined in this translation unit. */
|
||||
int idx;
|
||||
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) {
|
||||
int n = D->lglabels[idx];
|
||||
/* Undefined label: Collapse rel chain and replace with marker (< 0). */
|
||||
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->rbuf;
|
||||
int pos = DASM_SEC2POS(secnum);
|
||||
int lastpos = sec->pos;
|
||||
|
||||
while (pos != lastpos) {
|
||||
dasm_ActList p = D->actionlist + b[pos++];
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
switch (action) {
|
||||
case DASM_STOP: case DASM_SECTION: goto stop;
|
||||
case DASM_ESC: p++; break;
|
||||
case DASM_REL_EXT: break;
|
||||
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); 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_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
|
||||
case DASM_IMML: pos++; break;
|
||||
case DASM_IMM13X: pos += 2; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
ofs += sec->ofs; /* Next section starts right after current section. */
|
||||
}
|
||||
|
||||
D->codesize = ofs; /* Total size of all code sections */
|
||||
*szp = ofs;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
#define CK(x, st) \
|
||||
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
|
||||
#else
|
||||
#define CK(x, st) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Pass 3: Encode sections. */
|
||||
int dasm_encode(Dst_DECL, void *buffer)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
char *base = (char *)buffer;
|
||||
unsigned int *cp = (unsigned int *)buffer;
|
||||
int secnum;
|
||||
|
||||
/* Encode all code sections. No support for data sections (yet). */
|
||||
for (secnum = 0; secnum < D->maxsection; secnum++) {
|
||||
dasm_Section *sec = D->sections + secnum;
|
||||
int *b = sec->buf;
|
||||
int *endb = sec->rbuf + sec->pos;
|
||||
|
||||
while (b != endb) {
|
||||
dasm_ActList p = D->actionlist + *b++;
|
||||
while (1) {
|
||||
unsigned int ins = *p++;
|
||||
unsigned int action = (ins >> 16);
|
||||
int n = (action >= DASM_ALIGN && action < DASM__MAX) ? *b++ : 0;
|
||||
switch (action) {
|
||||
case DASM_STOP: case DASM_SECTION: goto stop;
|
||||
case DASM_ESC: *cp++ = *p++; break;
|
||||
case DASM_REL_EXT:
|
||||
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
|
||||
goto patchrel;
|
||||
case DASM_ALIGN:
|
||||
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
|
||||
break;
|
||||
case DASM_REL_LG:
|
||||
CK(n >= 0, UNDEF_LG);
|
||||
case DASM_REL_PC:
|
||||
CK(n >= 0, UNDEF_PC);
|
||||
n = *DASM_POS2PTR(D, n) - (int)((char *)cp - base) + 4;
|
||||
patchrel:
|
||||
if (!(ins & 0xf800)) { /* B, BL */
|
||||
CK((n & 3) == 0 && ((n+0x08000000) >> 28) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n >> 2) & 0x03ffffff);
|
||||
} else if ((ins & 0x800)) { /* B.cond, CBZ, CBNZ, LDR* literal */
|
||||
CK((n & 3) == 0 && ((n+0x00100000) >> 21) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n << 3) & 0x00ffffe0);
|
||||
} else if ((ins & 0x3000) == 0x2000) { /* ADR */
|
||||
CK(((n+0x00100000) >> 21) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n << 3) & 0x00ffffe0) | ((n & 3) << 29);
|
||||
} else if ((ins & 0x3000) == 0x3000) { /* ADRP */
|
||||
cp[-1] |= ((n >> 9) & 0x00ffffe0) | (((n >> 12) & 3) << 29);
|
||||
} else if ((ins & 0x1000)) { /* TBZ, TBNZ */
|
||||
CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL);
|
||||
cp[-1] |= ((n << 3) & 0x0007ffe0);
|
||||
}
|
||||
break;
|
||||
case DASM_LABEL_LG:
|
||||
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
|
||||
break;
|
||||
case DASM_LABEL_PC: break;
|
||||
case DASM_IMM:
|
||||
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
|
||||
break;
|
||||
case DASM_IMM6:
|
||||
cp[-1] |= ((n&31) << 19) | ((n&32) << 26);
|
||||
break;
|
||||
case DASM_IMM12:
|
||||
cp[-1] |= (dasm_imm12((unsigned int)n) << 10);
|
||||
break;
|
||||
case DASM_IMM13W:
|
||||
cp[-1] |= (dasm_imm13(n, n) << 10);
|
||||
break;
|
||||
case DASM_IMM13X:
|
||||
cp[-1] |= (dasm_imm13(n, *b++) << 10);
|
||||
break;
|
||||
case DASM_IMML: {
|
||||
int scale = (p[-2] >> 30);
|
||||
cp[-1] |= (!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ?
|
||||
((n << (10-scale)) | 0x01000000) : ((n & 511) << 12);
|
||||
break;
|
||||
}
|
||||
default: *cp++ = ins; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
}
|
||||
}
|
||||
|
||||
if (base + D->codesize != (char *)cp) /* Check for phase errors. */
|
||||
return DASM_S_PHASE;
|
||||
return DASM_S_OK;
|
||||
}
|
||||
#undef CK
|
||||
|
||||
/* Get PC label offset. */
|
||||
int dasm_getpclabel(Dst_DECL, unsigned int pc)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (pc*sizeof(int) < D->pcsize) {
|
||||
int pos = D->pclabels[pc];
|
||||
if (pos < 0) return *DASM_POS2PTR(D, -pos);
|
||||
if (pos > 0) return -1; /* Undefined. */
|
||||
}
|
||||
return -2; /* Unused or out of range. */
|
||||
}
|
||||
|
||||
#ifdef DASM_CHECKS
|
||||
/* Optional sanity checker to call between isolated encoding steps. */
|
||||
int dasm_checkstep(Dst_DECL, int secmatch)
|
||||
{
|
||||
dasm_State *D = Dst_REF;
|
||||
if (D->status == DASM_S_OK) {
|
||||
int i;
|
||||
for (i = 1; i <= 9; i++) {
|
||||
if (D->lglabels[i] > 0) { D->status = DASM_S_UNDEF_LG|i; break; }
|
||||
D->lglabels[i] = 0;
|
||||
}
|
||||
}
|
||||
if (D->status == DASM_S_OK && secmatch >= 0 &&
|
||||
D->section != &D->sections[secmatch])
|
||||
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
|
||||
return D->status;
|
||||
}
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** DynASM MIPS encoding engine.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
|
@ -21,7 +21,7 @@ enum {
|
|||
/* The following actions need a buffer position. */
|
||||
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
|
||||
/* The following actions also have an argument. */
|
||||
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM,
|
||||
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMS,
|
||||
DASM__MAX
|
||||
};
|
||||
|
||||
|
@ -231,7 +231,7 @@ void dasm_put(Dst_DECL, int start, ...)
|
|||
*pl = -pos; /* Label exists now. */
|
||||
b[pos++] = ofs; /* Store pass1 offset estimate. */
|
||||
break;
|
||||
case DASM_IMM:
|
||||
case DASM_IMM: case DASM_IMMS:
|
||||
#ifdef DASM_CHECKS
|
||||
CK((n & ((1<<((ins>>10)&31))-1)) == 0, RANGE_I);
|
||||
#endif
|
||||
|
@ -299,7 +299,7 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); 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_IMM: pos++; break;
|
||||
case DASM_IMM: case DASM_IMMS: pos++; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
|
@ -356,7 +356,7 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||
if (ins & 2048)
|
||||
n = n - (int)((char *)cp - base);
|
||||
else
|
||||
n = (n + (int)base) & 0x0fffffff;
|
||||
n = (n + (int)(size_t)base) & 0x0fffffff;
|
||||
patchrel:
|
||||
CK((n & 3) == 0 &&
|
||||
((n + ((ins & 2048) ? 0x00020000 : 0)) >>
|
||||
|
@ -367,6 +367,9 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
|
||||
break;
|
||||
case DASM_LABEL_PC: break;
|
||||
case DASM_IMMS:
|
||||
cp[-1] |= ((n>>3) & 4); n &= 0x1f;
|
||||
/* fallthrough */
|
||||
case DASM_IMM:
|
||||
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
|
||||
break;
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
------------------------------------------------------------------------------
|
||||
-- DynASM MIPS module.
|
||||
-- DynASM MIPS32/MIPS64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local mips64 = mips64
|
||||
|
||||
-- Module information:
|
||||
local _info = {
|
||||
arch = "mips",
|
||||
description = "DynASM MIPS module",
|
||||
version = "1.3.0",
|
||||
vernum = 10300,
|
||||
release = "2012-01-23",
|
||||
arch = mips64 and "mips64" or "mips",
|
||||
description = "DynASM MIPS32/MIPS64 module",
|
||||
version = "1.4.0",
|
||||
vernum = 10400,
|
||||
release = "2016-05-24",
|
||||
author = "Mike Pall",
|
||||
license = "MIT",
|
||||
}
|
||||
|
@ -27,7 +29,8 @@ local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
|
|||
local match, gmatch = _s.match, _s.gmatch
|
||||
local concat, sort = table.concat, table.sort
|
||||
local bit = bit or require("bit")
|
||||
local band, shl, sar, tohex = bit.band, bit.lshift, bit.arshift, bit.tohex
|
||||
local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
|
||||
local tohex = bit.tohex
|
||||
|
||||
-- Inherited tables and callbacks.
|
||||
local g_opt, g_arch
|
||||
|
@ -38,7 +41,7 @@ local wline, werror, wfatal, wwarn
|
|||
local action_names = {
|
||||
"STOP", "SECTION", "ESC", "REL_EXT",
|
||||
"ALIGN", "REL_LG", "LABEL_LG",
|
||||
"REL_PC", "LABEL_PC", "IMM",
|
||||
"REL_PC", "LABEL_PC", "IMM", "IMMS",
|
||||
}
|
||||
|
||||
-- Maximum number of section buffer positions for dasm_put().
|
||||
|
@ -251,6 +254,10 @@ local map_op = {
|
|||
bnel_3 = "54000000STB",
|
||||
blezl_2 = "58000000SB",
|
||||
bgtzl_2 = "5c000000SB",
|
||||
daddi_3 = mips64 and "60000000TSI",
|
||||
daddiu_3 = mips64 and "64000000TSI",
|
||||
ldl_2 = mips64 and "68000000TO",
|
||||
ldr_2 = mips64 and "6c000000TO",
|
||||
lb_2 = "80000000TO",
|
||||
lh_2 = "84000000TO",
|
||||
lwl_2 = "88000000TO",
|
||||
|
@ -258,23 +265,30 @@ local map_op = {
|
|||
lbu_2 = "90000000TO",
|
||||
lhu_2 = "94000000TO",
|
||||
lwr_2 = "98000000TO",
|
||||
lwu_2 = mips64 and "9c000000TO",
|
||||
sb_2 = "a0000000TO",
|
||||
sh_2 = "a4000000TO",
|
||||
swl_2 = "a8000000TO",
|
||||
sw_2 = "ac000000TO",
|
||||
sdl_2 = mips64 and "b0000000TO",
|
||||
sdr_2 = mips64 and "b1000000TO",
|
||||
swr_2 = "b8000000TO",
|
||||
cache_2 = "bc000000NO",
|
||||
ll_2 = "c0000000TO",
|
||||
lwc1_2 = "c4000000HO",
|
||||
pref_2 = "cc000000NO",
|
||||
ldc1_2 = "d4000000HO",
|
||||
ld_2 = mips64 and "dc000000TO",
|
||||
sc_2 = "e0000000TO",
|
||||
swc1_2 = "e4000000HO",
|
||||
scd_2 = mips64 and "f0000000TO",
|
||||
sdc1_2 = "f4000000HO",
|
||||
sd_2 = mips64 and "fc000000TO",
|
||||
|
||||
-- Opcode SPECIAL.
|
||||
nop_0 = "00000000",
|
||||
sll_3 = "00000000DTA",
|
||||
sextw_2 = "00000000DT",
|
||||
movf_2 = "00000001DS",
|
||||
movf_3 = "00000001DSC",
|
||||
movt_2 = "00010001DS",
|
||||
|
@ -285,6 +299,7 @@ local map_op = {
|
|||
sllv_3 = "00000004DTS",
|
||||
srlv_3 = "00000006DTS",
|
||||
rotrv_3 = "00000046DTS",
|
||||
drotrv_3 = mips64 and "00000056DTS",
|
||||
srav_3 = "00000007DTS",
|
||||
jr_1 = "00000008S",
|
||||
jalr_1 = "0000f809S",
|
||||
|
@ -300,15 +315,22 @@ local map_op = {
|
|||
mthi_1 = "00000011S",
|
||||
mflo_1 = "00000012D",
|
||||
mtlo_1 = "00000013S",
|
||||
dsllv_3 = mips64 and "00000014DTS",
|
||||
dsrlv_3 = mips64 and "00000016DTS",
|
||||
dsrav_3 = mips64 and "00000017DTS",
|
||||
mult_2 = "00000018ST",
|
||||
multu_2 = "00000019ST",
|
||||
div_2 = "0000001aST",
|
||||
divu_2 = "0000001bST",
|
||||
dmult_2 = mips64 and "0000001cST",
|
||||
dmultu_2 = mips64 and "0000001dST",
|
||||
ddiv_2 = mips64 and "0000001eST",
|
||||
ddivu_2 = mips64 and "0000001fST",
|
||||
add_3 = "00000020DST",
|
||||
move_2 = "00000021DS",
|
||||
move_2 = mips64 and "00000025DS" or "00000021DS",
|
||||
addu_3 = "00000021DST",
|
||||
sub_3 = "00000022DST",
|
||||
negu_2 = "00000023DT",
|
||||
negu_2 = mips64 and "0000002fDT" or "00000023DT",
|
||||
subu_3 = "00000023DST",
|
||||
and_3 = "00000024DST",
|
||||
or_3 = "00000025DST",
|
||||
|
@ -317,6 +339,10 @@ local map_op = {
|
|||
nor_3 = "00000027DST",
|
||||
slt_3 = "0000002aDST",
|
||||
sltu_3 = "0000002bDST",
|
||||
dadd_3 = mips64 and "0000002cDST",
|
||||
daddu_3 = mips64 and "0000002dDST",
|
||||
dsub_3 = mips64 and "0000002eDST",
|
||||
dsubu_3 = mips64 and "0000002fDST",
|
||||
tge_2 = "00000030ST",
|
||||
tge_3 = "00000030STZ",
|
||||
tgeu_2 = "00000031ST",
|
||||
|
@ -329,6 +355,14 @@ local map_op = {
|
|||
teq_3 = "00000034STZ",
|
||||
tne_2 = "00000036ST",
|
||||
tne_3 = "00000036STZ",
|
||||
dsll_3 = mips64 and "00000038DTa",
|
||||
dsrl_3 = mips64 and "0000003aDTa",
|
||||
drotr_3 = mips64 and "0020003aDTa",
|
||||
dsra_3 = mips64 and "0000003bDTa",
|
||||
dsll32_3 = mips64 and "0000003cDTA",
|
||||
dsrl32_3 = mips64 and "0000003eDTA",
|
||||
drotr32_3 = mips64 and "0020003eDTA",
|
||||
dsra32_3 = mips64 and "0000003fDTA",
|
||||
|
||||
-- Opcode REGIMM.
|
||||
bltz_2 = "04000000SB",
|
||||
|
@ -356,13 +390,24 @@ local map_op = {
|
|||
msubu_2 = "70000005ST",
|
||||
clz_2 = "70000020DS=",
|
||||
clo_2 = "70000021DS=",
|
||||
dclz_2 = mips64 and "70000024DS=",
|
||||
dclo_2 = mips64 and "70000025DS=",
|
||||
sdbbp_0 = "7000003f",
|
||||
sdbbp_1 = "7000003fY",
|
||||
|
||||
-- Opcode SPECIAL3.
|
||||
ext_4 = "7c000000TSAM", -- Note: last arg is msbd = size-1
|
||||
dextm_4 = mips64 and "7c000001TSAM", -- Args: pos | size-1-32
|
||||
dextu_4 = mips64 and "7c000002TSAM", -- Args: pos-32 | size-1
|
||||
dext_4 = mips64 and "7c000003TSAM", -- Args: pos | size-1
|
||||
zextw_2 = mips64 and "7c00f803TS",
|
||||
ins_4 = "7c000004TSAM", -- Note: last arg is msb = pos+size-1
|
||||
dinsm_4 = mips64 and "7c000005TSAM", -- Args: pos | pos+size-33
|
||||
dinsu_4 = mips64 and "7c000006TSAM", -- Args: pos-32 | pos+size-33
|
||||
dins_4 = mips64 and "7c000007TSAM", -- Args: pos | pos+size-1
|
||||
wsbh_2 = "7c0000a0DT",
|
||||
dsbh_2 = mips64 and "7c0000a4DT",
|
||||
dshd_2 = mips64 and "7c000164DT",
|
||||
seb_2 = "7c000420DT",
|
||||
seh_2 = "7c000620DT",
|
||||
rdhwr_2 = "7c00003bTD",
|
||||
|
@ -370,8 +415,12 @@ local map_op = {
|
|||
-- Opcode COP0.
|
||||
mfc0_2 = "40000000TD",
|
||||
mfc0_3 = "40000000TDW",
|
||||
dmfc0_2 = mips64 and "40200000TD",
|
||||
dmfc0_3 = mips64 and "40200000TDW",
|
||||
mtc0_2 = "40800000TD",
|
||||
mtc0_3 = "40800000TDW",
|
||||
dmtc0_2 = mips64 and "40a00000TD",
|
||||
dmtc0_3 = mips64 and "40a00000TDW",
|
||||
rdpgpr_2 = "41400000DT",
|
||||
di_0 = "41606000",
|
||||
di_1 = "41606000T",
|
||||
|
@ -388,9 +437,11 @@ local map_op = {
|
|||
|
||||
-- Opcode COP1.
|
||||
mfc1_2 = "44000000TG",
|
||||
dmfc1_2 = mips64 and "44200000TG",
|
||||
cfc1_2 = "44400000TG",
|
||||
mfhc1_2 = "44600000TG",
|
||||
mtc1_2 = "44800000TG",
|
||||
dmtc1_2 = mips64 and "44a00000TG",
|
||||
ctc1_2 = "44c00000TG",
|
||||
mthc1_2 = "44e00000TG",
|
||||
|
||||
|
@ -633,7 +684,7 @@ local function parse_fpr(expr)
|
|||
werror("bad register name `"..expr.."'")
|
||||
end
|
||||
|
||||
local function parse_imm(imm, bits, shift, scale, signed)
|
||||
local function parse_imm(imm, bits, shift, scale, signed, action)
|
||||
local n = tonumber(imm)
|
||||
if n then
|
||||
local m = sar(n, scale)
|
||||
|
@ -651,7 +702,8 @@ local function parse_imm(imm, bits, shift, scale, signed)
|
|||
match(imm, "^([%w_]+):([rf][1-3]?[0-9])$") then
|
||||
werror("expected immediate operand, got register")
|
||||
else
|
||||
waction("IMM", (signed and 32768 or 0)+scale*1024+bits*32+shift, imm)
|
||||
waction(action or "IMM",
|
||||
(signed and 32768 or 0)+shl(scale, 10)+shl(bits, 5)+shift, imm)
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
@ -763,6 +815,9 @@ map_op[".template__"] = function(params, template, nparams)
|
|||
n = n + 1
|
||||
elseif p == "A" then
|
||||
op = op + parse_imm(params[n], 5, 6, 0, false); n = n + 1
|
||||
elseif p == "a" then
|
||||
local m = parse_imm(params[n], 6, 6, 0, false, "IMMS"); n = n + 1
|
||||
op = op + band(m, 0x7c0) + band(shr(m, 9), 4)
|
||||
elseif p == "M" then
|
||||
op = op + parse_imm(params[n], 5, 11, 0, false); n = n + 1
|
||||
elseif p == "N" then
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
------------------------------------------------------------------------------
|
||||
-- DynASM MIPS64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
|
||||
-- All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
mips64 = true -- Using a global is an ugly, but effective solution.
|
||||
return require("dasm_mips")
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** DynASM PPC encoding engine.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** DynASM PPC/PPC64 encoding engine.
|
||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
|
@ -21,7 +21,7 @@ enum {
|
|||
/* The following actions need a buffer position. */
|
||||
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
|
||||
/* The following actions also have an argument. */
|
||||
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM,
|
||||
DASM_REL_PC, DASM_LABEL_PC, DASM_IMM, DASM_IMMSH,
|
||||
DASM__MAX
|
||||
};
|
||||
|
||||
|
@ -244,6 +244,10 @@ void dasm_put(Dst_DECL, int start, ...)
|
|||
#endif
|
||||
b[pos++] = n;
|
||||
break;
|
||||
case DASM_IMMSH:
|
||||
CK((n >> 6) == 0, RANGE_I);
|
||||
b[pos++] = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +303,7 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||
case DASM_ALIGN: ofs -= (b[pos++] + ofs) & (ins & 255); 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_IMM: pos++; break;
|
||||
case DASM_IMM: case DASM_IMMSH: pos++; break;
|
||||
}
|
||||
}
|
||||
stop: (void)0;
|
||||
|
@ -366,6 +370,9 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||
case DASM_IMM:
|
||||
cp[-1] |= (n & ((1<<((ins>>5)&31))-1)) << (ins&31);
|
||||
break;
|
||||
case DASM_IMMSH:
|
||||
cp[-1] |= (ins & 1) ? ((n&31)<<11)|((n&32)>>4) : ((n&31)<<6)|(n&32);
|
||||
break;
|
||||
default: *cp++ = ins; break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
------------------------------------------------------------------------------
|
||||
-- DynASM PPC module.
|
||||
-- DynASM PPC/PPC64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
--
|
||||
-- Support for various extensions contributed by Caio Souza Oliveira.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- Module information:
|
||||
local _info = {
|
||||
arch = "ppc",
|
||||
description = "DynASM PPC module",
|
||||
version = "1.3.0",
|
||||
vernum = 10300,
|
||||
release = "2011-05-05",
|
||||
version = "1.4.0",
|
||||
vernum = 10400,
|
||||
release = "2015-10-18",
|
||||
author = "Mike Pall",
|
||||
license = "MIT",
|
||||
}
|
||||
|
@ -39,7 +41,7 @@ local wline, werror, wfatal, wwarn
|
|||
local action_names = {
|
||||
"STOP", "SECTION", "ESC", "REL_EXT",
|
||||
"ALIGN", "REL_LG", "LABEL_LG",
|
||||
"REL_PC", "LABEL_PC", "IMM",
|
||||
"REL_PC", "LABEL_PC", "IMM", "IMMSH"
|
||||
}
|
||||
|
||||
-- Maximum number of section buffer positions for dasm_put().
|
||||
|
@ -228,8 +230,18 @@ local map_cond = {
|
|||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local map_op, op_template
|
||||
|
||||
local function op_alias(opname, f)
|
||||
return function(params, nparams)
|
||||
if not params then return "-> "..opname:sub(1, -3) end
|
||||
f(params, nparams)
|
||||
op_template(params, map_op[opname], nparams)
|
||||
end
|
||||
end
|
||||
|
||||
-- Template strings for PPC instructions.
|
||||
local map_op = {
|
||||
map_op = {
|
||||
tdi_3 = "08000000ARI",
|
||||
twi_3 = "0c000000ARI",
|
||||
mulli_3 = "1c000000RRI",
|
||||
|
@ -297,6 +309,250 @@ local map_op = {
|
|||
std_2 = "f8000000RD",
|
||||
stdu_2 = "f8000001RD",
|
||||
|
||||
subi_3 = op_alias("addi_3", function(p) p[3] = "-("..p[3]..")" end),
|
||||
subis_3 = op_alias("addis_3", function(p) p[3] = "-("..p[3]..")" end),
|
||||
subic_3 = op_alias("addic_3", function(p) p[3] = "-("..p[3]..")" end),
|
||||
["subic._3"] = op_alias("addic._3", function(p) p[3] = "-("..p[3]..")" end),
|
||||
|
||||
rotlwi_3 = op_alias("rlwinm_5", function(p)
|
||||
p[4] = "0"; p[5] = "31"
|
||||
end),
|
||||
rotrwi_3 = op_alias("rlwinm_5", function(p)
|
||||
p[3] = "32-("..p[3]..")"; p[4] = "0"; p[5] = "31"
|
||||
end),
|
||||
rotlw_3 = op_alias("rlwnm_5", function(p)
|
||||
p[4] = "0"; p[5] = "31"
|
||||
end),
|
||||
slwi_3 = op_alias("rlwinm_5", function(p)
|
||||
p[5] = "31-("..p[3]..")"; p[4] = "0"
|
||||
end),
|
||||
srwi_3 = op_alias("rlwinm_5", function(p)
|
||||
p[4] = p[3]; p[3] = "32-("..p[3]..")"; p[5] = "31"
|
||||
end),
|
||||
clrlwi_3 = op_alias("rlwinm_5", function(p)
|
||||
p[4] = p[3]; p[3] = "0"; p[5] = "31"
|
||||
end),
|
||||
clrrwi_3 = op_alias("rlwinm_5", function(p)
|
||||
p[5] = "31-("..p[3]..")"; p[3] = "0"; p[4] = "0"
|
||||
end),
|
||||
|
||||
-- Primary opcode 4:
|
||||
mulhhwu_3 = "10000010RRR.",
|
||||
machhwu_3 = "10000018RRR.",
|
||||
mulhhw_3 = "10000050RRR.",
|
||||
nmachhw_3 = "1000005cRRR.",
|
||||
machhwsu_3 = "10000098RRR.",
|
||||
machhws_3 = "100000d8RRR.",
|
||||
nmachhws_3 = "100000dcRRR.",
|
||||
mulchwu_3 = "10000110RRR.",
|
||||
macchwu_3 = "10000118RRR.",
|
||||
mulchw_3 = "10000150RRR.",
|
||||
macchw_3 = "10000158RRR.",
|
||||
nmacchw_3 = "1000015cRRR.",
|
||||
macchwsu_3 = "10000198RRR.",
|
||||
macchws_3 = "100001d8RRR.",
|
||||
nmacchws_3 = "100001dcRRR.",
|
||||
mullhw_3 = "10000350RRR.",
|
||||
maclhw_3 = "10000358RRR.",
|
||||
nmaclhw_3 = "1000035cRRR.",
|
||||
maclhwsu_3 = "10000398RRR.",
|
||||
maclhws_3 = "100003d8RRR.",
|
||||
nmaclhws_3 = "100003dcRRR.",
|
||||
machhwuo_3 = "10000418RRR.",
|
||||
nmachhwo_3 = "1000045cRRR.",
|
||||
machhwsuo_3 = "10000498RRR.",
|
||||
machhwso_3 = "100004d8RRR.",
|
||||
nmachhwso_3 = "100004dcRRR.",
|
||||
macchwuo_3 = "10000518RRR.",
|
||||
macchwo_3 = "10000558RRR.",
|
||||
nmacchwo_3 = "1000055cRRR.",
|
||||
macchwsuo_3 = "10000598RRR.",
|
||||
macchwso_3 = "100005d8RRR.",
|
||||
nmacchwso_3 = "100005dcRRR.",
|
||||
maclhwo_3 = "10000758RRR.",
|
||||
nmaclhwo_3 = "1000075cRRR.",
|
||||
maclhwsuo_3 = "10000798RRR.",
|
||||
maclhwso_3 = "100007d8RRR.",
|
||||
nmaclhwso_3 = "100007dcRRR.",
|
||||
|
||||
vaddubm_3 = "10000000VVV",
|
||||
vmaxub_3 = "10000002VVV",
|
||||
vrlb_3 = "10000004VVV",
|
||||
vcmpequb_3 = "10000006VVV",
|
||||
vmuloub_3 = "10000008VVV",
|
||||
vaddfp_3 = "1000000aVVV",
|
||||
vmrghb_3 = "1000000cVVV",
|
||||
vpkuhum_3 = "1000000eVVV",
|
||||
vmhaddshs_4 = "10000020VVVV",
|
||||
vmhraddshs_4 = "10000021VVVV",
|
||||
vmladduhm_4 = "10000022VVVV",
|
||||
vmsumubm_4 = "10000024VVVV",
|
||||
vmsummbm_4 = "10000025VVVV",
|
||||
vmsumuhm_4 = "10000026VVVV",
|
||||
vmsumuhs_4 = "10000027VVVV",
|
||||
vmsumshm_4 = "10000028VVVV",
|
||||
vmsumshs_4 = "10000029VVVV",
|
||||
vsel_4 = "1000002aVVVV",
|
||||
vperm_4 = "1000002bVVVV",
|
||||
vsldoi_4 = "1000002cVVVP",
|
||||
vpermxor_4 = "1000002dVVVV",
|
||||
vmaddfp_4 = "1000002eVVVV~",
|
||||
vnmsubfp_4 = "1000002fVVVV~",
|
||||
vaddeuqm_4 = "1000003cVVVV",
|
||||
vaddecuq_4 = "1000003dVVVV",
|
||||
vsubeuqm_4 = "1000003eVVVV",
|
||||
vsubecuq_4 = "1000003fVVVV",
|
||||
vadduhm_3 = "10000040VVV",
|
||||
vmaxuh_3 = "10000042VVV",
|
||||
vrlh_3 = "10000044VVV",
|
||||
vcmpequh_3 = "10000046VVV",
|
||||
vmulouh_3 = "10000048VVV",
|
||||
vsubfp_3 = "1000004aVVV",
|
||||
vmrghh_3 = "1000004cVVV",
|
||||
vpkuwum_3 = "1000004eVVV",
|
||||
vadduwm_3 = "10000080VVV",
|
||||
vmaxuw_3 = "10000082VVV",
|
||||
vrlw_3 = "10000084VVV",
|
||||
vcmpequw_3 = "10000086VVV",
|
||||
vmulouw_3 = "10000088VVV",
|
||||
vmuluwm_3 = "10000089VVV",
|
||||
vmrghw_3 = "1000008cVVV",
|
||||
vpkuhus_3 = "1000008eVVV",
|
||||
vaddudm_3 = "100000c0VVV",
|
||||
vmaxud_3 = "100000c2VVV",
|
||||
vrld_3 = "100000c4VVV",
|
||||
vcmpeqfp_3 = "100000c6VVV",
|
||||
vcmpequd_3 = "100000c7VVV",
|
||||
vpkuwus_3 = "100000ceVVV",
|
||||
vadduqm_3 = "10000100VVV",
|
||||
vmaxsb_3 = "10000102VVV",
|
||||
vslb_3 = "10000104VVV",
|
||||
vmulosb_3 = "10000108VVV",
|
||||
vrefp_2 = "1000010aV-V",
|
||||
vmrglb_3 = "1000010cVVV",
|
||||
vpkshus_3 = "1000010eVVV",
|
||||
vaddcuq_3 = "10000140VVV",
|
||||
vmaxsh_3 = "10000142VVV",
|
||||
vslh_3 = "10000144VVV",
|
||||
vmulosh_3 = "10000148VVV",
|
||||
vrsqrtefp_2 = "1000014aV-V",
|
||||
vmrglh_3 = "1000014cVVV",
|
||||
vpkswus_3 = "1000014eVVV",
|
||||
vaddcuw_3 = "10000180VVV",
|
||||
vmaxsw_3 = "10000182VVV",
|
||||
vslw_3 = "10000184VVV",
|
||||
vmulosw_3 = "10000188VVV",
|
||||
vexptefp_2 = "1000018aV-V",
|
||||
vmrglw_3 = "1000018cVVV",
|
||||
vpkshss_3 = "1000018eVVV",
|
||||
vmaxsd_3 = "100001c2VVV",
|
||||
vsl_3 = "100001c4VVV",
|
||||
vcmpgefp_3 = "100001c6VVV",
|
||||
vlogefp_2 = "100001caV-V",
|
||||
vpkswss_3 = "100001ceVVV",
|
||||
vadduhs_3 = "10000240VVV",
|
||||
vminuh_3 = "10000242VVV",
|
||||
vsrh_3 = "10000244VVV",
|
||||
vcmpgtuh_3 = "10000246VVV",
|
||||
vmuleuh_3 = "10000248VVV",
|
||||
vrfiz_2 = "1000024aV-V",
|
||||
vsplth_3 = "1000024cVV3",
|
||||
vupkhsh_2 = "1000024eV-V",
|
||||
vminuw_3 = "10000282VVV",
|
||||
vminud_3 = "100002c2VVV",
|
||||
vcmpgtud_3 = "100002c7VVV",
|
||||
vrfim_2 = "100002caV-V",
|
||||
vcmpgtsb_3 = "10000306VVV",
|
||||
vcfux_3 = "1000030aVVA~",
|
||||
vaddshs_3 = "10000340VVV",
|
||||
vminsh_3 = "10000342VVV",
|
||||
vsrah_3 = "10000344VVV",
|
||||
vcmpgtsh_3 = "10000346VVV",
|
||||
vmulesh_3 = "10000348VVV",
|
||||
vcfsx_3 = "1000034aVVA~",
|
||||
vspltish_2 = "1000034cVS",
|
||||
vupkhpx_2 = "1000034eV-V",
|
||||
vaddsws_3 = "10000380VVV",
|
||||
vminsw_3 = "10000382VVV",
|
||||
vsraw_3 = "10000384VVV",
|
||||
vcmpgtsw_3 = "10000386VVV",
|
||||
vmulesw_3 = "10000388VVV",
|
||||
vctuxs_3 = "1000038aVVA~",
|
||||
vspltisw_2 = "1000038cVS",
|
||||
vminsd_3 = "100003c2VVV",
|
||||
vsrad_3 = "100003c4VVV",
|
||||
vcmpbfp_3 = "100003c6VVV",
|
||||
vcmpgtsd_3 = "100003c7VVV",
|
||||
vctsxs_3 = "100003caVVA~",
|
||||
vupklpx_2 = "100003ceV-V",
|
||||
vsububm_3 = "10000400VVV",
|
||||
["bcdadd._4"] = "10000401VVVy.",
|
||||
vavgub_3 = "10000402VVV",
|
||||
vand_3 = "10000404VVV",
|
||||
["vcmpequb._3"] = "10000406VVV",
|
||||
vmaxfp_3 = "1000040aVVV",
|
||||
vsubuhm_3 = "10000440VVV",
|
||||
["bcdsub._4"] = "10000441VVVy.",
|
||||
vavguh_3 = "10000442VVV",
|
||||
vandc_3 = "10000444VVV",
|
||||
["vcmpequh._3"] = "10000446VVV",
|
||||
vminfp_3 = "1000044aVVV",
|
||||
vpkudum_3 = "1000044eVVV",
|
||||
vsubuwm_3 = "10000480VVV",
|
||||
vavguw_3 = "10000482VVV",
|
||||
vor_3 = "10000484VVV",
|
||||
["vcmpequw._3"] = "10000486VVV",
|
||||
vpmsumw_3 = "10000488VVV",
|
||||
["vcmpeqfp._3"] = "100004c6VVV",
|
||||
["vcmpequd._3"] = "100004c7VVV",
|
||||
vpkudus_3 = "100004ceVVV",
|
||||
vavgsb_3 = "10000502VVV",
|
||||
vavgsh_3 = "10000542VVV",
|
||||
vorc_3 = "10000544VVV",
|
||||
vbpermq_3 = "1000054cVVV",
|
||||
vpksdus_3 = "1000054eVVV",
|
||||
vavgsw_3 = "10000582VVV",
|
||||
vsld_3 = "100005c4VVV",
|
||||
["vcmpgefp._3"] = "100005c6VVV",
|
||||
vpksdss_3 = "100005ceVVV",
|
||||
vsububs_3 = "10000600VVV",
|
||||
mfvscr_1 = "10000604V--",
|
||||
vsum4ubs_3 = "10000608VVV",
|
||||
vsubuhs_3 = "10000640VVV",
|
||||
mtvscr_1 = "10000644--V",
|
||||
["vcmpgtuh._3"] = "10000646VVV",
|
||||
vsum4shs_3 = "10000648VVV",
|
||||
vupkhsw_2 = "1000064eV-V",
|
||||
vsubuws_3 = "10000680VVV",
|
||||
vshasigmaw_4 = "10000682VVYp",
|
||||
veqv_3 = "10000684VVV",
|
||||
vsum2sws_3 = "10000688VVV",
|
||||
vmrgow_3 = "1000068cVVV",
|
||||
vshasigmad_4 = "100006c2VVYp",
|
||||
vsrd_3 = "100006c4VVV",
|
||||
["vcmpgtud._3"] = "100006c7VVV",
|
||||
vupklsw_2 = "100006ceV-V",
|
||||
vupkslw_2 = "100006ceV-V",
|
||||
vsubsbs_3 = "10000700VVV",
|
||||
vclzb_2 = "10000702V-V",
|
||||
vpopcntb_2 = "10000703V-V",
|
||||
["vcmpgtsb._3"] = "10000706VVV",
|
||||
vsum4sbs_3 = "10000708VVV",
|
||||
vsubshs_3 = "10000740VVV",
|
||||
vclzh_2 = "10000742V-V",
|
||||
vpopcnth_2 = "10000743V-V",
|
||||
["vcmpgtsh._3"] = "10000746VVV",
|
||||
vsubsws_3 = "10000780VVV",
|
||||
vclzw_2 = "10000782V-V",
|
||||
vpopcntw_2 = "10000783V-V",
|
||||
["vcmpgtsw._3"] = "10000786VVV",
|
||||
vsumsws_3 = "10000788VVV",
|
||||
vmrgew_3 = "1000078cVVV",
|
||||
vclzd_2 = "100007c2V-V",
|
||||
vpopcntd_2 = "100007c3V-V",
|
||||
["vcmpbfp._3"] = "100007c6VVV",
|
||||
["vcmpgtsd._3"] = "100007c7VVV",
|
||||
|
||||
-- Primary opcode 19:
|
||||
mcrf_2 = "4c000000XX",
|
||||
isync_0 = "4c00012c",
|
||||
|
@ -316,6 +572,8 @@ local map_op = {
|
|||
bclrl_2 = "4c000021AA",
|
||||
bcctr_2 = "4c000420AA",
|
||||
bcctrl_2 = "4c000421AA",
|
||||
bctar_2 = "4c000460AA",
|
||||
bctarl_2 = "4c000461AA",
|
||||
blr_0 = "4e800020",
|
||||
blrl_0 = "4e800021",
|
||||
bctr_0 = "4e800420",
|
||||
|
@ -327,6 +585,7 @@ local map_op = {
|
|||
cmpd_3 = "7c200000XRR",
|
||||
cmpd_2 = "7c200000-RR",
|
||||
tw_3 = "7c000008ARR",
|
||||
lvsl_3 = "7c00000cVRR",
|
||||
subfc_3 = "7c000010RRR.",
|
||||
subc_3 = "7c000010RRR~.",
|
||||
mulhdu_3 = "7c000012RRR.",
|
||||
|
@ -351,50 +610,68 @@ local map_op = {
|
|||
cmplw_2 = "7c000040-RR",
|
||||
cmpld_3 = "7c200040XRR",
|
||||
cmpld_2 = "7c200040-RR",
|
||||
lvsr_3 = "7c00004cVRR",
|
||||
subf_3 = "7c000050RRR.",
|
||||
sub_3 = "7c000050RRR~.",
|
||||
lbarx_3 = "7c000068RR0R",
|
||||
ldux_3 = "7c00006aRR0R",
|
||||
dcbst_2 = "7c00006c-RR",
|
||||
lwzux_3 = "7c00006eRR0R",
|
||||
cntlzd_2 = "7c000074RR~",
|
||||
andc_3 = "7c000078RR~R.",
|
||||
td_3 = "7c000088ARR",
|
||||
lvewx_3 = "7c00008eVRR",
|
||||
mulhd_3 = "7c000092RRR.",
|
||||
addg6s_3 = "7c000094RRR",
|
||||
mulhw_3 = "7c000096RRR.",
|
||||
dlmzb_3 = "7c00009cRR~R.",
|
||||
ldarx_3 = "7c0000a8RR0R",
|
||||
dcbf_2 = "7c0000ac-RR",
|
||||
lbzx_3 = "7c0000aeRR0R",
|
||||
lvx_3 = "7c0000ceVRR",
|
||||
neg_2 = "7c0000d0RR.",
|
||||
lharx_3 = "7c0000e8RR0R",
|
||||
lbzux_3 = "7c0000eeRR0R",
|
||||
popcntb_2 = "7c0000f4RR~",
|
||||
not_2 = "7c0000f8RR~%.",
|
||||
nor_3 = "7c0000f8RR~R.",
|
||||
stvebx_3 = "7c00010eVRR",
|
||||
subfe_3 = "7c000110RRR.",
|
||||
sube_3 = "7c000110RRR~.",
|
||||
adde_3 = "7c000114RRR.",
|
||||
stdx_3 = "7c00012aRR0R",
|
||||
stwcx_3 = "7c00012cRR0R.",
|
||||
["stwcx._3"] = "7c00012dRR0R.",
|
||||
stwx_3 = "7c00012eRR0R",
|
||||
prtyw_2 = "7c000134RR~",
|
||||
stvehx_3 = "7c00014eVRR",
|
||||
stdux_3 = "7c00016aRR0R",
|
||||
["stqcx._3"] = "7c00016dR:R0R.",
|
||||
stwux_3 = "7c00016eRR0R",
|
||||
prtyd_2 = "7c000174RR~",
|
||||
stvewx_3 = "7c00018eVRR",
|
||||
subfze_2 = "7c000190RR.",
|
||||
addze_2 = "7c000194RR.",
|
||||
stdcx_3 = "7c0001acRR0R.",
|
||||
["stdcx._3"] = "7c0001adRR0R.",
|
||||
stbx_3 = "7c0001aeRR0R",
|
||||
stvx_3 = "7c0001ceVRR",
|
||||
subfme_2 = "7c0001d0RR.",
|
||||
mulld_3 = "7c0001d2RRR.",
|
||||
addme_2 = "7c0001d4RR.",
|
||||
mullw_3 = "7c0001d6RRR.",
|
||||
dcbtst_2 = "7c0001ec-RR",
|
||||
stbux_3 = "7c0001eeRR0R",
|
||||
bpermd_3 = "7c0001f8RR~R",
|
||||
lvepxl_3 = "7c00020eVRR",
|
||||
add_3 = "7c000214RRR.",
|
||||
lqarx_3 = "7c000228R:R0R",
|
||||
dcbt_2 = "7c00022c-RR",
|
||||
lhzx_3 = "7c00022eRR0R",
|
||||
cdtbcd_2 = "7c000234RR~",
|
||||
eqv_3 = "7c000238RR~R.",
|
||||
lvepx_3 = "7c00024eVRR",
|
||||
eciwx_3 = "7c00026cRR0R",
|
||||
lhzux_3 = "7c00026eRR0R",
|
||||
cbcdtd_2 = "7c000274RR~",
|
||||
xor_3 = "7c000278RR~R.",
|
||||
mfspefscr_1 = "7c0082a6R",
|
||||
mfxer_1 = "7c0102a6R",
|
||||
|
@ -404,8 +681,12 @@ local map_op = {
|
|||
lhax_3 = "7c0002aeRR0R",
|
||||
mftb_1 = "7c0c42e6R",
|
||||
mftbu_1 = "7c0d42e6R",
|
||||
lvxl_3 = "7c0002ceVRR",
|
||||
lwaux_3 = "7c0002eaRR0R",
|
||||
lhaux_3 = "7c0002eeRR0R",
|
||||
popcntw_2 = "7c0002f4RR~",
|
||||
divdeu_3 = "7c000312RRR.",
|
||||
divweu_3 = "7c000316RRR.",
|
||||
sthx_3 = "7c00032eRR0R",
|
||||
orc_3 = "7c000338RR~R.",
|
||||
ecowx_3 = "7c00036cRR0R",
|
||||
|
@ -420,10 +701,14 @@ local map_op = {
|
|||
mtctr_1 = "7c0903a6R",
|
||||
dcbi_2 = "7c0003ac-RR",
|
||||
nand_3 = "7c0003b8RR~R.",
|
||||
dsn_2 = "7c0003c6-RR",
|
||||
stvxl_3 = "7c0003ceVRR",
|
||||
divd_3 = "7c0003d2RRR.",
|
||||
divw_3 = "7c0003d6RRR.",
|
||||
popcntd_2 = "7c0003f4RR~",
|
||||
cmpb_3 = "7c0003f8RR~R.",
|
||||
mcrxr_1 = "7c000400X",
|
||||
lbdx_3 = "7c000406RRR",
|
||||
subfco_3 = "7c000410RRR.",
|
||||
subco_3 = "7c000410RRR~.",
|
||||
addco_3 = "7c000414RRR.",
|
||||
|
@ -433,16 +718,20 @@ local map_op = {
|
|||
lfsx_3 = "7c00042eFR0R",
|
||||
srw_3 = "7c000430RR~R.",
|
||||
srd_3 = "7c000436RR~R.",
|
||||
lhdx_3 = "7c000446RRR",
|
||||
subfo_3 = "7c000450RRR.",
|
||||
subo_3 = "7c000450RRR~.",
|
||||
lfsux_3 = "7c00046eFR0R",
|
||||
lwdx_3 = "7c000486RRR",
|
||||
lswi_3 = "7c0004aaRR0A",
|
||||
sync_0 = "7c0004ac",
|
||||
lwsync_0 = "7c2004ac",
|
||||
ptesync_0 = "7c4004ac",
|
||||
lfdx_3 = "7c0004aeFR0R",
|
||||
lddx_3 = "7c0004c6RRR",
|
||||
nego_2 = "7c0004d0RR.",
|
||||
lfdux_3 = "7c0004eeFR0R",
|
||||
stbdx_3 = "7c000506RRR",
|
||||
subfeo_3 = "7c000510RRR.",
|
||||
subeo_3 = "7c000510RRR~.",
|
||||
addeo_3 = "7c000514RRR.",
|
||||
|
@ -450,27 +739,42 @@ local map_op = {
|
|||
stswx_3 = "7c00052aRR0R",
|
||||
stwbrx_3 = "7c00052cRR0R",
|
||||
stfsx_3 = "7c00052eFR0R",
|
||||
sthdx_3 = "7c000546RRR",
|
||||
["stbcx._3"] = "7c00056dRRR",
|
||||
stfsux_3 = "7c00056eFR0R",
|
||||
stwdx_3 = "7c000586RRR",
|
||||
subfzeo_2 = "7c000590RR.",
|
||||
addzeo_2 = "7c000594RR.",
|
||||
stswi_3 = "7c0005aaRR0A",
|
||||
["sthcx._3"] = "7c0005adRRR",
|
||||
stfdx_3 = "7c0005aeFR0R",
|
||||
stddx_3 = "7c0005c6RRR",
|
||||
subfmeo_2 = "7c0005d0RR.",
|
||||
mulldo_3 = "7c0005d2RRR.",
|
||||
addmeo_2 = "7c0005d4RR.",
|
||||
mullwo_3 = "7c0005d6RRR.",
|
||||
dcba_2 = "7c0005ec-RR",
|
||||
stfdux_3 = "7c0005eeFR0R",
|
||||
stvepxl_3 = "7c00060eVRR",
|
||||
addo_3 = "7c000614RRR.",
|
||||
lhbrx_3 = "7c00062cRR0R",
|
||||
lfdpx_3 = "7c00062eF:RR",
|
||||
sraw_3 = "7c000630RR~R.",
|
||||
srad_3 = "7c000634RR~R.",
|
||||
lfddx_3 = "7c000646FRR",
|
||||
stvepx_3 = "7c00064eVRR",
|
||||
srawi_3 = "7c000670RR~A.",
|
||||
sradi_3 = "7c000674RR~H.",
|
||||
eieio_0 = "7c0006ac",
|
||||
lfiwax_3 = "7c0006aeFR0R",
|
||||
divdeuo_3 = "7c000712RRR.",
|
||||
divweuo_3 = "7c000716RRR.",
|
||||
sthbrx_3 = "7c00072cRR0R",
|
||||
stfdpx_3 = "7c00072eF:RR",
|
||||
extsh_2 = "7c000734RR~.",
|
||||
stfddx_3 = "7c000746FRR",
|
||||
divdeo_3 = "7c000752RRR.",
|
||||
divweo_3 = "7c000756RRR.",
|
||||
extsb_2 = "7c000774RR~.",
|
||||
divduo_3 = "7c000792RRR.",
|
||||
divwou_3 = "7c000796RRR.",
|
||||
|
@ -481,6 +785,40 @@ local map_op = {
|
|||
divwo_3 = "7c0007d6RRR.",
|
||||
dcbz_2 = "7c0007ec-RR",
|
||||
|
||||
["tbegin._1"] = "7c00051d1",
|
||||
["tbegin._0"] = "7c00051d",
|
||||
["tend._1"] = "7c00055dY",
|
||||
["tend._0"] = "7c00055d",
|
||||
["tendall._0"] = "7e00055d",
|
||||
tcheck_1 = "7c00059cX",
|
||||
["tsr._1"] = "7c0005dd1",
|
||||
["tsuspend._0"] = "7c0005dd",
|
||||
["tresume._0"] = "7c2005dd",
|
||||
["tabortwc._3"] = "7c00061dARR",
|
||||
["tabortdc._3"] = "7c00065dARR",
|
||||
["tabortwci._3"] = "7c00069dARS",
|
||||
["tabortdci._3"] = "7c0006ddARS",
|
||||
["tabort._1"] = "7c00071d-R-",
|
||||
["treclaim._1"] = "7c00075d-R",
|
||||
["trechkpt._0"] = "7c0007dd",
|
||||
|
||||
lxsiwzx_3 = "7c000018QRR",
|
||||
lxsiwax_3 = "7c000098QRR",
|
||||
mfvsrd_2 = "7c000066-Rq",
|
||||
mfvsrwz_2 = "7c0000e6-Rq",
|
||||
stxsiwx_3 = "7c000118QRR",
|
||||
mtvsrd_2 = "7c000166QR",
|
||||
mtvsrwa_2 = "7c0001a6QR",
|
||||
lxvdsx_3 = "7c000298QRR",
|
||||
lxsspx_3 = "7c000418QRR",
|
||||
lxsdx_3 = "7c000498QRR",
|
||||
stxsspx_3 = "7c000518QRR",
|
||||
stxsdx_3 = "7c000598QRR",
|
||||
lxvw4x_3 = "7c000618QRR",
|
||||
lxvd2x_3 = "7c000698QRR",
|
||||
stxvw4x_3 = "7c000718QRR",
|
||||
stxvd2x_3 = "7c000798QRR",
|
||||
|
||||
-- Primary opcode 30:
|
||||
rldicl_4 = "78000000RR~HM.",
|
||||
rldicr_4 = "78000004RR~HM.",
|
||||
|
@ -489,6 +827,34 @@ local map_op = {
|
|||
rldcl_4 = "78000010RR~RM.",
|
||||
rldcr_4 = "78000012RR~RM.",
|
||||
|
||||
rotldi_3 = op_alias("rldicl_4", function(p)
|
||||
p[4] = "0"
|
||||
end),
|
||||
rotrdi_3 = op_alias("rldicl_4", function(p)
|
||||
p[3] = "64-("..p[3]..")"; p[4] = "0"
|
||||
end),
|
||||
rotld_3 = op_alias("rldcl_4", function(p)
|
||||
p[4] = "0"
|
||||
end),
|
||||
sldi_3 = op_alias("rldicr_4", function(p)
|
||||
p[4] = "63-("..p[3]..")"
|
||||
end),
|
||||
srdi_3 = op_alias("rldicl_4", function(p)
|
||||
p[4] = p[3]; p[3] = "64-("..p[3]..")"
|
||||
end),
|
||||
clrldi_3 = op_alias("rldicl_4", function(p)
|
||||
p[4] = p[3]; p[3] = "0"
|
||||
end),
|
||||
clrrdi_3 = op_alias("rldicr_4", function(p)
|
||||
p[4] = "63-("..p[3]..")"; p[3] = "0"
|
||||
end),
|
||||
|
||||
-- Primary opcode 56:
|
||||
lq_2 = "e0000000R:D", -- NYI: displacement must be divisible by 8.
|
||||
|
||||
-- Primary opcode 57:
|
||||
lfdp_2 = "e4000000F:D", -- NYI: displacement must be divisible by 4.
|
||||
|
||||
-- Primary opcode 59:
|
||||
fdivs_3 = "ec000024FFF.",
|
||||
fsubs_3 = "ec000028FFF.",
|
||||
|
@ -501,6 +867,200 @@ local map_op = {
|
|||
fmadds_4 = "ec00003aFFFF~.",
|
||||
fnmsubs_4 = "ec00003cFFFF~.",
|
||||
fnmadds_4 = "ec00003eFFFF~.",
|
||||
fcfids_2 = "ec00069cF-F.",
|
||||
fcfidus_2 = "ec00079cF-F.",
|
||||
|
||||
dadd_3 = "ec000004FFF.",
|
||||
dqua_4 = "ec000006FFFZ.",
|
||||
dmul_3 = "ec000044FFF.",
|
||||
drrnd_4 = "ec000046FFFZ.",
|
||||
dscli_3 = "ec000084FF6.",
|
||||
dquai_4 = "ec000086SF~FZ.",
|
||||
dscri_3 = "ec0000c4FF6.",
|
||||
drintx_4 = "ec0000c61F~FZ.",
|
||||
dcmpo_3 = "ec000104XFF",
|
||||
dtstex_3 = "ec000144XFF",
|
||||
dtstdc_3 = "ec000184XF6",
|
||||
dtstdg_3 = "ec0001c4XF6",
|
||||
drintn_4 = "ec0001c61F~FZ.",
|
||||
dctdp_2 = "ec000204F-F.",
|
||||
dctfix_2 = "ec000244F-F.",
|
||||
ddedpd_3 = "ec000284ZF~F.",
|
||||
dxex_2 = "ec0002c4F-F.",
|
||||
dsub_3 = "ec000404FFF.",
|
||||
ddiv_3 = "ec000444FFF.",
|
||||
dcmpu_3 = "ec000504XFF",
|
||||
dtstsf_3 = "ec000544XFF",
|
||||
drsp_2 = "ec000604F-F.",
|
||||
dcffix_2 = "ec000644F-F.",
|
||||
denbcd_3 = "ec000684YF~F.",
|
||||
diex_3 = "ec0006c4FFF.",
|
||||
|
||||
-- Primary opcode 60:
|
||||
xsaddsp_3 = "f0000000QQQ",
|
||||
xsmaddasp_3 = "f0000008QQQ",
|
||||
xxsldwi_4 = "f0000010QQQz",
|
||||
xsrsqrtesp_2 = "f0000028Q-Q",
|
||||
xssqrtsp_2 = "f000002cQ-Q",
|
||||
xxsel_4 = "f0000030QQQQ",
|
||||
xssubsp_3 = "f0000040QQQ",
|
||||
xsmaddmsp_3 = "f0000048QQQ",
|
||||
xxpermdi_4 = "f0000050QQQz",
|
||||
xsresp_2 = "f0000068Q-Q",
|
||||
xsmulsp_3 = "f0000080QQQ",
|
||||
xsmsubasp_3 = "f0000088QQQ",
|
||||
xxmrghw_3 = "f0000090QQQ",
|
||||
xsdivsp_3 = "f00000c0QQQ",
|
||||
xsmsubmsp_3 = "f00000c8QQQ",
|
||||
xsadddp_3 = "f0000100QQQ",
|
||||
xsmaddadp_3 = "f0000108QQQ",
|
||||
xscmpudp_3 = "f0000118XQQ",
|
||||
xscvdpuxws_2 = "f0000120Q-Q",
|
||||
xsrdpi_2 = "f0000124Q-Q",
|
||||
xsrsqrtedp_2 = "f0000128Q-Q",
|
||||
xssqrtdp_2 = "f000012cQ-Q",
|
||||
xssubdp_3 = "f0000140QQQ",
|
||||
xsmaddmdp_3 = "f0000148QQQ",
|
||||
xscmpodp_3 = "f0000158XQQ",
|
||||
xscvdpsxws_2 = "f0000160Q-Q",
|
||||
xsrdpiz_2 = "f0000164Q-Q",
|
||||
xsredp_2 = "f0000168Q-Q",
|
||||
xsmuldp_3 = "f0000180QQQ",
|
||||
xsmsubadp_3 = "f0000188QQQ",
|
||||
xxmrglw_3 = "f0000190QQQ",
|
||||
xsrdpip_2 = "f00001a4Q-Q",
|
||||
xstsqrtdp_2 = "f00001a8X-Q",
|
||||
xsrdpic_2 = "f00001acQ-Q",
|
||||
xsdivdp_3 = "f00001c0QQQ",
|
||||
xsmsubmdp_3 = "f00001c8QQQ",
|
||||
xsrdpim_2 = "f00001e4Q-Q",
|
||||
xstdivdp_3 = "f00001e8XQQ",
|
||||
xvaddsp_3 = "f0000200QQQ",
|
||||
xvmaddasp_3 = "f0000208QQQ",
|
||||
xvcmpeqsp_3 = "f0000218QQQ",
|
||||
xvcvspuxws_2 = "f0000220Q-Q",
|
||||
xvrspi_2 = "f0000224Q-Q",
|
||||
xvrsqrtesp_2 = "f0000228Q-Q",
|
||||
xvsqrtsp_2 = "f000022cQ-Q",
|
||||
xvsubsp_3 = "f0000240QQQ",
|
||||
xvmaddmsp_3 = "f0000248QQQ",
|
||||
xvcmpgtsp_3 = "f0000258QQQ",
|
||||
xvcvspsxws_2 = "f0000260Q-Q",
|
||||
xvrspiz_2 = "f0000264Q-Q",
|
||||
xvresp_2 = "f0000268Q-Q",
|
||||
xvmulsp_3 = "f0000280QQQ",
|
||||
xvmsubasp_3 = "f0000288QQQ",
|
||||
xxspltw_3 = "f0000290QQg~",
|
||||
xvcmpgesp_3 = "f0000298QQQ",
|
||||
xvcvuxwsp_2 = "f00002a0Q-Q",
|
||||
xvrspip_2 = "f00002a4Q-Q",
|
||||
xvtsqrtsp_2 = "f00002a8X-Q",
|
||||
xvrspic_2 = "f00002acQ-Q",
|
||||
xvdivsp_3 = "f00002c0QQQ",
|
||||
xvmsubmsp_3 = "f00002c8QQQ",
|
||||
xvcvsxwsp_2 = "f00002e0Q-Q",
|
||||
xvrspim_2 = "f00002e4Q-Q",
|
||||
xvtdivsp_3 = "f00002e8XQQ",
|
||||
xvadddp_3 = "f0000300QQQ",
|
||||
xvmaddadp_3 = "f0000308QQQ",
|
||||
xvcmpeqdp_3 = "f0000318QQQ",
|
||||
xvcvdpuxws_2 = "f0000320Q-Q",
|
||||
xvrdpi_2 = "f0000324Q-Q",
|
||||
xvrsqrtedp_2 = "f0000328Q-Q",
|
||||
xvsqrtdp_2 = "f000032cQ-Q",
|
||||
xvsubdp_3 = "f0000340QQQ",
|
||||
xvmaddmdp_3 = "f0000348QQQ",
|
||||
xvcmpgtdp_3 = "f0000358QQQ",
|
||||
xvcvdpsxws_2 = "f0000360Q-Q",
|
||||
xvrdpiz_2 = "f0000364Q-Q",
|
||||
xvredp_2 = "f0000368Q-Q",
|
||||
xvmuldp_3 = "f0000380QQQ",
|
||||
xvmsubadp_3 = "f0000388QQQ",
|
||||
xvcmpgedp_3 = "f0000398QQQ",
|
||||
xvcvuxwdp_2 = "f00003a0Q-Q",
|
||||
xvrdpip_2 = "f00003a4Q-Q",
|
||||
xvtsqrtdp_2 = "f00003a8X-Q",
|
||||
xvrdpic_2 = "f00003acQ-Q",
|
||||
xvdivdp_3 = "f00003c0QQQ",
|
||||
xvmsubmdp_3 = "f00003c8QQQ",
|
||||
xvcvsxwdp_2 = "f00003e0Q-Q",
|
||||
xvrdpim_2 = "f00003e4Q-Q",
|
||||
xvtdivdp_3 = "f00003e8XQQ",
|
||||
xsnmaddasp_3 = "f0000408QQQ",
|
||||
xxland_3 = "f0000410QQQ",
|
||||
xscvdpsp_2 = "f0000424Q-Q",
|
||||
xscvdpspn_2 = "f000042cQ-Q",
|
||||
xsnmaddmsp_3 = "f0000448QQQ",
|
||||
xxlandc_3 = "f0000450QQQ",
|
||||
xsrsp_2 = "f0000464Q-Q",
|
||||
xsnmsubasp_3 = "f0000488QQQ",
|
||||
xxlor_3 = "f0000490QQQ",
|
||||
xscvuxdsp_2 = "f00004a0Q-Q",
|
||||
xsnmsubmsp_3 = "f00004c8QQQ",
|
||||
xxlxor_3 = "f00004d0QQQ",
|
||||
xscvsxdsp_2 = "f00004e0Q-Q",
|
||||
xsmaxdp_3 = "f0000500QQQ",
|
||||
xsnmaddadp_3 = "f0000508QQQ",
|
||||
xxlnor_3 = "f0000510QQQ",
|
||||
xscvdpuxds_2 = "f0000520Q-Q",
|
||||
xscvspdp_2 = "f0000524Q-Q",
|
||||
xscvspdpn_2 = "f000052cQ-Q",
|
||||
xsmindp_3 = "f0000540QQQ",
|
||||
xsnmaddmdp_3 = "f0000548QQQ",
|
||||
xxlorc_3 = "f0000550QQQ",
|
||||
xscvdpsxds_2 = "f0000560Q-Q",
|
||||
xsabsdp_2 = "f0000564Q-Q",
|
||||
xscpsgndp_3 = "f0000580QQQ",
|
||||
xsnmsubadp_3 = "f0000588QQQ",
|
||||
xxlnand_3 = "f0000590QQQ",
|
||||
xscvuxddp_2 = "f00005a0Q-Q",
|
||||
xsnabsdp_2 = "f00005a4Q-Q",
|
||||
xsnmsubmdp_3 = "f00005c8QQQ",
|
||||
xxleqv_3 = "f00005d0QQQ",
|
||||
xscvsxddp_2 = "f00005e0Q-Q",
|
||||
xsnegdp_2 = "f00005e4Q-Q",
|
||||
xvmaxsp_3 = "f0000600QQQ",
|
||||
xvnmaddasp_3 = "f0000608QQQ",
|
||||
["xvcmpeqsp._3"] = "f0000618QQQ",
|
||||
xvcvspuxds_2 = "f0000620Q-Q",
|
||||
xvcvdpsp_2 = "f0000624Q-Q",
|
||||
xvminsp_3 = "f0000640QQQ",
|
||||
xvnmaddmsp_3 = "f0000648QQQ",
|
||||
["xvcmpgtsp._3"] = "f0000658QQQ",
|
||||
xvcvspsxds_2 = "f0000660Q-Q",
|
||||
xvabssp_2 = "f0000664Q-Q",
|
||||
xvcpsgnsp_3 = "f0000680QQQ",
|
||||
xvnmsubasp_3 = "f0000688QQQ",
|
||||
["xvcmpgesp._3"] = "f0000698QQQ",
|
||||
xvcvuxdsp_2 = "f00006a0Q-Q",
|
||||
xvnabssp_2 = "f00006a4Q-Q",
|
||||
xvnmsubmsp_3 = "f00006c8QQQ",
|
||||
xvcvsxdsp_2 = "f00006e0Q-Q",
|
||||
xvnegsp_2 = "f00006e4Q-Q",
|
||||
xvmaxdp_3 = "f0000700QQQ",
|
||||
xvnmaddadp_3 = "f0000708QQQ",
|
||||
["xvcmpeqdp._3"] = "f0000718QQQ",
|
||||
xvcvdpuxds_2 = "f0000720Q-Q",
|
||||
xvcvspdp_2 = "f0000724Q-Q",
|
||||
xvmindp_3 = "f0000740QQQ",
|
||||
xvnmaddmdp_3 = "f0000748QQQ",
|
||||
["xvcmpgtdp._3"] = "f0000758QQQ",
|
||||
xvcvdpsxds_2 = "f0000760Q-Q",
|
||||
xvabsdp_2 = "f0000764Q-Q",
|
||||
xvcpsgndp_3 = "f0000780QQQ",
|
||||
xvnmsubadp_3 = "f0000788QQQ",
|
||||
["xvcmpgedp._3"] = "f0000798QQQ",
|
||||
xvcvuxddp_2 = "f00007a0Q-Q",
|
||||
xvnabsdp_2 = "f00007a4Q-Q",
|
||||
xvnmsubmdp_3 = "f00007c8QQQ",
|
||||
xvcvsxddp_2 = "f00007e0Q-Q",
|
||||
xvnegdp_2 = "f00007e4Q-Q",
|
||||
|
||||
-- Primary opcode 61:
|
||||
stfdp_2 = "f4000000F:D", -- NYI: displacement must be divisible by 4.
|
||||
|
||||
-- Primary opcode 62:
|
||||
stq_2 = "f8000002R:D", -- NYI: displacement must be divisible by 8.
|
||||
|
||||
-- Primary opcode 63:
|
||||
fdiv_3 = "fc000024FFF.",
|
||||
|
@ -526,8 +1086,12 @@ local map_op = {
|
|||
frsp_2 = "fc000018F-F.",
|
||||
fctiw_2 = "fc00001cF-F.",
|
||||
fctiwz_2 = "fc00001eF-F.",
|
||||
ftdiv_2 = "fc000100X-F.",
|
||||
fctiwu_2 = "fc00011cF-F.",
|
||||
fctiwuz_2 = "fc00011eF-F.",
|
||||
mtfsfi_2 = "fc00010cAA", -- NYI: upshift.
|
||||
fnabs_2 = "fc000110F-F.",
|
||||
ftsqrt_2 = "fc000140X-F.",
|
||||
fabs_2 = "fc000210F-F.",
|
||||
frin_2 = "fc000310F-F.",
|
||||
friz_2 = "fc000350F-F.",
|
||||
|
@ -537,7 +1101,38 @@ local map_op = {
|
|||
-- NYI: mtfsf, mtfsb0, mtfsb1.
|
||||
fctid_2 = "fc00065cF-F.",
|
||||
fctidz_2 = "fc00065eF-F.",
|
||||
fmrgow_3 = "fc00068cFFF",
|
||||
fcfid_2 = "fc00069cF-F.",
|
||||
fctidu_2 = "fc00075cF-F.",
|
||||
fctiduz_2 = "fc00075eF-F.",
|
||||
fmrgew_3 = "fc00078cFFF",
|
||||
fcfidu_2 = "fc00079cF-F.",
|
||||
|
||||
daddq_3 = "fc000004F:F:F:.",
|
||||
dquaq_4 = "fc000006F:F:F:Z.",
|
||||
dmulq_3 = "fc000044F:F:F:.",
|
||||
drrndq_4 = "fc000046F:F:F:Z.",
|
||||
dscliq_3 = "fc000084F:F:6.",
|
||||
dquaiq_4 = "fc000086SF:~F:Z.",
|
||||
dscriq_3 = "fc0000c4F:F:6.",
|
||||
drintxq_4 = "fc0000c61F:~F:Z.",
|
||||
dcmpoq_3 = "fc000104XF:F:",
|
||||
dtstexq_3 = "fc000144XF:F:",
|
||||
dtstdcq_3 = "fc000184XF:6",
|
||||
dtstdgq_3 = "fc0001c4XF:6",
|
||||
drintnq_4 = "fc0001c61F:~F:Z.",
|
||||
dctqpq_2 = "fc000204F:-F:.",
|
||||
dctfixq_2 = "fc000244F:-F:.",
|
||||
ddedpdq_3 = "fc000284ZF:~F:.",
|
||||
dxexq_2 = "fc0002c4F:-F:.",
|
||||
dsubq_3 = "fc000404F:F:F:.",
|
||||
ddivq_3 = "fc000444F:F:F:.",
|
||||
dcmpuq_3 = "fc000504XF:F:",
|
||||
dtstsfq_3 = "fc000544XF:F:",
|
||||
drdpq_2 = "fc000604F:-F:.",
|
||||
dcffixq_2 = "fc000644F:-F:.",
|
||||
denbcdq_3 = "fc000684YF:~F:.",
|
||||
diexq_3 = "fc0006c4F:FF:.",
|
||||
|
||||
-- Primary opcode 4, SPE APU extension:
|
||||
evaddw_3 = "10000200RRR",
|
||||
|
@ -822,7 +1417,7 @@ local map_op = {
|
|||
do
|
||||
local t = {}
|
||||
for k,v in pairs(map_op) do
|
||||
if sub(v, -1) == "." then
|
||||
if type(v) == "string" and sub(v, -1) == "." then
|
||||
local v2 = sub(v, 1, 7)..char(byte(v, 8)+1)..sub(v, 9, -2)
|
||||
t[sub(k, 1, -3).."."..sub(k, -2)] = v2
|
||||
end
|
||||
|
@ -884,6 +1479,24 @@ local function parse_fpr(expr)
|
|||
werror("bad register name `"..expr.."'")
|
||||
end
|
||||
|
||||
local function parse_vr(expr)
|
||||
local r = match(expr, "^v([1-3]?[0-9])$")
|
||||
if r then
|
||||
r = tonumber(r)
|
||||
if r <= 31 then return r end
|
||||
end
|
||||
werror("bad register name `"..expr.."'")
|
||||
end
|
||||
|
||||
local function parse_vs(expr)
|
||||
local r = match(expr, "^vs([1-6]?[0-9])$")
|
||||
if r then
|
||||
r = tonumber(r)
|
||||
if r <= 63 then return r end
|
||||
end
|
||||
werror("bad register name `"..expr.."'")
|
||||
end
|
||||
|
||||
local function parse_cr(expr)
|
||||
local r = match(expr, "^cr([0-7])$")
|
||||
if r then return tonumber(r) end
|
||||
|
@ -900,8 +1513,30 @@ local function parse_cond(expr)
|
|||
werror("bad condition bit name `"..expr.."'")
|
||||
end
|
||||
|
||||
local parse_ctx = {}
|
||||
|
||||
local loadenv = setfenv and function(s)
|
||||
local code = loadstring(s, "")
|
||||
if code then setfenv(code, parse_ctx) end
|
||||
return code
|
||||
end or function(s)
|
||||
return load(s, "", nil, parse_ctx)
|
||||
end
|
||||
|
||||
-- Try to parse simple arithmetic, too, since some basic ops are aliases.
|
||||
local function parse_number(n)
|
||||
local x = tonumber(n)
|
||||
if x then return x end
|
||||
local code = loadenv("return "..n)
|
||||
if code then
|
||||
local ok, y = pcall(code)
|
||||
if ok then return y end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function parse_imm(imm, bits, shift, scale, signed)
|
||||
local n = tonumber(imm)
|
||||
local n = parse_number(imm)
|
||||
if n then
|
||||
local m = sar(n, scale)
|
||||
if shl(m, scale) == n then
|
||||
|
@ -914,7 +1549,8 @@ local function parse_imm(imm, bits, shift, scale, signed)
|
|||
end
|
||||
end
|
||||
werror("out of range immediate `"..imm.."'")
|
||||
elseif match(imm, "^r([1-3]?[0-9])$") or
|
||||
elseif match(imm, "^[rfv]([1-3]?[0-9])$") or
|
||||
match(imm, "^vs([1-6]?[0-9])$") or
|
||||
match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then
|
||||
werror("expected immediate operand, got register")
|
||||
else
|
||||
|
@ -924,11 +1560,11 @@ local function parse_imm(imm, bits, shift, scale, signed)
|
|||
end
|
||||
|
||||
local function parse_shiftmask(imm, isshift)
|
||||
local n = tonumber(imm)
|
||||
local n = parse_number(imm)
|
||||
if n then
|
||||
if shr(n, 6) == 0 then
|
||||
local lsb = band(imm, 31)
|
||||
local msb = imm - lsb
|
||||
local lsb = band(n, 31)
|
||||
local msb = n - lsb
|
||||
return isshift and (shl(lsb, 11)+shr(msb, 4)) or (shl(lsb, 6)+msb)
|
||||
end
|
||||
werror("out of range immediate `"..imm.."'")
|
||||
|
@ -936,7 +1572,8 @@ local function parse_shiftmask(imm, isshift)
|
|||
match(imm, "^([%w_]+):(r[1-3]?[0-9])$") then
|
||||
werror("expected immediate operand, got register")
|
||||
else
|
||||
werror("NYI: parameterized 64 bit shift/mask")
|
||||
waction("IMMSH", isshift and 1 or 0, imm)
|
||||
return 0;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1011,7 +1648,7 @@ end
|
|||
------------------------------------------------------------------------------
|
||||
|
||||
-- Handle opcodes defined with template strings.
|
||||
map_op[".template__"] = function(params, template, nparams)
|
||||
op_template = function(params, template, nparams)
|
||||
if not params then return sub(template, 9) end
|
||||
local op = tonumber(sub(template, 1, 8), 16)
|
||||
local n, rs = 1, 26
|
||||
|
@ -1027,6 +1664,15 @@ map_op[".template__"] = function(params, template, nparams)
|
|||
rs = rs - 5; op = op + shl(parse_gpr(params[n]), rs); n = n + 1
|
||||
elseif p == "F" then
|
||||
rs = rs - 5; op = op + shl(parse_fpr(params[n]), rs); n = n + 1
|
||||
elseif p == "V" then
|
||||
rs = rs - 5; op = op + shl(parse_vr(params[n]), rs); n = n + 1
|
||||
elseif p == "Q" then
|
||||
local vs = parse_vs(params[n]); n = n + 1; rs = rs - 5
|
||||
local sh = rs == 6 and 2 or 3 + band(shr(rs, 1), 3)
|
||||
op = op + shl(band(vs, 31), rs) + shr(band(vs, 32), sh)
|
||||
elseif p == "q" then
|
||||
local vs = parse_vs(params[n]); n = n + 1
|
||||
op = op + shl(band(vs, 31), 21) + shr(band(vs, 32), 5)
|
||||
elseif p == "A" then
|
||||
rs = rs - 5; op = op + parse_imm(params[n], 5, rs, 0, false); n = n + 1
|
||||
elseif p == "S" then
|
||||
|
@ -1047,6 +1693,26 @@ map_op[".template__"] = function(params, template, nparams)
|
|||
rs = rs - 5; op = op + shl(parse_cond(params[n]), rs); n = n + 1
|
||||
elseif p == "X" then
|
||||
rs = rs - 5; op = op + shl(parse_cr(params[n]), rs+2); n = n + 1
|
||||
elseif p == "1" then
|
||||
rs = rs - 5; op = op + parse_imm(params[n], 1, rs, 0, false); n = n + 1
|
||||
elseif p == "g" then
|
||||
rs = rs - 5; op = op + parse_imm(params[n], 2, rs, 0, false); n = n + 1
|
||||
elseif p == "3" then
|
||||
rs = rs - 5; op = op + parse_imm(params[n], 3, rs, 0, false); n = n + 1
|
||||
elseif p == "P" then
|
||||
rs = rs - 5; op = op + parse_imm(params[n], 4, rs, 0, false); n = n + 1
|
||||
elseif p == "p" then
|
||||
op = op + parse_imm(params[n], 4, rs, 0, false); n = n + 1
|
||||
elseif p == "6" then
|
||||
rs = rs - 6; op = op + parse_imm(params[n], 6, rs, 0, false); n = n + 1
|
||||
elseif p == "Y" then
|
||||
rs = rs - 5; op = op + parse_imm(params[n], 1, rs+4, 0, false); n = n + 1
|
||||
elseif p == "y" then
|
||||
rs = rs - 5; op = op + parse_imm(params[n], 1, rs+3, 0, false); n = n + 1
|
||||
elseif p == "Z" then
|
||||
rs = rs - 5; op = op + parse_imm(params[n], 2, rs+3, 0, false); n = n + 1
|
||||
elseif p == "z" then
|
||||
rs = rs - 5; op = op + parse_imm(params[n], 2, rs+2, 0, false); n = n + 1
|
||||
elseif p == "W" then
|
||||
op = op + parse_cr(params[n]); n = n + 1
|
||||
elseif p == "G" then
|
||||
|
@ -1071,6 +1737,8 @@ map_op[".template__"] = function(params, template, nparams)
|
|||
local lo = band(op, mm)
|
||||
local hi = band(op, shl(mm, 5))
|
||||
op = op - lo - hi + shl(lo, 5) + shr(hi, 5)
|
||||
elseif p == ":" then
|
||||
if band(shr(op, rs), 1) ~= 0 then werror("register pair expected") end
|
||||
elseif p == "-" then
|
||||
rs = rs - 5
|
||||
elseif p == "." then
|
||||
|
@ -1082,6 +1750,8 @@ map_op[".template__"] = function(params, template, nparams)
|
|||
wputpos(pos, op)
|
||||
end
|
||||
|
||||
map_op[".template__"] = op_template
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- Pseudo-opcode to mark the position where the action list is to be emitted.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** DynASM encoding engine prototypes.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
|
@ -10,8 +10,8 @@
|
|||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define DASM_IDENT "DynASM 1.3.0"
|
||||
#define DASM_VERSION 10300 /* 1.3.0 */
|
||||
#define DASM_IDENT "DynASM 1.4.0"
|
||||
#define DASM_VERSION 10400 /* 1.4.0 */
|
||||
|
||||
#ifndef Dst_DECL
|
||||
#define Dst_DECL dasm_State **Dst
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
------------------------------------------------------------------------------
|
||||
-- DynASM x64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
-- This module just sets 64 bit mode for the combined x86/x64 module.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** DynASM x86 encoding engine.
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
** Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
** Released under the MIT license. See dynasm.lua for full copyright notice.
|
||||
*/
|
||||
|
||||
|
@ -170,7 +170,7 @@ void dasm_put(Dst_DECL, int start, ...)
|
|||
dasm_State *D = Dst_REF;
|
||||
dasm_ActList p = D->actionlist + start;
|
||||
dasm_Section *sec = D->section;
|
||||
int pos = sec->pos, ofs = sec->ofs, mrm = 4;
|
||||
int pos = sec->pos, ofs = sec->ofs, mrm = -1;
|
||||
int *b;
|
||||
|
||||
if (pos >= sec->epos) {
|
||||
|
@ -193,7 +193,7 @@ void dasm_put(Dst_DECL, int start, ...)
|
|||
b[pos++] = n;
|
||||
switch (action) {
|
||||
case DASM_DISP:
|
||||
if (n == 0) { if ((mrm&7) == 4) mrm = p[-2]; if ((mrm&7) != 5) break; }
|
||||
if (n == 0) { if (mrm < 0) mrm = p[-2]; if ((mrm&7) != 5) break; }
|
||||
case DASM_IMM_DB: if (((n+128)&-256) == 0) goto ob;
|
||||
case DASM_REL_A: /* Assumes ptrdiff_t is int. !x64 */
|
||||
case DASM_IMM_D: ofs += 4; break;
|
||||
|
@ -203,10 +203,17 @@ void dasm_put(Dst_DECL, int start, ...)
|
|||
case DASM_IMM_W: CK((n&-65536) == 0, RANGE_I); ofs += 2; break;
|
||||
case DASM_SPACE: p++; ofs += n; break;
|
||||
case DASM_SETLABEL: b[pos-2] = -0x40000000; break; /* Neg. label ofs. */
|
||||
case DASM_VREG: CK((n&-8) == 0 && (n != 4 || (*p&1) == 0), RANGE_VREG);
|
||||
if (*p++ == 1 && *p == DASM_DISP) mrm = n; continue;
|
||||
case DASM_VREG: CK((n&-16) == 0 && (n != 4 || (*p>>5) != 2), RANGE_VREG);
|
||||
if (*p < 0x40 && p[1] == DASM_DISP) mrm = n;
|
||||
if (*p < 0x20 && (n&7) == 4) ofs++;
|
||||
switch ((*p++ >> 3) & 3) {
|
||||
case 3: n |= b[pos-3];
|
||||
case 2: n |= b[pos-2];
|
||||
case 1: if (n <= 7) { b[pos-1] |= 0x10; ofs--; }
|
||||
}
|
||||
continue;
|
||||
}
|
||||
mrm = 4;
|
||||
mrm = -1;
|
||||
} else {
|
||||
int *pl, n;
|
||||
switch (action) {
|
||||
|
@ -391,7 +398,27 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||
case DASM_IMM_D: wd: dasmd(n); break;
|
||||
case DASM_IMM_WB: if (((n+128)&-256) == 0) goto db; else mark = NULL;
|
||||
case DASM_IMM_W: dasmw(n); break;
|
||||
case DASM_VREG: { int t = *p++; if (t >= 2) n<<=3; cp[-1] |= n; break; }
|
||||
case DASM_VREG: {
|
||||
int t = *p++;
|
||||
unsigned char *ex = cp - (t&7);
|
||||
if ((n & 8) && t < 0xa0) {
|
||||
if (*ex & 0x80) ex[1] ^= 0x20 << (t>>6); else *ex ^= 1 << (t>>6);
|
||||
n &= 7;
|
||||
} else if (n & 0x10) {
|
||||
if (*ex & 0x80) {
|
||||
*ex = 0xc5; ex[1] = (ex[1] & 0x80) | ex[2]; ex += 2;
|
||||
}
|
||||
while (++ex < cp) ex[-1] = *ex;
|
||||
if (mark) mark--;
|
||||
cp--;
|
||||
n &= 7;
|
||||
}
|
||||
if (t >= 0xc0) n <<= 4;
|
||||
else if (t >= 0x40) n <<= 3;
|
||||
else if (n == 4 && t < 0x20) { cp[-1] ^= n; *cp++ = 0x20; }
|
||||
cp[-1] ^= n;
|
||||
break;
|
||||
}
|
||||
case DASM_REL_LG: p++; if (n >= 0) goto rel_pc;
|
||||
b++; n = (int)(ptrdiff_t)D->globals[-n];
|
||||
case DASM_REL_A: rel_a: n -= (int)(ptrdiff_t)(cp+4); goto wd; /* !x64 */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
------------------------------------------------------------------------------
|
||||
-- DynASM x86/x64 module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- See dynasm.lua for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
@ -11,9 +11,9 @@ local x64 = x64
|
|||
local _info = {
|
||||
arch = x64 and "x64" or "x86",
|
||||
description = "DynASM x86/x64 module",
|
||||
version = "1.3.0",
|
||||
vernum = 10300,
|
||||
release = "2011-05-05",
|
||||
version = "1.4.0",
|
||||
vernum = 10400,
|
||||
release = "2015-10-18",
|
||||
author = "Mike Pall",
|
||||
license = "MIT",
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ local assert, unpack, setmetatable = assert, unpack or table.unpack, setmetatabl
|
|||
local _s = string
|
||||
local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char
|
||||
local find, match, gmatch, gsub = _s.find, _s.match, _s.gmatch, _s.gsub
|
||||
local concat, sort = table.concat, table.sort
|
||||
local concat, sort, remove = table.concat, table.sort, table.remove
|
||||
local bit = bit or require("bit")
|
||||
local band, shl, shr = bit.band, bit.lshift, bit.rshift
|
||||
local band, bxor, shl, shr = bit.band, bit.bxor, bit.lshift, bit.rshift
|
||||
|
||||
-- Inherited tables and callbacks.
|
||||
local g_opt, g_arch
|
||||
|
@ -41,7 +41,7 @@ local action_names = {
|
|||
-- int arg, 1 buffer pos:
|
||||
"DISP", "IMM_S", "IMM_B", "IMM_W", "IMM_D", "IMM_WB", "IMM_DB",
|
||||
-- action arg (1 byte), int arg, 1 buffer pos (reg/num):
|
||||
"VREG", "SPACE", -- !x64: VREG support NYI.
|
||||
"VREG", "SPACE",
|
||||
-- ptrdiff_t arg, 1 buffer pos (address): !x64
|
||||
"SETLABEL", "REL_A",
|
||||
-- action arg (1 byte) or int arg, 2 buffer pos (link, offset):
|
||||
|
@ -83,6 +83,21 @@ local actargs = { 0 }
|
|||
-- Current number of section buffer positions for dasm_put().
|
||||
local secpos = 1
|
||||
|
||||
-- VREG kind encodings, pre-shifted by 5 bits.
|
||||
local map_vreg = {
|
||||
["modrm.rm.m"] = 0x00,
|
||||
["modrm.rm.r"] = 0x20,
|
||||
["opcode"] = 0x20,
|
||||
["sib.base"] = 0x20,
|
||||
["sib.index"] = 0x40,
|
||||
["modrm.reg"] = 0x80,
|
||||
["vex.v"] = 0xa0,
|
||||
["imm.hi"] = 0xc0,
|
||||
}
|
||||
|
||||
-- Current number of VREG actions contributing to REX/VEX shrinkage.
|
||||
local vreg_shrink_count = 0
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- Compute action numbers for action names.
|
||||
|
@ -134,6 +149,21 @@ local function waction(action, a, num)
|
|||
if a or num then secpos = secpos + (num or 1) end
|
||||
end
|
||||
|
||||
-- Optionally add a VREG action.
|
||||
local function wvreg(kind, vreg, psz, sk, defer)
|
||||
if not vreg then return end
|
||||
waction("VREG", vreg)
|
||||
local b = assert(map_vreg[kind], "bad vreg kind `"..vreg.."'")
|
||||
if b < (sk or 0) then
|
||||
vreg_shrink_count = vreg_shrink_count + 1
|
||||
end
|
||||
if not defer then
|
||||
b = b + vreg_shrink_count * 8
|
||||
vreg_shrink_count = 0
|
||||
end
|
||||
wputxb(b + (psz or 0))
|
||||
end
|
||||
|
||||
-- Add call to embedded DynASM C code.
|
||||
local function wcall(func, args)
|
||||
wline(format("dasm_%s(Dst, %s);", func, concat(args, ", ")), true)
|
||||
|
@ -299,7 +329,7 @@ local function mkrmap(sz, cl, names)
|
|||
local iname = format("@%s%x%s", sz, i, needrex and "R" or "")
|
||||
if needrex then map_reg_needrex[iname] = true end
|
||||
local name
|
||||
if sz == "o" then name = format("xmm%d", i)
|
||||
if sz == "o" or sz == "y" then name = format("%s%d", cl, i)
|
||||
elseif sz == "f" then name = format("st%d", i)
|
||||
else name = format("r%d%s", i, sz == addrsize and "" or sz) end
|
||||
map_archdef[name] = iname
|
||||
|
@ -326,6 +356,7 @@ mkrmap("w", "Rw", {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di"})
|
|||
mkrmap("b", "Rb", {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"})
|
||||
map_reg_valid_index[map_archdef.esp] = false
|
||||
if x64 then map_reg_valid_index[map_archdef.rsp] = false end
|
||||
if x64 then map_reg_needrex[map_archdef.Rb] = true end
|
||||
map_archdef["Ra"] = "@"..addrsize
|
||||
|
||||
-- FP registers (internally tword sized, but use "f" as operand size).
|
||||
|
@ -334,21 +365,24 @@ mkrmap("f", "Rf")
|
|||
-- SSE registers (oword sized, but qword and dword accessible).
|
||||
mkrmap("o", "xmm")
|
||||
|
||||
-- AVX registers (yword sized, but oword, qword and dword accessible).
|
||||
mkrmap("y", "ymm")
|
||||
|
||||
-- Operand size prefixes to codes.
|
||||
local map_opsize = {
|
||||
byte = "b", word = "w", dword = "d", qword = "q", oword = "o", tword = "t",
|
||||
aword = addrsize,
|
||||
byte = "b", word = "w", dword = "d", qword = "q", oword = "o", yword = "y",
|
||||
tword = "t", aword = addrsize,
|
||||
}
|
||||
|
||||
-- Operand size code to number.
|
||||
local map_opsizenum = {
|
||||
b = 1, w = 2, d = 4, q = 8, o = 16, t = 10,
|
||||
b = 1, w = 2, d = 4, q = 8, o = 16, y = 32, t = 10,
|
||||
}
|
||||
|
||||
-- Operand size code to name.
|
||||
local map_opsizename = {
|
||||
b = "byte", w = "word", d = "dword", q = "qword", o = "oword", t = "tword",
|
||||
f = "fpword",
|
||||
b = "byte", w = "word", d = "dword", q = "qword", o = "oword", y = "yword",
|
||||
t = "tword", f = "fpword",
|
||||
}
|
||||
|
||||
-- Valid index register scale factors.
|
||||
|
@ -460,9 +494,45 @@ local function wputszarg(sz, n)
|
|||
end
|
||||
|
||||
-- Put multi-byte opcode with operand-size dependent modifications.
|
||||
local function wputop(sz, op, rex)
|
||||
local function wputop(sz, op, rex, vex, vregr, vregxb)
|
||||
local psz, sk = 0, nil
|
||||
if vex then
|
||||
local tail
|
||||
if vex.m == 1 and band(rex, 11) == 0 then
|
||||
if x64 and vregxb then
|
||||
sk = map_vreg["modrm.reg"]
|
||||
else
|
||||
wputb(0xc5)
|
||||
tail = shl(bxor(band(rex, 4), 4), 5)
|
||||
psz = 3
|
||||
end
|
||||
end
|
||||
if not tail then
|
||||
wputb(0xc4)
|
||||
wputb(shl(bxor(band(rex, 7), 7), 5) + vex.m)
|
||||
tail = shl(band(rex, 8), 4)
|
||||
psz = 4
|
||||
end
|
||||
local reg, vreg = 0, nil
|
||||
if vex.v then
|
||||
reg = vex.v.reg
|
||||
if not reg then werror("bad vex operand") end
|
||||
if reg < 0 then reg = 0; vreg = vex.v.vreg end
|
||||
end
|
||||
if sz == "y" or vex.l then tail = tail + 4 end
|
||||
wputb(tail + shl(bxor(reg, 15), 3) + vex.p)
|
||||
wvreg("vex.v", vreg)
|
||||
rex = 0
|
||||
if op >= 256 then werror("bad vex opcode") end
|
||||
else
|
||||
if rex ~= 0 then
|
||||
if not x64 then werror("bad operand size") end
|
||||
elseif (vregr or vregxb) and x64 then
|
||||
rex = 0x10
|
||||
sk = map_vreg["vex.v"]
|
||||
end
|
||||
end
|
||||
local r
|
||||
if rex ~= 0 and not x64 then werror("bad operand size") end
|
||||
if sz == "w" then wputb(102) end
|
||||
-- Needs >32 bit numbers, but only for crc32 eax, word [ebx]
|
||||
if op >= 4294967296 then r = op%4294967296 wputb((op-r)/4294967296) op = r end
|
||||
|
@ -471,20 +541,20 @@ local function wputop(sz, op, rex)
|
|||
if rex ~= 0 then
|
||||
local opc3 = band(op, 0xffff00)
|
||||
if opc3 == 0x0f3a00 or opc3 == 0x0f3800 then
|
||||
wputb(64 + band(rex, 15)); rex = 0
|
||||
wputb(64 + band(rex, 15)); rex = 0; psz = 2
|
||||
end
|
||||
end
|
||||
wputb(shr(op, 16)); op = band(op, 0xffff)
|
||||
wputb(shr(op, 16)); op = band(op, 0xffff); psz = psz + 1
|
||||
end
|
||||
if op >= 256 then
|
||||
local b = shr(op, 8)
|
||||
if b == 15 and rex ~= 0 then wputb(64 + band(rex, 15)); rex = 0 end
|
||||
wputb(b)
|
||||
op = band(op, 255)
|
||||
if b == 15 and rex ~= 0 then wputb(64 + band(rex, 15)); rex = 0; psz = 2 end
|
||||
wputb(b); op = band(op, 255); psz = psz + 1
|
||||
end
|
||||
if rex ~= 0 then wputb(64 + band(rex, 15)) end
|
||||
if rex ~= 0 then wputb(64 + band(rex, 15)); psz = 2 end
|
||||
if sz == "b" then op = op - 1 end
|
||||
wputb(op)
|
||||
return psz, sk
|
||||
end
|
||||
|
||||
-- Put ModRM or SIB formatted byte.
|
||||
|
@ -494,7 +564,7 @@ local function wputmodrm(m, s, rm, vs, vrm)
|
|||
end
|
||||
|
||||
-- Put ModRM/SIB plus optional displacement.
|
||||
local function wputmrmsib(t, imark, s, vsreg)
|
||||
local function wputmrmsib(t, imark, s, vsreg, psz, sk)
|
||||
local vreg, vxreg
|
||||
local reg, xreg = t.reg, t.xreg
|
||||
if reg and reg < 0 then reg = 0; vreg = t.vreg end
|
||||
|
@ -504,8 +574,8 @@ local function wputmrmsib(t, imark, s, vsreg)
|
|||
-- Register mode.
|
||||
if sub(t.mode, 1, 1) == "r" then
|
||||
wputmodrm(3, s, reg)
|
||||
if vsreg then waction("VREG", vsreg); wputxb(2) end
|
||||
if vreg then waction("VREG", vreg); wputxb(0) end
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk, vreg)
|
||||
wvreg("modrm.rm.r", vreg, psz+1, sk)
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -519,21 +589,22 @@ local function wputmrmsib(t, imark, s, vsreg)
|
|||
-- [xreg*xsc+disp] -> (0, s, esp) (xsc, xreg, ebp)
|
||||
wputmodrm(0, s, 4)
|
||||
if imark == "I" then waction("MARK") end
|
||||
if vsreg then waction("VREG", vsreg); wputxb(2) end
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk, vxreg)
|
||||
wputmodrm(t.xsc, xreg, 5)
|
||||
if vxreg then waction("VREG", vxreg); wputxb(3) end
|
||||
wvreg("sib.index", vxreg, psz+2, sk)
|
||||
else
|
||||
-- Pure 32 bit displacement.
|
||||
if x64 and tdisp ~= "table" then
|
||||
wputmodrm(0, s, 4) -- [disp] -> (0, s, esp) (0, esp, ebp)
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk)
|
||||
if imark == "I" then waction("MARK") end
|
||||
wputmodrm(0, 4, 5)
|
||||
else
|
||||
riprel = x64
|
||||
wputmodrm(0, s, 5) -- [disp|rip-label] -> (0, s, ebp)
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk)
|
||||
if imark == "I" then waction("MARK") end
|
||||
end
|
||||
if vsreg then waction("VREG", vsreg); wputxb(2) end
|
||||
end
|
||||
if riprel then -- Emit rip-relative displacement.
|
||||
if match("UWSiI", imark) then
|
||||
|
@ -561,16 +632,16 @@ local function wputmrmsib(t, imark, s, vsreg)
|
|||
if xreg or band(reg, 7) == 4 then
|
||||
wputmodrm(m or 2, s, 4) -- ModRM.
|
||||
if m == nil or imark == "I" then waction("MARK") end
|
||||
if vsreg then waction("VREG", vsreg); wputxb(2) end
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk, vxreg or vreg)
|
||||
wputmodrm(t.xsc or 0, xreg or 4, reg) -- SIB.
|
||||
if vxreg then waction("VREG", vxreg); wputxb(3) end
|
||||
if vreg then waction("VREG", vreg); wputxb(1) end
|
||||
wvreg("sib.index", vxreg, psz+2, sk, vreg)
|
||||
wvreg("sib.base", vreg, psz+2, sk)
|
||||
else
|
||||
wputmodrm(m or 2, s, reg) -- ModRM.
|
||||
if (imark == "I" and (m == 1 or m == 2)) or
|
||||
(m == nil and (vsreg or vreg)) then waction("MARK") end
|
||||
if vsreg then waction("VREG", vsreg); wputxb(2) end
|
||||
if vreg then waction("VREG", vreg); wputxb(1) end
|
||||
wvreg("modrm.reg", vsreg, psz+1, sk, vreg)
|
||||
wvreg("modrm.rm.m", vreg, psz+1, sk)
|
||||
end
|
||||
|
||||
-- Put displacement.
|
||||
|
@ -881,9 +952,15 @@ end
|
|||
-- "m"/"M" generates ModRM/SIB from the 1st/2nd operand.
|
||||
-- The spare 3 bits are either filled with the last hex digit or
|
||||
-- the result from a previous "r"/"R". The opcode is restored.
|
||||
-- "u" Use VEX encoding, vvvv unused.
|
||||
-- "v"/"V" Use VEX encoding, vvvv from 1st/2nd operand (the operand is
|
||||
-- removed from the list used by future characters).
|
||||
-- "L" Force VEX.L
|
||||
--
|
||||
-- All of the following characters force a flush of the opcode:
|
||||
-- "o"/"O" stores a pure 32 bit disp (offset) from the 1st/2nd operand.
|
||||
-- "s" stores a 4 bit immediate from the last register operand,
|
||||
-- followed by 4 zero bits.
|
||||
-- "S" stores a signed 8 bit immediate from the last operand.
|
||||
-- "U" stores an unsigned 8 bit immediate from the last operand.
|
||||
-- "W" stores an unsigned 16 bit immediate from the last operand.
|
||||
|
@ -1081,10 +1158,11 @@ local map_op = {
|
|||
btr_2 = "mrqdw:0FB3Rm|miqdw:0FBA6mU",
|
||||
bts_2 = "mrqdw:0FABRm|miqdw:0FBA5mU",
|
||||
|
||||
shld_3 = "mriqdw:0FA4RmU|mrCqdw:0FA5Rm",
|
||||
shrd_3 = "mriqdw:0FACRmU|mrCqdw:0FADRm",
|
||||
shld_3 = "mriqdw:0FA4RmU|mrC/qq:0FA5Rm|mrC/dd:|mrC/ww:",
|
||||
shrd_3 = "mriqdw:0FACRmU|mrC/qq:0FADRm|mrC/dd:|mrC/ww:",
|
||||
|
||||
rdtsc_0 = "0F31", -- P1+
|
||||
rdpmc_0 = "0F33", -- P6+
|
||||
cpuid_0 = "0FA2", -- P1+
|
||||
|
||||
-- floating point ops
|
||||
|
@ -1190,7 +1268,7 @@ local map_op = {
|
|||
cvtsi2sd_2 = "rm/od:F20F2ArM|rm/oq:F20F2ArXM",
|
||||
cvtsi2ss_2 = "rm/od:F30F2ArM|rm/oq:F30F2ArXM",
|
||||
cvtss2sd_2 = "rro:F30F5ArM|rx/od:",
|
||||
cvtss2si_2 = "rr/do:F20F2CrM|rr/qo:|rxd:|rx/qd:",
|
||||
cvtss2si_2 = "rr/do:F30F2DrM|rr/qo:|rxd:|rx/qd:",
|
||||
cvttpd2dq_2 = "rmo:660FE6rM",
|
||||
cvttps2dq_2 = "rmo:F30F5BrM",
|
||||
cvttsd2si_2 = "rr/do:F20F2CrM|rr/qo:|rx/dq:|rxq:",
|
||||
|
@ -1225,46 +1303,14 @@ local map_op = {
|
|||
movups_2 = "rmo:0F10rM|mro:0F11Rm",
|
||||
orpd_2 = "rmo:660F56rM",
|
||||
orps_2 = "rmo:0F56rM",
|
||||
packssdw_2 = "rmo:660F6BrM",
|
||||
packsswb_2 = "rmo:660F63rM",
|
||||
packuswb_2 = "rmo:660F67rM",
|
||||
paddb_2 = "rmo:660FFCrM",
|
||||
paddd_2 = "rmo:660FFErM",
|
||||
paddq_2 = "rmo:660FD4rM",
|
||||
paddsb_2 = "rmo:660FECrM",
|
||||
paddsw_2 = "rmo:660FEDrM",
|
||||
paddusb_2 = "rmo:660FDCrM",
|
||||
paddusw_2 = "rmo:660FDDrM",
|
||||
paddw_2 = "rmo:660FFDrM",
|
||||
pand_2 = "rmo:660FDBrM",
|
||||
pandn_2 = "rmo:660FDFrM",
|
||||
pause_0 = "F390",
|
||||
pavgb_2 = "rmo:660FE0rM",
|
||||
pavgw_2 = "rmo:660FE3rM",
|
||||
pcmpeqb_2 = "rmo:660F74rM",
|
||||
pcmpeqd_2 = "rmo:660F76rM",
|
||||
pcmpeqw_2 = "rmo:660F75rM",
|
||||
pcmpgtb_2 = "rmo:660F64rM",
|
||||
pcmpgtd_2 = "rmo:660F66rM",
|
||||
pcmpgtw_2 = "rmo:660F65rM",
|
||||
pextrw_3 = "rri/do:660FC5rMU|xri/wo:660F3A15nrMU", -- Mem op: SSE4.1 only.
|
||||
pextrw_3 = "rri/do:660FC5rMU|xri/wo:660F3A15nRmU", -- Mem op: SSE4.1 only.
|
||||
pinsrw_3 = "rri/od:660FC4rMU|rxi/ow:",
|
||||
pmaddwd_2 = "rmo:660FF5rM",
|
||||
pmaxsw_2 = "rmo:660FEErM",
|
||||
pmaxub_2 = "rmo:660FDErM",
|
||||
pminsw_2 = "rmo:660FEArM",
|
||||
pminub_2 = "rmo:660FDArM",
|
||||
pmovmskb_2 = "rr/do:660FD7rM",
|
||||
pmulhuw_2 = "rmo:660FE4rM",
|
||||
pmulhw_2 = "rmo:660FE5rM",
|
||||
pmullw_2 = "rmo:660FD5rM",
|
||||
pmuludq_2 = "rmo:660FF4rM",
|
||||
por_2 = "rmo:660FEBrM",
|
||||
prefetchnta_1 = "xb:n0F180m",
|
||||
prefetcht0_1 = "xb:n0F181m",
|
||||
prefetcht1_1 = "xb:n0F182m",
|
||||
prefetcht2_1 = "xb:n0F183m",
|
||||
psadbw_2 = "rmo:660FF6rM",
|
||||
pshufd_3 = "rmio:660F70rMU",
|
||||
pshufhw_3 = "rmio:F30F70rMU",
|
||||
pshuflw_3 = "rmio:F20F70rMU",
|
||||
|
@ -1278,23 +1324,6 @@ local map_op = {
|
|||
psrldq_2 = "rio:660F733mU",
|
||||
psrlq_2 = "rmo:660FD3rM|rio:660F732mU",
|
||||
psrlw_2 = "rmo:660FD1rM|rio:660F712mU",
|
||||
psubb_2 = "rmo:660FF8rM",
|
||||
psubd_2 = "rmo:660FFArM",
|
||||
psubq_2 = "rmo:660FFBrM",
|
||||
psubsb_2 = "rmo:660FE8rM",
|
||||
psubsw_2 = "rmo:660FE9rM",
|
||||
psubusb_2 = "rmo:660FD8rM",
|
||||
psubusw_2 = "rmo:660FD9rM",
|
||||
psubw_2 = "rmo:660FF9rM",
|
||||
punpckhbw_2 = "rmo:660F68rM",
|
||||
punpckhdq_2 = "rmo:660F6ArM",
|
||||
punpckhqdq_2 = "rmo:660F6DrM",
|
||||
punpckhwd_2 = "rmo:660F69rM",
|
||||
punpcklbw_2 = "rmo:660F60rM",
|
||||
punpckldq_2 = "rmo:660F62rM",
|
||||
punpcklqdq_2 = "rmo:660F6CrM",
|
||||
punpcklwd_2 = "rmo:660F61rM",
|
||||
pxor_2 = "rmo:660FEFrM",
|
||||
rcpps_2 = "rmo:0F53rM",
|
||||
rcpss_2 = "rro:F30F53rM|rx/od:",
|
||||
rsqrtps_2 = "rmo:0F52rM",
|
||||
|
@ -1352,7 +1381,7 @@ local map_op = {
|
|||
dpps_3 = "rmio:660F3A40rMU",
|
||||
extractps_3 = "mri/do:660F3A17RmU|rri/qo:660F3A17RXmU",
|
||||
insertps_3 = "rrio:660F3A41rMU|rxi/od:",
|
||||
movntdqa_2 = "rmo:660F382ArM",
|
||||
movntdqa_2 = "rxo:660F382ArM",
|
||||
mpsadbw_3 = "rmio:660F3A42rMU",
|
||||
packusdw_2 = "rmo:660F382BrM",
|
||||
pblendvb_3 = "rmRo:660F3810rM",
|
||||
|
@ -1412,6 +1441,242 @@ local map_op = {
|
|||
movntsd_2 = "xr/qo:nF20F2BRm",
|
||||
movntss_2 = "xr/do:F30F2BRm",
|
||||
-- popcnt is also in SSE4.2
|
||||
|
||||
-- AES-NI
|
||||
aesdec_2 = "rmo:660F38DErM",
|
||||
aesdeclast_2 = "rmo:660F38DFrM",
|
||||
aesenc_2 = "rmo:660F38DCrM",
|
||||
aesenclast_2 = "rmo:660F38DDrM",
|
||||
aesimc_2 = "rmo:660F38DBrM",
|
||||
aeskeygenassist_3 = "rmio:660F3ADFrMU",
|
||||
pclmulqdq_3 = "rmio:660F3A44rMU",
|
||||
|
||||
-- AVX FP ops
|
||||
vaddsubpd_3 = "rrmoy:660FVD0rM",
|
||||
vaddsubps_3 = "rrmoy:F20FVD0rM",
|
||||
vandpd_3 = "rrmoy:660FV54rM",
|
||||
vandps_3 = "rrmoy:0FV54rM",
|
||||
vandnpd_3 = "rrmoy:660FV55rM",
|
||||
vandnps_3 = "rrmoy:0FV55rM",
|
||||
vblendpd_4 = "rrmioy:660F3AV0DrMU",
|
||||
vblendps_4 = "rrmioy:660F3AV0CrMU",
|
||||
vblendvpd_4 = "rrmroy:660F3AV4BrMs",
|
||||
vblendvps_4 = "rrmroy:660F3AV4ArMs",
|
||||
vbroadcastf128_2 = "rx/yo:660F38u1ArM",
|
||||
vcmppd_4 = "rrmioy:660FVC2rMU",
|
||||
vcmpps_4 = "rrmioy:0FVC2rMU",
|
||||
vcmpsd_4 = "rrrio:F20FVC2rMU|rrxi/ooq:",
|
||||
vcmpss_4 = "rrrio:F30FVC2rMU|rrxi/ood:",
|
||||
vcomisd_2 = "rro:660Fu2FrM|rx/oq:",
|
||||
vcomiss_2 = "rro:0Fu2FrM|rx/od:",
|
||||
vcvtdq2pd_2 = "rro:F30FuE6rM|rx/oq:|rm/yo:",
|
||||
vcvtdq2ps_2 = "rmoy:0Fu5BrM",
|
||||
vcvtpd2dq_2 = "rmoy:F20FuE6rM",
|
||||
vcvtpd2ps_2 = "rmoy:660Fu5ArM",
|
||||
vcvtps2dq_2 = "rmoy:660Fu5BrM",
|
||||
vcvtps2pd_2 = "rro:0Fu5ArM|rx/oq:|rm/yo:",
|
||||
vcvtsd2si_2 = "rr/do:F20Fu2DrM|rx/dq:|rr/qo:|rxq:",
|
||||
vcvtsd2ss_3 = "rrro:F20FV5ArM|rrx/ooq:",
|
||||
vcvtsi2sd_3 = "rrm/ood:F20FV2ArM|rrm/ooq:F20FVX2ArM",
|
||||
vcvtsi2ss_3 = "rrm/ood:F30FV2ArM|rrm/ooq:F30FVX2ArM",
|
||||
vcvtss2sd_3 = "rrro:F30FV5ArM|rrx/ood:",
|
||||
vcvtss2si_2 = "rr/do:F30Fu2DrM|rxd:|rr/qo:|rx/qd:",
|
||||
vcvttpd2dq_2 = "rmo:660FuE6rM|rm/oy:660FuLE6rM",
|
||||
vcvttps2dq_2 = "rmoy:F30Fu5BrM",
|
||||
vcvttsd2si_2 = "rr/do:F20Fu2CrM|rx/dq:|rr/qo:|rxq:",
|
||||
vcvttss2si_2 = "rr/do:F30Fu2CrM|rxd:|rr/qo:|rx/qd:",
|
||||
vdppd_4 = "rrmio:660F3AV41rMU",
|
||||
vdpps_4 = "rrmioy:660F3AV40rMU",
|
||||
vextractf128_3 = "mri/oy:660F3AuL19RmU",
|
||||
vextractps_3 = "mri/do:660F3Au17RmU",
|
||||
vhaddpd_3 = "rrmoy:660FV7CrM",
|
||||
vhaddps_3 = "rrmoy:F20FV7CrM",
|
||||
vhsubpd_3 = "rrmoy:660FV7DrM",
|
||||
vhsubps_3 = "rrmoy:F20FV7DrM",
|
||||
vinsertf128_4 = "rrmi/yyo:660F3AV18rMU",
|
||||
vinsertps_4 = "rrrio:660F3AV21rMU|rrxi/ood:",
|
||||
vldmxcsr_1 = "xd:0FuAE2m",
|
||||
vmaskmovps_3 = "rrxoy:660F38V2CrM|xrroy:660F38V2ERm",
|
||||
vmaskmovpd_3 = "rrxoy:660F38V2DrM|xrroy:660F38V2FRm",
|
||||
vmovapd_2 = "rmoy:660Fu28rM|mroy:660Fu29Rm",
|
||||
vmovaps_2 = "rmoy:0Fu28rM|mroy:0Fu29Rm",
|
||||
vmovd_2 = "rm/od:660Fu6ErM|rm/oq:660FuX6ErM|mr/do:660Fu7ERm|mr/qo:",
|
||||
vmovq_2 = "rro:F30Fu7ErM|rx/oq:|xr/qo:660FuD6Rm",
|
||||
vmovddup_2 = "rmy:F20Fu12rM|rro:|rx/oq:",
|
||||
vmovhlps_3 = "rrro:0FV12rM",
|
||||
vmovhpd_2 = "xr/qo:660Fu17Rm",
|
||||
vmovhpd_3 = "rrx/ooq:660FV16rM",
|
||||
vmovhps_2 = "xr/qo:0Fu17Rm",
|
||||
vmovhps_3 = "rrx/ooq:0FV16rM",
|
||||
vmovlhps_3 = "rrro:0FV16rM",
|
||||
vmovlpd_2 = "xr/qo:660Fu13Rm",
|
||||
vmovlpd_3 = "rrx/ooq:660FV12rM",
|
||||
vmovlps_2 = "xr/qo:0Fu13Rm",
|
||||
vmovlps_3 = "rrx/ooq:0FV12rM",
|
||||
vmovmskpd_2 = "rr/do:660Fu50rM|rr/dy:660FuL50rM",
|
||||
vmovmskps_2 = "rr/do:0Fu50rM|rr/dy:0FuL50rM",
|
||||
vmovntpd_2 = "xroy:660Fu2BRm",
|
||||
vmovntps_2 = "xroy:0Fu2BRm",
|
||||
vmovsd_2 = "rx/oq:F20Fu10rM|xr/qo:F20Fu11Rm",
|
||||
vmovsd_3 = "rrro:F20FV10rM",
|
||||
vmovshdup_2 = "rmoy:F30Fu16rM",
|
||||
vmovsldup_2 = "rmoy:F30Fu12rM",
|
||||
vmovss_2 = "rx/od:F30Fu10rM|xr/do:F30Fu11Rm",
|
||||
vmovss_3 = "rrro:F30FV10rM",
|
||||
vmovupd_2 = "rmoy:660Fu10rM|mroy:660Fu11Rm",
|
||||
vmovups_2 = "rmoy:0Fu10rM|mroy:0Fu11Rm",
|
||||
vorpd_3 = "rrmoy:660FV56rM",
|
||||
vorps_3 = "rrmoy:0FV56rM",
|
||||
vpermilpd_3 = "rrmoy:660F38V0DrM|rmioy:660F3Au05rMU",
|
||||
vpermilps_3 = "rrmoy:660F38V0CrM|rmioy:660F3Au04rMU",
|
||||
vperm2f128_4 = "rrmiy:660F3AV06rMU",
|
||||
vptestpd_2 = "rmoy:660F38u0FrM",
|
||||
vptestps_2 = "rmoy:660F38u0ErM",
|
||||
vrcpps_2 = "rmoy:0Fu53rM",
|
||||
vrcpss_3 = "rrro:F30FV53rM|rrx/ood:",
|
||||
vrsqrtps_2 = "rmoy:0Fu52rM",
|
||||
vrsqrtss_3 = "rrro:F30FV52rM|rrx/ood:",
|
||||
vroundpd_3 = "rmioy:660F3AV09rMU",
|
||||
vroundps_3 = "rmioy:660F3AV08rMU",
|
||||
vroundsd_4 = "rrrio:660F3AV0BrMU|rrxi/ooq:",
|
||||
vroundss_4 = "rrrio:660F3AV0ArMU|rrxi/ood:",
|
||||
vshufpd_4 = "rrmioy:660FVC6rMU",
|
||||
vshufps_4 = "rrmioy:0FVC6rMU",
|
||||
vsqrtps_2 = "rmoy:0Fu51rM",
|
||||
vsqrtss_2 = "rro:F30Fu51rM|rx/od:",
|
||||
vsqrtpd_2 = "rmoy:660Fu51rM",
|
||||
vsqrtsd_2 = "rro:F20Fu51rM|rx/oq:",
|
||||
vstmxcsr_1 = "xd:0FuAE3m",
|
||||
vucomisd_2 = "rro:660Fu2ErM|rx/oq:",
|
||||
vucomiss_2 = "rro:0Fu2ErM|rx/od:",
|
||||
vunpckhpd_3 = "rrmoy:660FV15rM",
|
||||
vunpckhps_3 = "rrmoy:0FV15rM",
|
||||
vunpcklpd_3 = "rrmoy:660FV14rM",
|
||||
vunpcklps_3 = "rrmoy:0FV14rM",
|
||||
vxorpd_3 = "rrmoy:660FV57rM",
|
||||
vxorps_3 = "rrmoy:0FV57rM",
|
||||
vzeroall_0 = "0FuL77",
|
||||
vzeroupper_0 = "0Fu77",
|
||||
|
||||
-- AVX2 FP ops
|
||||
vbroadcastss_2 = "rx/od:660F38u18rM|rx/yd:|rro:|rr/yo:",
|
||||
vbroadcastsd_2 = "rx/yq:660F38u19rM|rr/yo:",
|
||||
-- *vgather* (!vsib)
|
||||
vpermpd_3 = "rmiy:660F3AuX01rMU",
|
||||
vpermps_3 = "rrmy:660F38V16rM",
|
||||
|
||||
-- AVX, AVX2 integer ops
|
||||
-- In general, xmm requires AVX, ymm requires AVX2.
|
||||
vaesdec_3 = "rrmo:660F38VDErM",
|
||||
vaesdeclast_3 = "rrmo:660F38VDFrM",
|
||||
vaesenc_3 = "rrmo:660F38VDCrM",
|
||||
vaesenclast_3 = "rrmo:660F38VDDrM",
|
||||
vaesimc_2 = "rmo:660F38uDBrM",
|
||||
vaeskeygenassist_3 = "rmio:660F3AuDFrMU",
|
||||
vlddqu_2 = "rxoy:F20FuF0rM",
|
||||
vmaskmovdqu_2 = "rro:660FuF7rM",
|
||||
vmovdqa_2 = "rmoy:660Fu6FrM|mroy:660Fu7FRm",
|
||||
vmovdqu_2 = "rmoy:F30Fu6FrM|mroy:F30Fu7FRm",
|
||||
vmovntdq_2 = "xroy:660FuE7Rm",
|
||||
vmovntdqa_2 = "rxoy:660F38u2ArM",
|
||||
vmpsadbw_4 = "rrmioy:660F3AV42rMU",
|
||||
vpabsb_2 = "rmoy:660F38u1CrM",
|
||||
vpabsd_2 = "rmoy:660F38u1ErM",
|
||||
vpabsw_2 = "rmoy:660F38u1DrM",
|
||||
vpackusdw_3 = "rrmoy:660F38V2BrM",
|
||||
vpalignr_4 = "rrmioy:660F3AV0FrMU",
|
||||
vpblendvb_4 = "rrmroy:660F3AV4CrMs",
|
||||
vpblendw_4 = "rrmioy:660F3AV0ErMU",
|
||||
vpclmulqdq_4 = "rrmio:660F3AV44rMU",
|
||||
vpcmpeqq_3 = "rrmoy:660F38V29rM",
|
||||
vpcmpestri_3 = "rmio:660F3Au61rMU",
|
||||
vpcmpestrm_3 = "rmio:660F3Au60rMU",
|
||||
vpcmpgtq_3 = "rrmoy:660F38V37rM",
|
||||
vpcmpistri_3 = "rmio:660F3Au63rMU",
|
||||
vpcmpistrm_3 = "rmio:660F3Au62rMU",
|
||||
vpextrb_3 = "rri/do:660F3Au14nRmU|rri/qo:|xri/bo:",
|
||||
vpextrw_3 = "rri/do:660FuC5rMU|xri/wo:660F3Au15nRmU",
|
||||
vpextrd_3 = "mri/do:660F3Au16RmU",
|
||||
vpextrq_3 = "mri/qo:660F3Au16RmU",
|
||||
vphaddw_3 = "rrmoy:660F38V01rM",
|
||||
vphaddd_3 = "rrmoy:660F38V02rM",
|
||||
vphaddsw_3 = "rrmoy:660F38V03rM",
|
||||
vphminposuw_2 = "rmo:660F38u41rM",
|
||||
vphsubw_3 = "rrmoy:660F38V05rM",
|
||||
vphsubd_3 = "rrmoy:660F38V06rM",
|
||||
vphsubsw_3 = "rrmoy:660F38V07rM",
|
||||
vpinsrb_4 = "rrri/ood:660F3AV20rMU|rrxi/oob:",
|
||||
vpinsrw_4 = "rrri/ood:660FVC4rMU|rrxi/oow:",
|
||||
vpinsrd_4 = "rrmi/ood:660F3AV22rMU",
|
||||
vpinsrq_4 = "rrmi/ooq:660F3AVX22rMU",
|
||||
vpmaddubsw_3 = "rrmoy:660F38V04rM",
|
||||
vpmaxsb_3 = "rrmoy:660F38V3CrM",
|
||||
vpmaxsd_3 = "rrmoy:660F38V3DrM",
|
||||
vpmaxuw_3 = "rrmoy:660F38V3ErM",
|
||||
vpmaxud_3 = "rrmoy:660F38V3FrM",
|
||||
vpminsb_3 = "rrmoy:660F38V38rM",
|
||||
vpminsd_3 = "rrmoy:660F38V39rM",
|
||||
vpminuw_3 = "rrmoy:660F38V3ArM",
|
||||
vpminud_3 = "rrmoy:660F38V3BrM",
|
||||
vpmovmskb_2 = "rr/do:660FuD7rM|rr/dy:660FuLD7rM",
|
||||
vpmovsxbw_2 = "rroy:660F38u20rM|rx/oq:|rx/yo:",
|
||||
vpmovsxbd_2 = "rroy:660F38u21rM|rx/od:|rx/yq:",
|
||||
vpmovsxbq_2 = "rroy:660F38u22rM|rx/ow:|rx/yd:",
|
||||
vpmovsxwd_2 = "rroy:660F38u23rM|rx/oq:|rx/yo:",
|
||||
vpmovsxwq_2 = "rroy:660F38u24rM|rx/od:|rx/yq:",
|
||||
vpmovsxdq_2 = "rroy:660F38u25rM|rx/oq:|rx/yo:",
|
||||
vpmovzxbw_2 = "rroy:660F38u30rM|rx/oq:|rx/yo:",
|
||||
vpmovzxbd_2 = "rroy:660F38u31rM|rx/od:|rx/yq:",
|
||||
vpmovzxbq_2 = "rroy:660F38u32rM|rx/ow:|rx/yd:",
|
||||
vpmovzxwd_2 = "rroy:660F38u33rM|rx/oq:|rx/yo:",
|
||||
vpmovzxwq_2 = "rroy:660F38u34rM|rx/od:|rx/yq:",
|
||||
vpmovzxdq_2 = "rroy:660F38u35rM|rx/oq:|rx/yo:",
|
||||
vpmuldq_3 = "rrmoy:660F38V28rM",
|
||||
vpmulhrsw_3 = "rrmoy:660F38V0BrM",
|
||||
vpmulld_3 = "rrmoy:660F38V40rM",
|
||||
vpshufb_3 = "rrmoy:660F38V00rM",
|
||||
vpshufd_3 = "rmioy:660Fu70rMU",
|
||||
vpshufhw_3 = "rmioy:F30Fu70rMU",
|
||||
vpshuflw_3 = "rmioy:F20Fu70rMU",
|
||||
vpsignb_3 = "rrmoy:660F38V08rM",
|
||||
vpsignw_3 = "rrmoy:660F38V09rM",
|
||||
vpsignd_3 = "rrmoy:660F38V0ArM",
|
||||
vpslldq_3 = "rrioy:660Fv737mU",
|
||||
vpsllw_3 = "rrmoy:660FVF1rM|rrioy:660Fv716mU",
|
||||
vpslld_3 = "rrmoy:660FVF2rM|rrioy:660Fv726mU",
|
||||
vpsllq_3 = "rrmoy:660FVF3rM|rrioy:660Fv736mU",
|
||||
vpsraw_3 = "rrmoy:660FVE1rM|rrioy:660Fv714mU",
|
||||
vpsrad_3 = "rrmoy:660FVE2rM|rrioy:660Fv724mU",
|
||||
vpsrldq_3 = "rrioy:660Fv733mU",
|
||||
vpsrlw_3 = "rrmoy:660FVD1rM|rrioy:660Fv712mU",
|
||||
vpsrld_3 = "rrmoy:660FVD2rM|rrioy:660Fv722mU",
|
||||
vpsrlq_3 = "rrmoy:660FVD3rM|rrioy:660Fv732mU",
|
||||
vptest_2 = "rmoy:660F38u17rM",
|
||||
|
||||
-- AVX2 integer ops
|
||||
vbroadcasti128_2 = "rx/yo:660F38u5ArM",
|
||||
vinserti128_4 = "rrmi/yyo:660F3AV38rMU",
|
||||
vextracti128_3 = "mri/oy:660F3AuL39RmU",
|
||||
vpblendd_4 = "rrmioy:660F3AV02rMU",
|
||||
vpbroadcastb_2 = "rro:660F38u78rM|rx/ob:|rr/yo:|rx/yb:",
|
||||
vpbroadcastw_2 = "rro:660F38u79rM|rx/ow:|rr/yo:|rx/yw:",
|
||||
vpbroadcastd_2 = "rro:660F38u58rM|rx/od:|rr/yo:|rx/yd:",
|
||||
vpbroadcastq_2 = "rro:660F38u59rM|rx/oq:|rr/yo:|rx/yq:",
|
||||
vpermd_3 = "rrmy:660F38V36rM",
|
||||
vpermq_3 = "rmiy:660F3AuX00rMU",
|
||||
-- *vpgather* (!vsib)
|
||||
vperm2i128_4 = "rrmiy:660F3AV46rMU",
|
||||
vpmaskmovd_3 = "rrxoy:660F38V8CrM|xrroy:660F38V8ERm",
|
||||
vpmaskmovq_3 = "rrxoy:660F38VX8CrM|xrroy:660F38VX8ERm",
|
||||
vpsllvd_3 = "rrmoy:660F38V47rM",
|
||||
vpsllvq_3 = "rrmoy:660F38VX47rM",
|
||||
vpsravd_3 = "rrmoy:660F38V46rM",
|
||||
vpsrlvd_3 = "rrmoy:660F38V45rM",
|
||||
vpsrlvq_3 = "rrmoy:660F38VX45rM",
|
||||
|
||||
-- Intel ADX
|
||||
adcx_2 = "rmqd:660F38F6rM",
|
||||
adox_2 = "rmqd:F30F38F6rM",
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
@ -1462,28 +1727,58 @@ for cc,n in pairs{ b=0, e=1, be=2, u=3, nb=4, ne=5, nbe=6, nu=7 } do
|
|||
map_op["fcmov"..cc.."_2"] = format("Fff:%04XR", nc) -- P6+
|
||||
end
|
||||
|
||||
-- SSE FP arithmetic ops.
|
||||
-- SSE / AVX FP arithmetic ops.
|
||||
for name,n in pairs{ sqrt = 1, add = 8, mul = 9,
|
||||
sub = 12, min = 13, div = 14, max = 15 } do
|
||||
map_op[name.."ps_2"] = format("rmo:0F5%XrM", n)
|
||||
map_op[name.."ss_2"] = format("rro:F30F5%XrM|rx/od:", n)
|
||||
map_op[name.."pd_2"] = format("rmo:660F5%XrM", n)
|
||||
map_op[name.."sd_2"] = format("rro:F20F5%XrM|rx/oq:", n)
|
||||
if n ~= 1 then
|
||||
map_op["v"..name.."ps_3"] = format("rrmoy:0FV5%XrM", n)
|
||||
map_op["v"..name.."ss_3"] = format("rrro:F30FV5%XrM|rrx/ood:", n)
|
||||
map_op["v"..name.."pd_3"] = format("rrmoy:660FV5%XrM", n)
|
||||
map_op["v"..name.."sd_3"] = format("rrro:F20FV5%XrM|rrx/ooq:", n)
|
||||
end
|
||||
end
|
||||
|
||||
-- SSE2 / AVX / AVX2 integer arithmetic ops (66 0F leaf).
|
||||
for name,n in pairs{
|
||||
paddb = 0xFC, paddw = 0xFD, paddd = 0xFE, paddq = 0xD4,
|
||||
paddsb = 0xEC, paddsw = 0xED, packssdw = 0x6B,
|
||||
packsswb = 0x63, packuswb = 0x67, paddusb = 0xDC,
|
||||
paddusw = 0xDD, pand = 0xDB, pandn = 0xDF, pavgb = 0xE0,
|
||||
pavgw = 0xE3, pcmpeqb = 0x74, pcmpeqd = 0x76,
|
||||
pcmpeqw = 0x75, pcmpgtb = 0x64, pcmpgtd = 0x66,
|
||||
pcmpgtw = 0x65, pmaddwd = 0xF5, pmaxsw = 0xEE,
|
||||
pmaxub = 0xDE, pminsw = 0xEA, pminub = 0xDA,
|
||||
pmulhuw = 0xE4, pmulhw = 0xE5, pmullw = 0xD5,
|
||||
pmuludq = 0xF4, por = 0xEB, psadbw = 0xF6, psubb = 0xF8,
|
||||
psubw = 0xF9, psubd = 0xFA, psubq = 0xFB, psubsb = 0xE8,
|
||||
psubsw = 0xE9, psubusb = 0xD8, psubusw = 0xD9,
|
||||
punpckhbw = 0x68, punpckhwd = 0x69, punpckhdq = 0x6A,
|
||||
punpckhqdq = 0x6D, punpcklbw = 0x60, punpcklwd = 0x61,
|
||||
punpckldq = 0x62, punpcklqdq = 0x6C, pxor = 0xEF
|
||||
} do
|
||||
map_op[name.."_2"] = format("rmo:660F%02XrM", n)
|
||||
map_op["v"..name.."_3"] = format("rrmoy:660FV%02XrM", n)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local map_vexarg = { u = false, v = 1, V = 2 }
|
||||
|
||||
-- Process pattern string.
|
||||
local function dopattern(pat, args, sz, op, needrex)
|
||||
local digit, addin
|
||||
local digit, addin, vex
|
||||
local opcode = 0
|
||||
local szov = sz
|
||||
local narg = 1
|
||||
local rex = 0
|
||||
|
||||
-- Limit number of section buffer positions used by a single dasm_put().
|
||||
-- A single opcode needs a maximum of 5 positions.
|
||||
if secpos+5 > maxsecpos then wflush() end
|
||||
-- A single opcode needs a maximum of 6 positions.
|
||||
if secpos+6 > maxsecpos then wflush() end
|
||||
|
||||
-- Process each character.
|
||||
for c in gmatch(pat.."|", ".") do
|
||||
|
@ -1497,6 +1792,8 @@ local function dopattern(pat, args, sz, op, needrex)
|
|||
szov = nil
|
||||
elseif c == "X" then -- Force REX.W.
|
||||
rex = 8
|
||||
elseif c == "L" then -- Force VEX.L.
|
||||
vex.l = true
|
||||
elseif c == "r" then -- Merge 1st operand regno. into opcode.
|
||||
addin = args[1]; opcode = opcode + (addin.reg % 8)
|
||||
if narg < 2 then narg = 2 end
|
||||
|
@ -1520,21 +1817,42 @@ local function dopattern(pat, args, sz, op, needrex)
|
|||
if t.xreg and t.xreg > 7 then rex = rex + 2 end
|
||||
if s > 7 then rex = rex + 4 end
|
||||
if needrex then rex = rex + 16 end
|
||||
wputop(szov, opcode, rex); opcode = nil
|
||||
local psz, sk = wputop(szov, opcode, rex, vex, s < 0, t.vreg or t.vxreg)
|
||||
opcode = nil
|
||||
local imark = sub(pat, -1) -- Force a mark (ugly).
|
||||
-- Put ModRM/SIB with regno/last digit as spare.
|
||||
wputmrmsib(t, imark, s, addin and addin.vreg)
|
||||
wputmrmsib(t, imark, s, addin and addin.vreg, psz, sk)
|
||||
addin = nil
|
||||
elseif map_vexarg[c] ~= nil then -- Encode using VEX prefix
|
||||
local b = band(opcode, 255); opcode = shr(opcode, 8)
|
||||
local m = 1
|
||||
if b == 0x38 then m = 2
|
||||
elseif b == 0x3a then m = 3 end
|
||||
if m ~= 1 then b = band(opcode, 255); opcode = shr(opcode, 8) end
|
||||
if b ~= 0x0f then
|
||||
werror("expected `0F', `0F38', or `0F3A' to precede `"..c..
|
||||
"' in pattern `"..pat.."' for `"..op.."'")
|
||||
end
|
||||
local v = map_vexarg[c]
|
||||
if v then v = remove(args, v) end
|
||||
b = band(opcode, 255)
|
||||
local p = 0
|
||||
if b == 0x66 then p = 1
|
||||
elseif b == 0xf3 then p = 2
|
||||
elseif b == 0xf2 then p = 3 end
|
||||
if p ~= 0 then opcode = shr(opcode, 8) end
|
||||
if opcode ~= 0 then wputop(nil, opcode, 0); opcode = 0 end
|
||||
vex = { m = m, p = p, v = v }
|
||||
else
|
||||
if opcode then -- Flush opcode.
|
||||
if szov == "q" and rex == 0 then rex = rex + 8 end
|
||||
if needrex then rex = rex + 16 end
|
||||
if addin and addin.reg == -1 then
|
||||
wputop(szov, opcode - 7, rex)
|
||||
waction("VREG", addin.vreg); wputxb(0)
|
||||
local psz, sk = wputop(szov, opcode - 7, rex, vex, true)
|
||||
wvreg("opcode", addin.vreg, psz, sk)
|
||||
else
|
||||
if addin and addin.reg > 7 then rex = rex + 1 end
|
||||
wputop(szov, opcode, rex)
|
||||
wputop(szov, opcode, rex, vex)
|
||||
end
|
||||
opcode = nil
|
||||
end
|
||||
|
@ -1571,6 +1889,14 @@ local function dopattern(pat, args, sz, op, needrex)
|
|||
else
|
||||
wputlabel("REL_", imm, 2)
|
||||
end
|
||||
elseif c == "s" then
|
||||
local reg = a.reg
|
||||
if reg < 0 then
|
||||
wputb(0)
|
||||
wvreg("imm.hi", a.vreg)
|
||||
else
|
||||
wputb(shl(reg, 4))
|
||||
end
|
||||
else
|
||||
werror("bad char `"..c.."' in pattern `"..pat.."' for `"..op.."'")
|
||||
end
|
||||
|
@ -1647,11 +1973,14 @@ map_op[".template__"] = function(params, template, nparams)
|
|||
if pat == "" then pat = lastpat else lastpat = pat end
|
||||
if matchtm(tm, args) then
|
||||
local prefix = sub(szm, 1, 1)
|
||||
if prefix == "/" then -- Match both operand sizes.
|
||||
if args[1].opsize == sub(szm, 2, 2) and
|
||||
args[2].opsize == sub(szm, 3, 3) then
|
||||
dopattern(pat, args, sz, params.op, needrex) -- Process pattern.
|
||||
return
|
||||
if prefix == "/" then -- Exactly match leading operand sizes.
|
||||
for i = #szm,1,-1 do
|
||||
if i == 1 then
|
||||
dopattern(pat, args, sz, params.op, needrex) -- Process pattern.
|
||||
return
|
||||
elseif args[i-1].opsize ~= sub(szm, i, i) then
|
||||
break
|
||||
end
|
||||
end
|
||||
else -- Match common operand size.
|
||||
local szp = sz
|
||||
|
@ -1716,8 +2045,8 @@ if x64 then
|
|||
rex = a.reg > 7 and 9 or 8
|
||||
end
|
||||
end
|
||||
wputop(sz, opcode, rex)
|
||||
if vreg then waction("VREG", vreg); wputxb(0) end
|
||||
local psz, sk = wputop(sz, opcode, rex, nil, vreg)
|
||||
wvreg("opcode", vreg, psz, sk)
|
||||
waction("IMM_D", format("(unsigned int)(%s)", op64))
|
||||
waction("IMM_D", format("(unsigned int)((%s)>>32)", op64))
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
-- DynASM. A dynamic assembler for code generation engines.
|
||||
-- Originally designed and implemented for LuaJIT.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- See below for full copyright notice.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
@ -10,14 +10,14 @@
|
|||
local _info = {
|
||||
name = "DynASM",
|
||||
description = "A dynamic assembler for code generation engines",
|
||||
version = "1.3.0",
|
||||
vernum = 10300,
|
||||
release = "2011-05-05",
|
||||
version = "1.4.0",
|
||||
vernum = 10400,
|
||||
release = "2015-10-18",
|
||||
author = "Mike Pall",
|
||||
url = "http://luajit.org/dynasm.html",
|
||||
license = "MIT",
|
||||
copyright = [[
|
||||
Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
.TH luajit 1 "" "" "LuaJIT documentation"
|
||||
.SH NAME
|
||||
luajit \- Just-In-Time Compiler for the Lua Language
|
||||
\fB
|
||||
.SH SYNOPSIS
|
||||
.B luajit
|
||||
[\fIoptions\fR]... [\fIscript\fR [\fIargs\fR]...]
|
||||
.SH "WEB SITE"
|
||||
.IR http://luajit.org
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
This is the command-line program to run Lua programs with \fBLuaJIT\fR.
|
||||
.PP
|
||||
\fBLuaJIT\fR is a just-in-time (JIT) compiler for the Lua language.
|
||||
The virtual machine (VM) is based on a fast interpreter combined with
|
||||
a trace compiler. It can significantly improve the performance of Lua programs.
|
||||
.PP
|
||||
\fBLuaJIT\fR is API\- and ABI-compatible with the VM of the standard
|
||||
Lua\ 5.1 interpreter. When embedding the VM into an application,
|
||||
the built library can be used as a drop-in replacement.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BI "\-e " chunk
|
||||
Run the given chunk of Lua code.
|
||||
.TP
|
||||
.BI "\-l " library
|
||||
Load the named library, just like \fBrequire("\fR\fIlibrary\fR\fB")\fR.
|
||||
.TP
|
||||
.BI "\-b " ...
|
||||
Save or list bytecode. Run without arguments to get help on options.
|
||||
.TP
|
||||
.BI "\-j " command
|
||||
Perform LuaJIT control command (optional space after \fB\-j\fR).
|
||||
.TP
|
||||
.BI "\-O" [opt]
|
||||
Control LuaJIT optimizations.
|
||||
.TP
|
||||
.B "\-i"
|
||||
Run in interactive mode.
|
||||
.TP
|
||||
.B "\-v"
|
||||
Show \fBLuaJIT\fR version.
|
||||
.TP
|
||||
.B "\-E"
|
||||
Ignore environment variables.
|
||||
.TP
|
||||
.B "\-\-"
|
||||
Stop processing options.
|
||||
.TP
|
||||
.B "\-"
|
||||
Read script from stdin instead.
|
||||
.PP
|
||||
After all options are processed, the given \fIscript\fR is run.
|
||||
The arguments are passed in the global \fIarg\fR table.
|
||||
.PP
|
||||
Interactive mode is only entered, if no \fIscript\fR and no \fB\-e\fR
|
||||
option is given. Interactive mode can be left with EOF (\fICtrl\-Z\fB).
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
luajit hello.lua world
|
||||
|
||||
Prints "Hello world", assuming \fIhello.lua\fR contains:
|
||||
.br
|
||||
print("Hello", arg[1])
|
||||
.TP
|
||||
luajit \-e "local x=0; for i=1,1e9 do x=x+i end; print(x)"
|
||||
|
||||
Calculates the sum of the numbers from 1 to 1000000000.
|
||||
.br
|
||||
And finishes in a reasonable amount of time, too.
|
||||
.TP
|
||||
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.
|
||||
.SH COPYRIGHT
|
||||
.PP
|
||||
\fBLuaJIT\fR is Copyright \(co 2005-2017 Mike Pall.
|
||||
.br
|
||||
\fBLuaJIT\fR is open source software, released under the MIT license.
|
||||
.SH SEE ALSO
|
||||
.PP
|
||||
More details in the provided HTML docs or at:
|
||||
.IR http://luajit.org
|
||||
.br
|
||||
More about the Lua language can be found at:
|
||||
.IR http://lua.org/docs.html
|
||||
.PP
|
||||
lua(1)
|
|
@ -0,0 +1,25 @@
|
|||
# Package information for LuaJIT to be used by pkg-config.
|
||||
majver=2
|
||||
minver=1
|
||||
relver=0
|
||||
version=${majver}.${minver}.${relver}-beta3
|
||||
abiver=5.1
|
||||
|
||||
prefix=/usr/local
|
||||
multilib=lib
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/${multilib}
|
||||
libname=luajit-${abiver}
|
||||
includedir=${prefix}/include/luajit-${majver}.${minver}
|
||||
|
||||
INSTALL_LMOD=${prefix}/share/lua/${abiver}
|
||||
INSTALL_CMOD=${prefix}/${multilib}/lua/${abiver}
|
||||
|
||||
Name: LuaJIT
|
||||
Description: Just-in-time compiler for Lua
|
||||
URL: http://luajit.org
|
||||
Version: ${version}
|
||||
Requires:
|
||||
Libs: -L${libdir} -l${libname}
|
||||
Libs.private: -Wl,-E -lm -ldl
|
||||
Cflags: -I${includedir}
|
|
@ -1,167 +0,0 @@
|
|||
/*
|
||||
** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||
** Auxiliary functions for building Lua libraries
|
||||
** See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
|
||||
#ifndef lauxlib_h
|
||||
#define lauxlib_h
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
|
||||
#define luaL_getn(L,i) ((int)lua_objlen(L, i))
|
||||
#define luaL_setn(L,i,j) ((void)0) /* no op! */
|
||||
|
||||
/* extra error code for `luaL_load' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
typedef struct luaL_Reg {
|
||||
const char *name;
|
||||
lua_CFunction func;
|
||||
} luaL_Reg;
|
||||
|
||||
LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l, int nup);
|
||||
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
|
||||
const luaL_Reg *l);
|
||||
LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);
|
||||
LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);
|
||||
LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);
|
||||
LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,
|
||||
size_t *l);
|
||||
LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,
|
||||
const char *def, size_t *l);
|
||||
LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);
|
||||
|
||||
LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);
|
||||
LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,
|
||||
lua_Integer def);
|
||||
|
||||
LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);
|
||||
LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);
|
||||
LUALIB_API void (luaL_checkany) (lua_State *L, int narg);
|
||||
|
||||
LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname);
|
||||
LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);
|
||||
|
||||
LUALIB_API void (luaL_where) (lua_State *L, int lvl);
|
||||
LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
|
||||
|
||||
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
|
||||
const char *const lst[]);
|
||||
|
||||
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||
|
||||
LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);
|
||||
LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name);
|
||||
LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);
|
||||
|
||||
LUALIB_API lua_State *(luaL_newstate) (void);
|
||||
|
||||
|
||||
LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,
|
||||
const char *r);
|
||||
|
||||
LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,
|
||||
const char *fname, int szhint);
|
||||
|
||||
/* From Lua 5.2. */
|
||||
LUALIB_API int luaL_fileresult(lua_State *L, int stat, const char *fname);
|
||||
LUALIB_API int luaL_execresult(lua_State *L, int stat);
|
||||
LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename,
|
||||
const char *mode);
|
||||
LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
||||
const char *name, const char *mode);
|
||||
LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
|
||||
int level);
|
||||
|
||||
|
||||
/*
|
||||
** ===============================================================
|
||||
** some useful macros
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
#define luaL_argcheck(L, cond,numarg,extramsg) \
|
||||
((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))
|
||||
#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL))
|
||||
#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL))
|
||||
#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
|
||||
#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n)))
|
||||
#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d)))
|
||||
|
||||
#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i)))
|
||||
|
||||
#define luaL_dofile(L, fn) \
|
||||
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_dostring(L, s) \
|
||||
(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))
|
||||
|
||||
#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n)))
|
||||
|
||||
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
** =======================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
typedef struct luaL_Buffer {
|
||||
char *p; /* current position in buffer */
|
||||
int lvl; /* number of strings in the stack (level) */
|
||||
lua_State *L;
|
||||
char buffer[LUAL_BUFFERSIZE];
|
||||
} luaL_Buffer;
|
||||
|
||||
#define luaL_addchar(B,c) \
|
||||
((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \
|
||||
(*(B)->p++ = (char)(c)))
|
||||
|
||||
/* compatibility only */
|
||||
#define luaL_putchar(B,c) luaL_addchar(B,c)
|
||||
|
||||
#define luaL_addsize(B,n) ((B)->p += (n))
|
||||
|
||||
LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);
|
||||
LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);
|
||||
LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);
|
||||
LUALIB_API void (luaL_addvalue) (luaL_Buffer *B);
|
||||
LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
|
||||
|
||||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
/* compatibility with ref system */
|
||||
|
||||
/* pre-defined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
|
||||
(lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
|
||||
|
||||
#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
|
||||
|
||||
#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
|
||||
|
||||
|
||||
#define luaL_reg luaL_Reg
|
||||
|
||||
#endif
|
|
@ -1,393 +0,0 @@
|
|||
/*
|
||||
** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $
|
||||
** Lua - An Extensible Extension Language
|
||||
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
|
||||
** See Copyright Notice at the end of this file
|
||||
*/
|
||||
|
||||
|
||||
#ifndef lua_h
|
||||
#define lua_h
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#include "luaconf.h"
|
||||
|
||||
|
||||
#define LUA_VERSION "Lua 5.1"
|
||||
#define LUA_RELEASE "Lua 5.1.4"
|
||||
#define LUA_VERSION_NUM 501
|
||||
#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio"
|
||||
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
|
||||
|
||||
|
||||
/* mark for precompiled code (`<esc>Lua') */
|
||||
#define LUA_SIGNATURE "\033Lua"
|
||||
|
||||
/* option for multiple returns in `lua_pcall' and `lua_call' */
|
||||
#define LUA_MULTRET (-1)
|
||||
|
||||
|
||||
/*
|
||||
** pseudo-indices
|
||||
*/
|
||||
#define LUA_REGISTRYINDEX (-10000)
|
||||
#define LUA_ENVIRONINDEX (-10001)
|
||||
#define LUA_GLOBALSINDEX (-10002)
|
||||
#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i))
|
||||
|
||||
|
||||
/* thread status; 0 is OK */
|
||||
#define LUA_YIELD 1
|
||||
#define LUA_ERRRUN 2
|
||||
#define LUA_ERRSYNTAX 3
|
||||
#define LUA_ERRMEM 4
|
||||
#define LUA_ERRERR 5
|
||||
|
||||
|
||||
typedef struct lua_State lua_State;
|
||||
|
||||
typedef int (*lua_CFunction) (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** functions that read/write blocks when loading/dumping Lua chunks
|
||||
*/
|
||||
typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);
|
||||
|
||||
typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);
|
||||
|
||||
|
||||
/*
|
||||
** prototype for memory-allocation functions
|
||||
*/
|
||||
typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);
|
||||
|
||||
|
||||
/*
|
||||
** basic types
|
||||
*/
|
||||
#define LUA_TNONE (-1)
|
||||
|
||||
#define LUA_TNIL 0
|
||||
#define LUA_TBOOLEAN 1
|
||||
#define LUA_TLIGHTUSERDATA 2
|
||||
#define LUA_TNUMBER 3
|
||||
#define LUA_TSTRING 4
|
||||
#define LUA_TTABLE 5
|
||||
#define LUA_TFUNCTION 6
|
||||
#define LUA_TUSERDATA 7
|
||||
#define LUA_TTHREAD 8
|
||||
|
||||
|
||||
|
||||
/* minimum Lua stack available to a C function */
|
||||
#define LUA_MINSTACK 20
|
||||
|
||||
|
||||
/*
|
||||
** generic extra include file
|
||||
*/
|
||||
#if defined(LUA_USER_H)
|
||||
#include LUA_USER_H
|
||||
#endif
|
||||
|
||||
|
||||
/* type of numbers in Lua */
|
||||
typedef LUA_NUMBER lua_Number;
|
||||
|
||||
|
||||
/* type for integer functions */
|
||||
typedef LUA_INTEGER lua_Integer;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** state manipulation
|
||||
*/
|
||||
LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);
|
||||
LUA_API void (lua_close) (lua_State *L);
|
||||
LUA_API lua_State *(lua_newthread) (lua_State *L);
|
||||
|
||||
LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
|
||||
|
||||
|
||||
/*
|
||||
** basic stack manipulation
|
||||
*/
|
||||
LUA_API int (lua_gettop) (lua_State *L);
|
||||
LUA_API void (lua_settop) (lua_State *L, int idx);
|
||||
LUA_API void (lua_pushvalue) (lua_State *L, int idx);
|
||||
LUA_API void (lua_remove) (lua_State *L, int idx);
|
||||
LUA_API void (lua_insert) (lua_State *L, int idx);
|
||||
LUA_API void (lua_replace) (lua_State *L, int idx);
|
||||
LUA_API int (lua_checkstack) (lua_State *L, int sz);
|
||||
|
||||
LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n);
|
||||
|
||||
|
||||
/*
|
||||
** access functions (stack -> C)
|
||||
*/
|
||||
|
||||
LUA_API int (lua_isnumber) (lua_State *L, int idx);
|
||||
LUA_API int (lua_isstring) (lua_State *L, int idx);
|
||||
LUA_API int (lua_iscfunction) (lua_State *L, int idx);
|
||||
LUA_API int (lua_isuserdata) (lua_State *L, int idx);
|
||||
LUA_API int (lua_type) (lua_State *L, int idx);
|
||||
LUA_API const char *(lua_typename) (lua_State *L, int tp);
|
||||
|
||||
LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2);
|
||||
LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2);
|
||||
|
||||
LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx);
|
||||
LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx);
|
||||
LUA_API int (lua_toboolean) (lua_State *L, int idx);
|
||||
LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len);
|
||||
LUA_API size_t (lua_objlen) (lua_State *L, int idx);
|
||||
LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx);
|
||||
LUA_API void *(lua_touserdata) (lua_State *L, int idx);
|
||||
LUA_API lua_State *(lua_tothread) (lua_State *L, int idx);
|
||||
LUA_API const void *(lua_topointer) (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
** push functions (C -> stack)
|
||||
*/
|
||||
LUA_API void (lua_pushnil) (lua_State *L);
|
||||
LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n);
|
||||
LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n);
|
||||
LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l);
|
||||
LUA_API void (lua_pushstring) (lua_State *L, const char *s);
|
||||
LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,
|
||||
va_list argp);
|
||||
LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);
|
||||
LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);
|
||||
LUA_API void (lua_pushboolean) (lua_State *L, int b);
|
||||
LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p);
|
||||
LUA_API int (lua_pushthread) (lua_State *L);
|
||||
|
||||
|
||||
/*
|
||||
** get functions (Lua -> stack)
|
||||
*/
|
||||
LUA_API void (lua_gettable) (lua_State *L, int idx);
|
||||
LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k);
|
||||
LUA_API void (lua_rawget) (lua_State *L, int idx);
|
||||
LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n);
|
||||
LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec);
|
||||
LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);
|
||||
LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
|
||||
LUA_API void (lua_getfenv) (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
** set functions (stack -> Lua)
|
||||
*/
|
||||
LUA_API void (lua_settable) (lua_State *L, int idx);
|
||||
LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k);
|
||||
LUA_API void (lua_rawset) (lua_State *L, int idx);
|
||||
LUA_API void (lua_rawseti) (lua_State *L, int idx, int n);
|
||||
LUA_API int (lua_setmetatable) (lua_State *L, int objindex);
|
||||
LUA_API int (lua_setfenv) (lua_State *L, int idx);
|
||||
|
||||
|
||||
/*
|
||||
** `load' and `call' functions (load and run Lua code)
|
||||
*/
|
||||
LUA_API void (lua_call) (lua_State *L, int nargs, int nresults);
|
||||
LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);
|
||||
LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);
|
||||
LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt,
|
||||
const char *chunkname);
|
||||
|
||||
LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);
|
||||
|
||||
|
||||
/*
|
||||
** coroutine functions
|
||||
*/
|
||||
LUA_API int (lua_yield) (lua_State *L, int nresults);
|
||||
LUA_API int (lua_resume) (lua_State *L, int narg);
|
||||
LUA_API int (lua_status) (lua_State *L);
|
||||
|
||||
/*
|
||||
** garbage-collection function and options
|
||||
*/
|
||||
|
||||
#define LUA_GCSTOP 0
|
||||
#define LUA_GCRESTART 1
|
||||
#define LUA_GCCOLLECT 2
|
||||
#define LUA_GCCOUNT 3
|
||||
#define LUA_GCCOUNTB 4
|
||||
#define LUA_GCSTEP 5
|
||||
#define LUA_GCSETPAUSE 6
|
||||
#define LUA_GCSETSTEPMUL 7
|
||||
|
||||
LUA_API int (lua_gc) (lua_State *L, int what, int data);
|
||||
|
||||
|
||||
/*
|
||||
** miscellaneous functions
|
||||
*/
|
||||
|
||||
LUA_API int (lua_error) (lua_State *L);
|
||||
|
||||
LUA_API int (lua_next) (lua_State *L, int idx);
|
||||
|
||||
LUA_API void (lua_concat) (lua_State *L, int n);
|
||||
|
||||
LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
|
||||
LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** ===============================================================
|
||||
** some useful macros
|
||||
** ===============================================================
|
||||
*/
|
||||
|
||||
#define lua_pop(L,n) lua_settop(L, -(n)-1)
|
||||
|
||||
#define lua_newtable(L) lua_createtable(L, 0, 0)
|
||||
|
||||
#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
|
||||
|
||||
#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
|
||||
|
||||
#define lua_strlen(L,i) lua_objlen(L, (i))
|
||||
|
||||
#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION)
|
||||
#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE)
|
||||
#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA)
|
||||
#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL)
|
||||
#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN)
|
||||
#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD)
|
||||
#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE)
|
||||
#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0)
|
||||
|
||||
#define lua_pushliteral(L, s) \
|
||||
lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1)
|
||||
|
||||
#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s))
|
||||
#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s))
|
||||
|
||||
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** compatibility macros and functions
|
||||
*/
|
||||
|
||||
#define lua_open() luaL_newstate()
|
||||
|
||||
#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX)
|
||||
|
||||
#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0)
|
||||
|
||||
#define lua_Chunkreader lua_Reader
|
||||
#define lua_Chunkwriter lua_Writer
|
||||
|
||||
|
||||
/* hack */
|
||||
LUA_API void lua_setlevel (lua_State *from, lua_State *to);
|
||||
|
||||
|
||||
/*
|
||||
** {======================================================================
|
||||
** Debug API
|
||||
** =======================================================================
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
** Event codes
|
||||
*/
|
||||
#define LUA_HOOKCALL 0
|
||||
#define LUA_HOOKRET 1
|
||||
#define LUA_HOOKLINE 2
|
||||
#define LUA_HOOKCOUNT 3
|
||||
#define LUA_HOOKTAILRET 4
|
||||
|
||||
|
||||
/*
|
||||
** Event masks
|
||||
*/
|
||||
#define LUA_MASKCALL (1 << LUA_HOOKCALL)
|
||||
#define LUA_MASKRET (1 << LUA_HOOKRET)
|
||||
#define LUA_MASKLINE (1 << LUA_HOOKLINE)
|
||||
#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT)
|
||||
|
||||
typedef struct lua_Debug lua_Debug; /* activation record */
|
||||
|
||||
|
||||
/* Functions to be called by the debuger in specific events */
|
||||
typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);
|
||||
|
||||
|
||||
LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);
|
||||
LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
|
||||
LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);
|
||||
LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);
|
||||
LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);
|
||||
LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);
|
||||
LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);
|
||||
LUA_API lua_Hook lua_gethook (lua_State *L);
|
||||
LUA_API int lua_gethookmask (lua_State *L);
|
||||
LUA_API int lua_gethookcount (lua_State *L);
|
||||
|
||||
/* From Lua 5.2. */
|
||||
LUA_API void *lua_upvalueid (lua_State *L, int idx, int n);
|
||||
LUA_API void lua_upvaluejoin (lua_State *L, int idx1, int n1, int idx2, int n2);
|
||||
LUA_API int lua_loadx (lua_State *L, lua_Reader reader, void *dt,
|
||||
const char *chunkname, const char *mode);
|
||||
|
||||
|
||||
struct lua_Debug {
|
||||
int event;
|
||||
const char *name; /* (n) */
|
||||
const char *namewhat; /* (n) `global', `local', `field', `method' */
|
||||
const char *what; /* (S) `Lua', `C', `main', `tail' */
|
||||
const char *source; /* (S) */
|
||||
int currentline; /* (l) */
|
||||
int nups; /* (u) number of upvalues */
|
||||
int linedefined; /* (S) */
|
||||
int lastlinedefined; /* (S) */
|
||||
char short_src[LUA_IDSIZE]; /* (S) */
|
||||
/* private part */
|
||||
int i_ci; /* active function */
|
||||
};
|
||||
|
||||
/* }====================================================================== */
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#endif
|
|
@ -1,9 +0,0 @@
|
|||
// C++ wrapper for LuaJIT header files.
|
||||
|
||||
extern "C" {
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
#include "luajit.h"
|
||||
}
|
||||
|
|
@ -1,156 +0,0 @@
|
|||
/*
|
||||
** Configuration header.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef luaconf_h
|
||||
#define luaconf_h
|
||||
|
||||
#ifndef WINVER
|
||||
#define WINVER 0x0501
|
||||
#endif
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Default path for loading Lua and C modules with require(). */
|
||||
#if defined(_WIN32)
|
||||
/*
|
||||
** In Windows, any exclamation mark ('!') in the path is replaced by the
|
||||
** path of the directory of the executable file of the current process.
|
||||
*/
|
||||
#define LUA_LDIR "!\\lua\\"
|
||||
#define LUA_CDIR "!\\"
|
||||
#define LUA_PATH_DEFAULT \
|
||||
".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;"
|
||||
#define LUA_CPATH_DEFAULT \
|
||||
".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll"
|
||||
#else
|
||||
/*
|
||||
** Note to distribution maintainers: do NOT patch the following lines!
|
||||
** Please read ../doc/install.html#distro and pass PREFIX=/usr instead.
|
||||
*/
|
||||
#ifndef LUA_MULTILIB
|
||||
#define LUA_MULTILIB "lib"
|
||||
#endif
|
||||
#ifndef LUA_LMULTILIB
|
||||
#define LUA_LMULTILIB "lib"
|
||||
#endif
|
||||
#define LUA_LROOT "/usr/local"
|
||||
#define LUA_LUADIR "/lua/5.1/"
|
||||
#define LUA_LJDIR "/luajit-2.0.4/"
|
||||
|
||||
#ifdef LUA_ROOT
|
||||
#define LUA_JROOT LUA_ROOT
|
||||
#define LUA_RLDIR LUA_ROOT "/share" LUA_LUADIR
|
||||
#define LUA_RCDIR LUA_ROOT "/" LUA_MULTILIB LUA_LUADIR
|
||||
#define LUA_RLPATH ";" LUA_RLDIR "?.lua;" LUA_RLDIR "?/init.lua"
|
||||
#define LUA_RCPATH ";" LUA_RCDIR "?.so"
|
||||
#else
|
||||
#define LUA_JROOT LUA_LROOT
|
||||
#define LUA_RLPATH
|
||||
#define LUA_RCPATH
|
||||
#endif
|
||||
|
||||
#define LUA_JPATH ";" LUA_JROOT "/share" LUA_LJDIR "?.lua"
|
||||
#define LUA_LLDIR LUA_LROOT "/share" LUA_LUADIR
|
||||
#define LUA_LCDIR LUA_LROOT "/" LUA_LMULTILIB LUA_LUADIR
|
||||
#define LUA_LLPATH ";" LUA_LLDIR "?.lua;" LUA_LLDIR "?/init.lua"
|
||||
#define LUA_LCPATH1 ";" LUA_LCDIR "?.so"
|
||||
#define LUA_LCPATH2 ";" LUA_LCDIR "loadall.so"
|
||||
|
||||
#define LUA_PATH_DEFAULT "./?.lua" LUA_JPATH LUA_LLPATH LUA_RLPATH
|
||||
#define LUA_CPATH_DEFAULT "./?.so" LUA_LCPATH1 LUA_RCPATH LUA_LCPATH2
|
||||
#endif
|
||||
|
||||
/* Environment variable names for path overrides and initialization code. */
|
||||
#define LUA_PATH "LUA_PATH"
|
||||
#define LUA_CPATH "LUA_CPATH"
|
||||
#define LUA_INIT "LUA_INIT"
|
||||
|
||||
/* Special file system characters. */
|
||||
#if defined(_WIN32)
|
||||
#define LUA_DIRSEP "\\"
|
||||
#else
|
||||
#define LUA_DIRSEP "/"
|
||||
#endif
|
||||
#define LUA_PATHSEP ";"
|
||||
#define LUA_PATH_MARK "?"
|
||||
#define LUA_EXECDIR "!"
|
||||
#define LUA_IGMARK "-"
|
||||
#define LUA_PATH_CONFIG \
|
||||
LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" \
|
||||
LUA_EXECDIR "\n" LUA_IGMARK
|
||||
|
||||
/* Quoting in error messages. */
|
||||
#define LUA_QL(x) "'" x "'"
|
||||
#define LUA_QS LUA_QL("%s")
|
||||
|
||||
/* Various tunables. */
|
||||
#define LUAI_MAXSTACK 65500 /* Max. # of stack slots for a thread (<64K). */
|
||||
#define LUAI_MAXCSTACK 8000 /* Max. # of stack slots for a C func (<10K). */
|
||||
#define LUAI_GCPAUSE 200 /* Pause GC until memory is at 200%. */
|
||||
#define LUAI_GCMUL 200 /* Run GC at 200% of allocation speed. */
|
||||
#define LUA_MAXCAPTURES 32 /* Max. pattern captures. */
|
||||
|
||||
/* Compatibility with older library function names. */
|
||||
#define LUA_COMPAT_MOD /* OLD: math.mod, NEW: math.fmod */
|
||||
#define LUA_COMPAT_GFIND /* OLD: string.gfind, NEW: string.gmatch */
|
||||
|
||||
/* Configuration for the frontend (the luajit executable). */
|
||||
#if defined(luajit_c)
|
||||
#define LUA_PROGNAME "luajit" /* Fallback frontend name. */
|
||||
#define LUA_PROMPT "> " /* Interactive prompt. */
|
||||
#define LUA_PROMPT2 ">> " /* Continuation prompt. */
|
||||
#define LUA_MAXINPUT 512 /* Max. input line length. */
|
||||
#endif
|
||||
|
||||
/* Note: changing the following defines breaks the Lua 5.1 ABI. */
|
||||
#define LUA_INTEGER ptrdiff_t
|
||||
#define LUA_IDSIZE 60 /* Size of lua_Debug.short_src. */
|
||||
/*
|
||||
** Size of lauxlib and io.* on-stack buffers. Weird workaround to avoid using
|
||||
** unreasonable amounts of stack space, but still retain ABI compatibility.
|
||||
** Blame Lua for depending on BUFSIZ in the ABI, blame **** for wrecking it.
|
||||
*/
|
||||
#define LUAL_BUFFERSIZE (BUFSIZ > 16384 ? 8192 : BUFSIZ)
|
||||
|
||||
/* The following defines are here only for compatibility with luaconf.h
|
||||
** from the standard Lua distribution. They must not be changed for LuaJIT.
|
||||
*/
|
||||
#define LUA_NUMBER_DOUBLE
|
||||
#define LUA_NUMBER double
|
||||
#define LUAI_UACNUMBER double
|
||||
#define LUA_NUMBER_SCAN "%lf"
|
||||
#define LUA_NUMBER_FMT "%.14g"
|
||||
#define lua_number2str(s, n) sprintf((s), LUA_NUMBER_FMT, (n))
|
||||
#define LUAI_MAXNUMBER2STR 32
|
||||
#define LUA_INTFRMLEN "l"
|
||||
#define LUA_INTFRM_T long
|
||||
|
||||
/* Linkage of public API functions. */
|
||||
#if defined(LUA_BUILD_AS_DLL)
|
||||
#if defined(LUA_CORE) || defined(LUA_LIB)
|
||||
#define LUA_API __declspec(dllexport)
|
||||
#else
|
||||
#define LUA_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define LUA_API extern
|
||||
#endif
|
||||
|
||||
#define LUALIB_API LUA_API
|
||||
|
||||
/* Support for internal assertions. */
|
||||
#if defined(LUA_USE_ASSERT) || defined(LUA_USE_APICHECK)
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#ifdef LUA_USE_ASSERT
|
||||
#define lua_assert(x) assert(x)
|
||||
#endif
|
||||
#ifdef LUA_USE_APICHECK
|
||||
#define luai_apicheck(L, o) { (void)L; assert(o); }
|
||||
#else
|
||||
#define luai_apicheck(L, o) { (void)L; }
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
** LuaJIT -- a Just-In-Time Compiler for Lua. http://luajit.org/
|
||||
**
|
||||
** Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
**
|
||||
** Permission is hereby granted, free of charge, to any person obtaining
|
||||
** a copy of this software and associated documentation files (the
|
||||
** "Software"), to deal in the Software without restriction, including
|
||||
** without limitation the rights to use, copy, modify, merge, publish,
|
||||
** distribute, sublicense, and/or sell copies of the Software, and to
|
||||
** permit persons to whom the Software is furnished to do so, subject to
|
||||
** the following conditions:
|
||||
**
|
||||
** The above copyright notice and this permission notice shall be
|
||||
** included in all copies or substantial portions of the Software.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
** SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
**
|
||||
** [ MIT license: http://www.opensource.org/licenses/mit-license.php ]
|
||||
*/
|
||||
|
||||
#ifndef _LUAJIT_H
|
||||
#define _LUAJIT_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#define LUAJIT_VERSION "LuaJIT 2.0.4"
|
||||
#define LUAJIT_VERSION_NUM 20004 /* Version 2.0.4 = 02.00.04. */
|
||||
#define LUAJIT_VERSION_SYM luaJIT_version_2_0_4
|
||||
#define LUAJIT_COPYRIGHT "Copyright (C) 2005-2015 Mike Pall"
|
||||
#define LUAJIT_URL "http://luajit.org/"
|
||||
|
||||
/* Modes for luaJIT_setmode. */
|
||||
#define LUAJIT_MODE_MASK 0x00ff
|
||||
|
||||
enum {
|
||||
LUAJIT_MODE_ENGINE, /* Set mode for whole JIT engine. */
|
||||
LUAJIT_MODE_DEBUG, /* Set debug mode (idx = level). */
|
||||
|
||||
LUAJIT_MODE_FUNC, /* Change mode for a function. */
|
||||
LUAJIT_MODE_ALLFUNC, /* Recurse into subroutine protos. */
|
||||
LUAJIT_MODE_ALLSUBFUNC, /* Change only the subroutines. */
|
||||
|
||||
LUAJIT_MODE_TRACE, /* Flush a compiled trace. */
|
||||
|
||||
LUAJIT_MODE_WRAPCFUNC = 0x10, /* Set wrapper mode for C function calls. */
|
||||
|
||||
LUAJIT_MODE_MAX
|
||||
};
|
||||
|
||||
/* Flags or'ed in to the mode. */
|
||||
#define LUAJIT_MODE_OFF 0x0000 /* Turn feature off. */
|
||||
#define LUAJIT_MODE_ON 0x0100 /* Turn feature on. */
|
||||
#define LUAJIT_MODE_FLUSH 0x0200 /* Flush JIT-compiled code. */
|
||||
|
||||
/* LuaJIT public C API. */
|
||||
|
||||
/* Control the JIT engine. */
|
||||
LUA_API int luaJIT_setmode(lua_State *L, int idx, int mode);
|
||||
|
||||
/* Enforce (dynamic) linker error for version mismatches. Call from main. */
|
||||
LUA_API void LUAJIT_VERSION_SYM(void);
|
||||
|
||||
#endif
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
** Standard library header.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LUALIB_H
|
||||
#define _LUALIB_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#define LUA_FILEHANDLE "FILE*"
|
||||
|
||||
#define LUA_COLIBNAME "coroutine"
|
||||
#define LUA_MATHLIBNAME "math"
|
||||
#define LUA_STRLIBNAME "string"
|
||||
#define LUA_TABLIBNAME "table"
|
||||
#define LUA_IOLIBNAME "io"
|
||||
#define LUA_OSLIBNAME "os"
|
||||
#define LUA_LOADLIBNAME "package"
|
||||
#define LUA_DBLIBNAME "debug"
|
||||
#define LUA_BITLIBNAME "bit"
|
||||
#define LUA_JITLIBNAME "jit"
|
||||
#define LUA_FFILIBNAME "ffi"
|
||||
|
||||
LUALIB_API int luaopen_base(lua_State *L);
|
||||
LUALIB_API int luaopen_math(lua_State *L);
|
||||
LUALIB_API int luaopen_string(lua_State *L);
|
||||
LUALIB_API int luaopen_table(lua_State *L);
|
||||
LUALIB_API int luaopen_io(lua_State *L);
|
||||
LUALIB_API int luaopen_os(lua_State *L);
|
||||
LUALIB_API int luaopen_package(lua_State *L);
|
||||
LUALIB_API int luaopen_debug(lua_State *L);
|
||||
LUALIB_API int luaopen_bit(lua_State *L);
|
||||
LUALIB_API int luaopen_jit(lua_State *L);
|
||||
LUALIB_API int luaopen_ffi(lua_State *L);
|
||||
|
||||
LUALIB_API void luaL_openlibs(lua_State *L);
|
||||
|
||||
#ifndef lua_assert
|
||||
#define lua_assert(x) ((void)0)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,7 @@
|
|||
luajit
|
||||
lj_bcdef.h
|
||||
lj_ffdef.h
|
||||
lj_libdef.h
|
||||
lj_recdef.h
|
||||
lj_folddef.h
|
||||
lj_vm.[sS]
|
|
@ -7,12 +7,12 @@
|
|||
# Also works with MinGW and Cygwin on Windows.
|
||||
# Please check msvcbuild.bat for building with MSVC on Windows.
|
||||
#
|
||||
# Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
# Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
##############################################################################
|
||||
|
||||
MAJVER= 2
|
||||
MINVER= 0
|
||||
RELVER= 4
|
||||
MINVER= 1
|
||||
RELVER= 0
|
||||
ABIVER= 5.1
|
||||
NODOTABIVER= 51
|
||||
|
||||
|
@ -24,11 +24,13 @@ NODOTABIVER= 51
|
|||
# removing the '#' in front of them. Make sure you force a full recompile
|
||||
# with "make clean", followed by "make" if you change any options.
|
||||
#
|
||||
DEFAULT_CC = gcc
|
||||
#
|
||||
# LuaJIT builds as a native 32 or 64 bit binary by default.
|
||||
CC= gcc
|
||||
CC= $(DEFAULT_CC)
|
||||
#
|
||||
# Use this if you want to force a 32 bit build on a 64 bit multilib OS.
|
||||
#CC= gcc -m32
|
||||
#CC= $(DEFAULT_CC) -m32
|
||||
#
|
||||
# Since the assembler part does NOT maintain a frame pointer, it's pointless
|
||||
# to slow down the C part by not omitting it. Debugging, tracebacks and
|
||||
|
@ -42,17 +44,14 @@ CCOPT= -O2 -fomit-frame-pointer
|
|||
#
|
||||
# Target-specific compiler options:
|
||||
#
|
||||
# x86 only: it's recommended to compile at least for i686. Better yet,
|
||||
# compile for an architecture that has SSE2, too (-msse -msse2).
|
||||
#
|
||||
# x86/x64 only: For GCC 4.2 or higher and if you don't intend to distribute
|
||||
# the binaries to a different machine you could also use: -march=native
|
||||
#
|
||||
CCOPT_x86= -march=i686
|
||||
CCOPT_x86= -march=i686 -msse -msse2 -mfpmath=sse
|
||||
CCOPT_x64=
|
||||
CCOPT_arm=
|
||||
CCOPT_arm64=
|
||||
CCOPT_ppc=
|
||||
CCOPT_ppcspe=
|
||||
CCOPT_mips=
|
||||
#
|
||||
#CCDEBUG=
|
||||
|
@ -88,7 +87,7 @@ BUILDMODE= static
|
|||
##############################################################################
|
||||
# Enable/disable these features as needed, but make sure you force a full
|
||||
# recompile with "make clean", followed by "make".
|
||||
XCFLAGS=-Igen
|
||||
XCFLAGS=
|
||||
#
|
||||
# Permanently disable the FFI extension to reduce the size of the LuaJIT
|
||||
# executable. But please consider that the FFI library is compiled-in,
|
||||
|
@ -111,6 +110,9 @@ XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT
|
|||
#XCFLAGS+= -DLUAJIT_NUMMODE=1
|
||||
#XCFLAGS+= -DLUAJIT_NUMMODE=2
|
||||
#
|
||||
# Enable GC64 mode for x64.
|
||||
#XCFLAGS+= -DLUAJIT_ENABLE_GC64
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
|
@ -122,8 +124,8 @@ XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT
|
|||
#
|
||||
# Use the system provided memory allocator (realloc) instead of the
|
||||
# bundled memory allocator. This is slower, but sometimes helpful for
|
||||
# debugging. This option cannot be enabled on x64, since realloc usually
|
||||
# doesn't return addresses in the right address range.
|
||||
# debugging. This option cannot be enabled on x64 without GC64, since
|
||||
# realloc usually doesn't return addresses in the right address range.
|
||||
# OTOH this option is mandatory for Valgrind's memcheck tool on x64 and
|
||||
# the only way to get useful results from it for all other architectures.
|
||||
#XCFLAGS+= -DLUAJIT_USE_SYSMALLOC
|
||||
|
@ -150,6 +152,25 @@ XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT
|
|||
# You probably don't need to change anything below this line!
|
||||
##############################################################################
|
||||
|
||||
##############################################################################
|
||||
# Host system detection.
|
||||
##############################################################################
|
||||
|
||||
ifeq (Windows,$(findstring Windows,$(OS))$(MSYSTEM)$(TERM))
|
||||
HOST_SYS= Windows
|
||||
HOST_RM= del
|
||||
else
|
||||
HOST_SYS:= $(shell uname -s)
|
||||
ifneq (,$(findstring MINGW,$(HOST_SYS)))
|
||||
HOST_SYS= Windows
|
||||
HOST_MSYS= mingw
|
||||
endif
|
||||
ifneq (,$(findstring CYGWIN,$(HOST_SYS)))
|
||||
HOST_SYS= Windows
|
||||
HOST_MSYS= cygwin
|
||||
endif
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
# Flags and options for host and target.
|
||||
##############################################################################
|
||||
|
@ -165,7 +186,8 @@ XCFLAGS+= -DLUAJIT_ENABLE_LUA52COMPAT
|
|||
# make HOST_CC="gcc -m32" CROSS=i586-mingw32msvc- TARGET_SYS=Windows
|
||||
# make HOST_CC="gcc -m32" CROSS=powerpc-linux-gnu-
|
||||
|
||||
CCOPTIONS= $(CCDEBUG) $(CCOPT) $(CCWARN) $(XCFLAGS) $(CFLAGS)
|
||||
ASOPTIONS= $(CCOPT) $(CCWARN) $(XCFLAGS) $(CFLAGS)
|
||||
CCOPTIONS= $(CCDEBUG) $(ASOPTIONS)
|
||||
LDOPTIONS= $(CCDEBUG) $(LDFLAGS)
|
||||
|
||||
HOST_CC= $(CC)
|
||||
|
@ -187,14 +209,14 @@ TARGET_CC= $(STATIC_CC)
|
|||
TARGET_STCC= $(STATIC_CC)
|
||||
TARGET_DYNCC= $(DYNAMIC_CC)
|
||||
TARGET_LD= $(CROSS)$(CC)
|
||||
TARGET_AR= $(CROSS)ar rcus
|
||||
TARGET_AR= $(CROSS)ar rcus 2>/dev/null
|
||||
TARGET_STRIP= $(CROSS)strip
|
||||
|
||||
TARGET_LIBPATH= $(CURDIR)
|
||||
#TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib)
|
||||
TARGET_LIBPATH= $(CURDIR)
|
||||
TARGET_SONAME= libluajit-$(ABIVER).so.$(MAJVER)
|
||||
TARGET_DYLIBNAME= libluajit-aegisub.so
|
||||
#TARGET_DYLIBNAME= libluajit-$(ABIVER).$(MAJVER).dylib
|
||||
TARGET_DYLIBNAME= libluajit-aegisub.so
|
||||
TARGET_DYLIBPATH= $(TARGET_LIBPATH)/$(TARGET_DYLIBNAME)
|
||||
TARGET_DLLNAME= lua$(NODOTABIVER).dll
|
||||
TARGET_XSHLDFLAGS= -shared -fPIC -Wl,-soname,$(TARGET_SONAME)
|
||||
|
@ -206,6 +228,7 @@ TARGET_XLDFLAGS=
|
|||
TARGET_XLIBS= -lm
|
||||
TARGET_TCFLAGS= $(CCOPTIONS) $(TARGET_XCFLAGS) $(TARGET_FLAGS) $(TARGET_CFLAGS)
|
||||
TARGET_ACFLAGS= $(CCOPTIONS) $(TARGET_XCFLAGS) $(TARGET_FLAGS) $(TARGET_CFLAGS)
|
||||
TARGET_ASFLAGS= $(ASOPTIONS) $(TARGET_XCFLAGS) $(TARGET_FLAGS) $(TARGET_CFLAGS)
|
||||
TARGET_ALDFLAGS= $(LDOPTIONS) $(TARGET_XLDFLAGS) $(TARGET_FLAGS) $(TARGET_LDFLAGS)
|
||||
TARGET_ASHLDFLAGS= $(LDOPTIONS) $(TARGET_XSHLDFLAGS) $(TARGET_FLAGS) $(TARGET_SHLDFLAGS)
|
||||
TARGET_ALIBS= $(TARGET_XLIBS) $(LIBS) $(TARGET_LIBS)
|
||||
|
@ -220,17 +243,29 @@ else
|
|||
ifneq (,$(findstring LJ_TARGET_ARM ,$(TARGET_TESTARCH)))
|
||||
TARGET_LJARCH= arm
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_PPC ,$(TARGET_TESTARCH)))
|
||||
TARGET_LJARCH= ppc
|
||||
ifneq (,$(findstring LJ_TARGET_ARM64 ,$(TARGET_TESTARCH)))
|
||||
ifneq (,$(findstring __AARCH64EB__ ,$(TARGET_TESTARCH)))
|
||||
TARGET_ARCH= -D__AARCH64EB__=1
|
||||
endif
|
||||
TARGET_LJARCH= arm64
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_PPCSPE ,$(TARGET_TESTARCH)))
|
||||
TARGET_LJARCH= ppcspe
|
||||
ifneq (,$(findstring LJ_TARGET_PPC ,$(TARGET_TESTARCH)))
|
||||
ifneq (,$(findstring LJ_LE 1,$(TARGET_TESTARCH)))
|
||||
TARGET_ARCH= -DLJ_ARCH_ENDIAN=LUAJIT_LE
|
||||
else
|
||||
TARGET_ARCH= -DLJ_ARCH_ENDIAN=LUAJIT_BE
|
||||
endif
|
||||
TARGET_LJARCH= ppc
|
||||
else
|
||||
ifneq (,$(findstring LJ_TARGET_MIPS ,$(TARGET_TESTARCH)))
|
||||
ifneq (,$(findstring MIPSEL ,$(TARGET_TESTARCH)))
|
||||
TARGET_ARCH= -D__MIPSEL__=1
|
||||
endif
|
||||
TARGET_LJARCH= mips
|
||||
ifneq (,$(findstring LJ_TARGET_MIPS64 ,$(TARGET_TESTARCH)))
|
||||
TARGET_LJARCH= mips64
|
||||
else
|
||||
TARGET_LJARCH= mips
|
||||
endif
|
||||
else
|
||||
$(error Unsupported target architecture)
|
||||
endif
|
||||
|
@ -244,9 +279,7 @@ ifneq (,$(findstring LJ_TARGET_PS3 1,$(TARGET_TESTARCH)))
|
|||
TARGET_SYS= PS3
|
||||
TARGET_ARCH+= -D__CELLOS_LV2__
|
||||
TARGET_XCFLAGS+= -DLUAJIT_USE_SYSMALLOC
|
||||
endif
|
||||
ifneq (,$(findstring LJ_NO_UNWIND 1,$(TARGET_TESTARCH)))
|
||||
TARGET_ARCH+= -DLUAJIT_NO_UNWIND
|
||||
TARGET_XLIBS+= -lpthread
|
||||
endif
|
||||
|
||||
TARGET_XCFLAGS+= $(CCOPT_$(TARGET_LJARCH))
|
||||
|
@ -268,24 +301,9 @@ ifneq (,$(LMULTILIB))
|
|||
endif
|
||||
|
||||
##############################################################################
|
||||
# System detection.
|
||||
# Target system detection.
|
||||
##############################################################################
|
||||
|
||||
ifeq (Windows,$(findstring Windows,$(OS))$(MSYSTEM)$(TERM))
|
||||
HOST_SYS= Windows
|
||||
HOST_RM= del
|
||||
else
|
||||
HOST_SYS:= $(shell uname -s)
|
||||
ifneq (,$(findstring MINGW,$(HOST_SYS)))
|
||||
HOST_SYS= Windows
|
||||
HOST_MSYS= mingw
|
||||
endif
|
||||
ifneq (,$(findstring CYGWIN,$(HOST_SYS)))
|
||||
HOST_SYS= Windows
|
||||
HOST_MSYS= cygwin
|
||||
endif
|
||||
endif
|
||||
|
||||
TARGET_SYS?= $(HOST_SYS)
|
||||
ifeq (Windows,$(TARGET_SYS))
|
||||
TARGET_STRIP+= --strip-unneeded
|
||||
|
@ -300,7 +318,6 @@ ifeq (Darwin,$(TARGET_SYS))
|
|||
export MACOSX_DEPLOYMENT_TARGET=10.4
|
||||
endif
|
||||
TARGET_STRIP+= -x
|
||||
TARGET_AR+= 2>/dev/null
|
||||
TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC
|
||||
TARGET_DYNXLDOPTS=
|
||||
TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER)
|
||||
|
@ -311,10 +328,12 @@ ifeq (Darwin,$(TARGET_SYS))
|
|||
else
|
||||
ifeq (iOS,$(TARGET_SYS))
|
||||
TARGET_STRIP+= -x
|
||||
TARGET_AR+= 2>/dev/null
|
||||
TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC
|
||||
TARGET_DYNXLDOPTS=
|
||||
TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER)
|
||||
ifeq (arm64,$(TARGET_LJARCH))
|
||||
TARGET_XCFLAGS+= -fno-omit-frame-pointer
|
||||
endif
|
||||
else
|
||||
ifneq (SunOS,$(TARGET_SYS))
|
||||
ifneq (PS3,$(TARGET_SYS))
|
||||
|
@ -375,6 +394,11 @@ DASM_XFLAGS=
|
|||
DASM_AFLAGS=
|
||||
DASM_ARCH= $(TARGET_LJARCH)
|
||||
|
||||
ifneq (,$(findstring LJ_LE 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D ENDIAN_LE
|
||||
else
|
||||
DASM_AFLAGS+= -D ENDIAN_BE
|
||||
endif
|
||||
ifneq (,$(findstring LJ_ARCH_BITS 64,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D P64
|
||||
endif
|
||||
|
@ -399,17 +423,18 @@ ifeq (,$(findstring LJ_ABI_SOFTFP 1,$(TARGET_TESTARCH)))
|
|||
else
|
||||
TARGET_ARCH+= -DLJ_ABI_SOFTFP=1
|
||||
endif
|
||||
ifneq (,$(findstring LJ_NO_UNWIND 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D NO_UNWIND
|
||||
TARGET_ARCH+= -DLUAJIT_NO_UNWIND
|
||||
endif
|
||||
DASM_AFLAGS+= -D VER=$(subst LJ_ARCH_VERSION_,,$(filter LJ_ARCH_VERSION_%,$(subst LJ_ARCH_VERSION ,LJ_ARCH_VERSION_,$(TARGET_TESTARCH))))
|
||||
ifeq (Windows,$(TARGET_SYS))
|
||||
DASM_AFLAGS+= -D WIN
|
||||
endif
|
||||
ifeq (x86,$(TARGET_LJARCH))
|
||||
ifneq (,$(findstring __SSE2__ 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D SSE
|
||||
endif
|
||||
else
|
||||
ifeq (x64,$(TARGET_LJARCH))
|
||||
DASM_ARCH= x86
|
||||
ifeq (,$(findstring LJ_FR2 1,$(TARGET_TESTARCH)))
|
||||
DASM_ARCH= x86
|
||||
endif
|
||||
else
|
||||
ifeq (arm,$(TARGET_LJARCH))
|
||||
ifeq (iOS,$(TARGET_SYS))
|
||||
|
@ -423,13 +448,15 @@ ifeq (ppc,$(TARGET_LJARCH))
|
|||
ifneq (,$(findstring LJ_ARCH_ROUND 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D ROUND
|
||||
endif
|
||||
ifneq (,$(findstring LJ_ARCH_PPC64 1,$(TARGET_TESTARCH)))
|
||||
ifneq (,$(findstring LJ_ARCH_PPC32ON64 1,$(TARGET_TESTARCH)))
|
||||
DASM_AFLAGS+= -D GPR64
|
||||
endif
|
||||
ifeq (PS3,$(TARGET_SYS))
|
||||
DASM_AFLAGS+= -D PPE -D TOC
|
||||
endif
|
||||
endif
|
||||
ifneq (,$(findstring LJ_ARCH_PPC64 ,$(TARGET_TESTARCH)))
|
||||
DASM_ARCH= ppc64
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
@ -445,7 +472,7 @@ BUILDVM_X= $(BUILDVM_T)
|
|||
HOST_O= $(MINILUA_O) $(BUILDVM_O)
|
||||
HOST_T= $(MINILUA_T) $(BUILDVM_T)
|
||||
|
||||
LJVM_S= lj_vm.s
|
||||
LJVM_S= lj_vm.S
|
||||
LJVM_O= lj_vm.o
|
||||
LJVM_BOUT= $(LJVM_S)
|
||||
LJVM_MODE= elfasm
|
||||
|
@ -454,10 +481,11 @@ 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
|
||||
LJLIB_C= $(LJLIB_O:.o=.c)
|
||||
|
||||
LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o \
|
||||
LJCORE_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_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_strscan.o \
|
||||
lj_api.o lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \
|
||||
lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.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_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
|
||||
lj_mcode.o lj_snap.o lj_record.o lj_crecord.o lj_ffrecord.o \
|
||||
|
@ -479,8 +507,8 @@ LUAJIT_SO= libluajit-aegisub.so
|
|||
LUAJIT_T= luajit
|
||||
|
||||
ALL_T= $(LUAJIT_T) $(LUAJIT_A) $(LUAJIT_SO) $(HOST_T)
|
||||
ALL_HDRGEN= gen/lj_bcdef.h gen/lj_ffdef.h gen/lj_libdef.h gen/lj_recdef.h gen/lj_folddef.h \
|
||||
gen/buildvm_arch.h
|
||||
ALL_HDRGEN= lj_bcdef.h lj_ffdef.h lj_libdef.h lj_recdef.h lj_folddef.h \
|
||||
host/buildvm_arch.h
|
||||
ALL_GEN= $(LJVM_S) $(ALL_HDRGEN) $(LIB_VMDEFP)
|
||||
WIN_RM= *.obj *.lib *.exp *.dll *.exe *.manifest *.pdb *.ilk
|
||||
ALL_RM= $(ALL_T) $(ALL_GEN) *.o host/*.o $(WIN_RM)
|
||||
|
@ -513,9 +541,6 @@ ifeq (Windows,$(TARGET_SYS))
|
|||
endif
|
||||
ifeq (Darwin,$(TARGET_SYS))
|
||||
LJVM_MODE= machasm
|
||||
# -dead_strip breaks LuaJIT, but we really want it for everything else, so we
|
||||
# have to dynamically link it
|
||||
BUILDMODE= dynamic
|
||||
endif
|
||||
ifeq (iOS,$(TARGET_SYS))
|
||||
LJVM_MODE= machasm
|
||||
|
@ -562,13 +587,10 @@ endif
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(V),1)
|
||||
Q=
|
||||
E= @:
|
||||
else
|
||||
Q= @
|
||||
E= @echo
|
||||
endif
|
||||
#Q=
|
||||
#E= @:
|
||||
|
||||
##############################################################################
|
||||
# Make targets.
|
||||
|
@ -577,11 +599,16 @@ endif
|
|||
default all: $(TARGET_T)
|
||||
|
||||
amalg:
|
||||
@grep "^[+|]" ljamalg.c
|
||||
$(MAKE) all "LJCORE_O=ljamalg.o"
|
||||
|
||||
clean:
|
||||
$(HOST_RM) $(ALL_RM)
|
||||
|
||||
libbc:
|
||||
./$(LUAJIT_T) host/genlibbc.lua -o host/buildvm_libbc.h $(LJLIB_C)
|
||||
$(MAKE) all
|
||||
|
||||
depend:
|
||||
@for file in $(ALL_HDRGEN); do \
|
||||
test -f $$file || touch $$file; \
|
||||
|
@ -596,7 +623,7 @@ depend:
|
|||
test -s $$file || $(HOST_RM) $$file; \
|
||||
done
|
||||
|
||||
.PHONY: default all amalg clean depend
|
||||
.PHONY: default all amalg clean libbc depend
|
||||
|
||||
##############################################################################
|
||||
# Rules for generated files.
|
||||
|
@ -606,10 +633,7 @@ $(MINILUA_T): $(MINILUA_O)
|
|||
$(E) "HOSTLINK $@"
|
||||
$(Q)$(HOST_CC) $(HOST_ALDFLAGS) -o $@ $(MINILUA_O) $(MINILUA_LIBS) $(HOST_ALIBS)
|
||||
|
||||
gen:
|
||||
mkdir -p gen
|
||||
|
||||
gen/buildvm_arch.h: $(DASM_DASC) $(DASM_DEP) gen
|
||||
host/buildvm_arch.h: $(DASM_DASC) $(DASM_DEP) $(DASM_DIR)/*.lua
|
||||
$(E) "DYNASM $@"
|
||||
$(Q)$(DASM) $(DASM_FLAGS) -o $@ $(DASM_DASC)
|
||||
|
||||
|
@ -623,19 +647,19 @@ $(LJVM_BOUT): $(BUILDVM_T)
|
|||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m $(LJVM_MODE) -o $@
|
||||
|
||||
gen/lj_bcdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
lj_bcdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m bcdef -o $@ $(LJLIB_C)
|
||||
|
||||
gen/lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
lj_ffdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m ffdef -o $@ $(LJLIB_C)
|
||||
|
||||
gen/lj_libdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
lj_libdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m libdef -o $@ $(LJLIB_C)
|
||||
|
||||
gen/lj_recdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
lj_recdef.h: $(BUILDVM_T) $(LJLIB_C)
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m recdef -o $@ $(LJLIB_C)
|
||||
|
||||
|
@ -643,7 +667,7 @@ $(LIB_VMDEF): $(BUILDVM_T) $(LJLIB_C)
|
|||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m vmdef -o $(LIB_VMDEFP) $(LJLIB_C)
|
||||
|
||||
gen/lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c
|
||||
lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c
|
||||
$(E) "BUILDVM $@"
|
||||
$(Q)$(BUILDVM_X) -m folddef -o $@ lj_opt_fold.c
|
||||
|
||||
|
@ -656,10 +680,10 @@ gen/lj_folddef.h: $(BUILDVM_T) lj_opt_fold.c
|
|||
$(Q)$(TARGET_DYNCC) $(TARGET_ACFLAGS) -c -o $(@:.o=_dyn.o) $<
|
||||
$(Q)$(TARGET_CC) $(TARGET_ACFLAGS) -c -o $@ $<
|
||||
|
||||
%.o: %.s
|
||||
%.o: %.S
|
||||
$(E) "ASM $@"
|
||||
$(Q)$(TARGET_DYNCC) $(TARGET_ACFLAGS) -c -o $(@:.o=_dyn.o) $<
|
||||
$(Q)$(TARGET_CC) $(TARGET_ACFLAGS) -c -o $@ $<
|
||||
$(Q)$(TARGET_DYNCC) $(TARGET_ASFLAGS) -c -o $(@:.o=_dyn.o) $<
|
||||
$(Q)$(TARGET_CC) $(TARGET_ASFLAGS) -c -o $@ $<
|
||||
|
||||
$(LUAJIT_O):
|
||||
$(E) "CC $@"
|
||||
|
|
|
@ -3,64 +3,71 @@ lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
|
|||
lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h lj_alloc.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_tab.h lj_meta.h lj_state.h lj_ctype.h lj_cconv.h lj_bc.h lj_ff.h \
|
||||
gen/lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \
|
||||
lj_lib.h gen/lj_libdef.h
|
||||
lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \
|
||||
lj_ff.h lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.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 \
|
||||
lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_lib.h gen/lj_libdef.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_ffdef.h lj_lib.h lj_libdef.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 \
|
||||
gen/lj_libdef.h
|
||||
lj_libdef.h
|
||||
lib_ffi.o: lib_ffi.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_str.h lj_tab.h lj_meta.h \
|
||||
lj_ctype.h lj_cparse.h lj_cdata.h lj_cconv.h lj_carith.h lj_ccall.h \
|
||||
lj_ccallback.h lj_clib.h lj_ff.h gen/lj_ffdef.h lj_lib.h gen/lj_libdef.h
|
||||
lj_ccallback.h lj_clib.h lj_strfmt.h lj_ff.h lj_ffdef.h lj_lib.h \
|
||||
lj_libdef.h
|
||||
lib_init.o: lib_init.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h
|
||||
lib_io.o: lib_io.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_str.h lj_state.h lj_ff.h \
|
||||
gen/lj_ffdef.h lj_lib.h gen/lj_libdef.h
|
||||
lib_jit.o: lib_jit.c lua.h luaconf.h lauxlib.h lualib.h lj_arch.h \
|
||||
lj_obj.h lj_def.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h \
|
||||
lj_bc.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_target.h \
|
||||
lj_target_*.h lj_dispatch.h lj_vm.h lj_vmevent.h lj_lib.h luajit.h \
|
||||
gen/lj_libdef.h
|
||||
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_state.h \
|
||||
lj_strfmt.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h
|
||||
lib_jit.o: lib_jit.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_tab.h \
|
||||
lj_state.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \
|
||||
lj_target.h lj_target_*.h lj_trace.h lj_dispatch.h lj_traceerr.h \
|
||||
lj_vm.h lj_vmevent.h lj_lib.h luajit.h lj_libdef.h
|
||||
lib_math.o: lib_math.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
|
||||
lj_def.h lj_arch.h lj_lib.h lj_vm.h gen/lj_libdef.h
|
||||
lj_def.h lj_arch.h lj_lib.h lj_vm.h lj_libdef.h
|
||||
lib_os.o: lib_os.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_lib.h gen/lj_libdef.h
|
||||
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_lib.h \
|
||||
lj_libdef.h
|
||||
lib_package.o: lib_package.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_lib.h
|
||||
lib_string.o: lib_string.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_str.h lj_tab.h \
|
||||
lj_meta.h lj_state.h lj_ff.h gen/lj_ffdef.h lj_bcdump.h lj_lex.h lj_char.h \
|
||||
lj_lib.h gen/lj_libdef.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_meta.h lj_state.h lj_ff.h lj_ffdef.h lj_bcdump.h lj_lex.h \
|
||||
lj_char.h lj_strfmt.h lj_lib.h lj_libdef.h
|
||||
lib_table.o: lib_table.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_tab.h lj_lib.h \
|
||||
gen/lj_libdef.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_ff.h lj_ffdef.h lj_lib.h lj_libdef.h
|
||||
lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h
|
||||
lj_api.o: lj_api.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_str.h lj_tab.h lj_func.h lj_udata.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_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_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h \
|
||||
lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h lj_traceerr.h \
|
||||
lj_snap.h lj_asm.h lj_vm.h lj_target.h lj_target_*.h lj_emit_*.h \
|
||||
lj_asm_*.h
|
||||
lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \
|
||||
gen/lj_bcdef.h
|
||||
lj_bcdef.h
|
||||
lj_bcread.o: lj_bcread.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_tab.h lj_bc.h lj_ctype.h \
|
||||
lj_cdata.h lualib.h lj_lex.h lj_bcdump.h lj_state.h
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_bc.h \
|
||||
lj_ctype.h lj_cdata.h lualib.h lj_lex.h lj_bcdump.h lj_state.h \
|
||||
lj_strfmt.h
|
||||
lj_bcwrite.o: lj_bcwrite.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_gc.h lj_str.h lj_bc.h lj_ctype.h lj_dispatch.h lj_jit.h lj_ir.h \
|
||||
lj_bcdump.h lj_lex.h lj_err.h lj_errmsg.h lj_vm.h
|
||||
lj_gc.h lj_buf.h lj_str.h lj_bc.h lj_ctype.h lj_dispatch.h lj_jit.h \
|
||||
lj_ir.h lj_strfmt.h lj_bcdump.h lj_lex.h lj_err.h lj_errmsg.h lj_vm.h
|
||||
lj_buf.o: lj_buf.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_strfmt.h
|
||||
lj_carith.o: lj_carith.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_meta.h lj_ctype.h lj_cconv.h \
|
||||
lj_cdata.h lj_carith.h
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_meta.h lj_ir.h lj_ctype.h \
|
||||
lj_cconv.h lj_cdata.h lj_carith.h lj_strscan.h
|
||||
lj_ccall.o: lj_ccall.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_tab.h lj_ctype.h lj_cconv.h \
|
||||
lj_cdata.h lj_ccall.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_cconv.h lj_cdata.h \
|
||||
lj_ccall.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \
|
||||
lj_traceerr.h
|
||||
lj_ccallback.o: lj_ccallback.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_state.h lj_frame.h \
|
||||
|
@ -71,107 +78,118 @@ 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_ccallback.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_str.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_clib.o: lj_clib.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_str.h lj_udata.h lj_ctype.h lj_cconv.h \
|
||||
lj_cdata.h lj_clib.h
|
||||
lj_cdata.h lj_clib.h lj_strfmt.h
|
||||
lj_cparse.o: lj_cparse.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_ctype.h lj_cparse.h lj_frame.h \
|
||||
lj_bc.h lj_vm.h lj_char.h lj_strscan.h
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_ctype.h lj_cparse.h \
|
||||
lj_frame.h lj_bc.h lj_vm.h lj_char.h lj_strscan.h lj_strfmt.h
|
||||
lj_crecord.o: lj_crecord.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_ctype.h \
|
||||
lj_gc.h lj_cdata.h lj_cparse.h lj_cconv.h lj_clib.h lj_ccall.h lj_ff.h \
|
||||
gen/lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \
|
||||
lj_err.h lj_errmsg.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_gc.h \
|
||||
lj_cdata.h lj_cparse.h lj_cconv.h lj_carith.h lj_clib.h lj_ccall.h \
|
||||
lj_ff.h lj_ffdef.h lj_ir.h lj_jit.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_crecord.h
|
||||
lj_crecord.h lj_strfmt.h
|
||||
lj_ctype.o: lj_ctype.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_tab.h lj_ctype.h lj_ccallback.h
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_strfmt.h lj_ctype.h \
|
||||
lj_ccallback.h lj_buf.h
|
||||
lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_state.h lj_frame.h \
|
||||
lj_bc.h lj_jit.h lj_ir.h
|
||||
lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \
|
||||
lj_state.h lj_frame.h lj_bc.h lj_strfmt.h lj_jit.h lj_ir.h
|
||||
lj_dispatch.o: lj_dispatch.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_err.h lj_errmsg.h lj_func.h lj_str.h lj_tab.h lj_meta.h lj_debug.h \
|
||||
lj_state.h lj_frame.h lj_bc.h lj_ff.h gen/lj_ffdef.h lj_jit.h lj_ir.h \
|
||||
lj_ccallback.h lj_ctype.h lj_gc.h lj_trace.h lj_dispatch.h lj_traceerr.h \
|
||||
lj_vm.h luajit.h
|
||||
lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_func.h lj_tab.h \
|
||||
lj_meta.h lj_debug.h lj_state.h lj_frame.h lj_bc.h lj_ff.h lj_ffdef.h \
|
||||
lj_strfmt.h lj_jit.h lj_ir.h lj_ccallback.h lj_ctype.h lj_trace.h \
|
||||
lj_dispatch.h lj_traceerr.h lj_profile.h lj_vm.h luajit.h
|
||||
lj_err.o: lj_err.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_err.h \
|
||||
lj_errmsg.h lj_debug.h lj_str.h lj_func.h lj_state.h lj_frame.h lj_bc.h \
|
||||
lj_ff.h gen/lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
|
||||
lj_traceerr.h lj_vm.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_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 \
|
||||
gen/lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \
|
||||
lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \
|
||||
lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h lj_crecord.h \
|
||||
lj_vm.h lj_strscan.h gen/lj_recdef.h
|
||||
lj_vm.h lj_strscan.h lj_strfmt.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.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \
|
||||
lj_traceerr.h lj_vm.h
|
||||
lj_gc.o: lj_gc.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_tab.h lj_func.h lj_udata.h lj_meta.h \
|
||||
lj_state.h lj_frame.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.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_func.h lj_udata.h \
|
||||
lj_meta.h lj_state.h lj_frame.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_gdbjit.o: lj_gdbjit.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_frame.h lj_bc.h lj_jit.h \
|
||||
lj_ir.h lj_dispatch.h
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_frame.h lj_bc.h lj_buf.h \
|
||||
lj_str.h lj_strfmt.h lj_jit.h lj_ir.h lj_dispatch.h
|
||||
lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.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_carith.h \
|
||||
lj_vm.h lj_strscan.h lj_lib.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_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.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_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
|
||||
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 \
|
||||
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_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_lib.h
|
||||
lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.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_arch.h lj_gc.h lj_err.h lj_errmsg.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_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_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_jit.h lj_ir.h lj_mcode.h lj_trace.h \
|
||||
lj_dispatch.h lj_bc.h lj_traceerr.h lj_vm.h
|
||||
lj_meta.o: lj_meta.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_tab.h lj_meta.h lj_frame.h lj_bc.h \
|
||||
lj_vm.h lj_strscan.h
|
||||
lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_meta.h lj_frame.h \
|
||||
lj_bc.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h
|
||||
lj_obj.o: lj_obj.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h
|
||||
lj_opt_dce.o: lj_opt_dce.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_ir.h lj_jit.h lj_iropt.h
|
||||
lj_opt_fold.o: lj_opt_fold.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \
|
||||
lj_bc.h lj_traceerr.h lj_ctype.h lj_gc.h lj_carith.h lj_vm.h \
|
||||
lj_strscan.h gen/lj_folddef.h
|
||||
lj_buf.h lj_gc.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_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_folddef.h
|
||||
lj_opt_loop.o: lj_opt_loop.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_err.h lj_errmsg.h lj_str.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h \
|
||||
lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h lj_vm.h
|
||||
lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_ir.h lj_jit.h \
|
||||
lj_iropt.h lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h \
|
||||
lj_vm.h
|
||||
lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_tab.h lj_ir.h lj_jit.h lj_iropt.h
|
||||
lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_ircall.h
|
||||
lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \
|
||||
lj_arch.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \
|
||||
lj_traceerr.h lj_vm.h lj_strscan.h
|
||||
lj_opt_sink.o: lj_opt_sink.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_ir.h lj_jit.h lj_iropt.h lj_target.h lj_target_*.h
|
||||
lj_opt_split.o: lj_opt_split.c lj_obj.h lua.h luaconf.h lj_def.h \
|
||||
lj_arch.h lj_err.h lj_errmsg.h lj_str.h lj_ir.h lj_jit.h lj_ircall.h \
|
||||
lj_iropt.h lj_vm.h
|
||||
lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_ir.h \
|
||||
lj_jit.h lj_ircall.h lj_iropt.h lj_dispatch.h lj_bc.h lj_vm.h
|
||||
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_str.h lj_tab.h lj_func.h \
|
||||
lj_state.h lj_bc.h lj_ctype.h lj_lex.h lj_parse.h lj_vm.h lj_vmevent.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_vm.h lj_vmevent.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_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.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_ctype.h lj_gc.h lj_ff.h gen/lj_ffdef.h lj_ir.h lj_jit.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_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_record.h lj_ffrecord.h lj_snap.h lj_vm.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_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \
|
||||
lj_target_*.h lj_ctype.h lj_cdata.h
|
||||
lj_state.o: lj_state.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_tab.h lj_func.h lj_meta.h \
|
||||
lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_trace.h lj_jit.h lj_ir.h \
|
||||
lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.h lj_alloc.h
|
||||
lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_func.h \
|
||||
lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_trace.h lj_jit.h \
|
||||
lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_lex.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_err.h lj_errmsg.h lj_str.h lj_state.h lj_char.h
|
||||
lj_err.h lj_errmsg.h lj_str.h lj_char.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_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_strscan.o: lj_strscan.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_char.h lj_strscan.h
|
||||
lj_tab.o: lj_tab.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
|
||||
|
@ -189,38 +207,40 @@ lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
|||
lj_vmmath.o: lj_vmmath.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
|
||||
lj_ir.h lj_vm.h
|
||||
ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_gc.c 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_udata.h lj_meta.h lj_state.h lj_frame.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 gen/lj_ffdef.h lj_char.c lj_char.h lj_bc.c gen/lj_bcdef.h \
|
||||
lj_obj.c lj_str.c lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h \
|
||||
lj_debug.c lj_state.c lj_lex.h lj_alloc.h lj_dispatch.c lj_ccallback.h \
|
||||
luajit.h lj_vmevent.c lj_vmevent.h lj_vmmath.c lj_strscan.c lj_api.c \
|
||||
lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c lj_bcdump.h \
|
||||
lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c \
|
||||
lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h lj_target_*.h \
|
||||
lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h lj_cparse.c \
|
||||
lj_cparse.h lj_lib.c lj_lib.h lj_ir.c lj_ircall.h lj_iropt.h \
|
||||
lj_opt_mem.c lj_opt_fold.c gen/lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \
|
||||
lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.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 gen/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 \
|
||||
lib_base.c gen/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_init.c
|
||||
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h \
|
||||
lj_func.h lj_udata.h lj_meta.h lj_state.h lj_frame.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_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_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_vmmath.c lj_strscan.c \
|
||||
lj_strfmt.c lj_strfmt_num.c lj_api.c lj_profile.c lj_lex.c lualib.h \
|
||||
lj_parse.h lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c \
|
||||
lj_ctype.c lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h \
|
||||
lj_ccallback.c lj_target.h lj_target_*.h lj_mcode.h lj_carith.c \
|
||||
lj_carith.h lj_clib.c lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c \
|
||||
lj_ircall.h lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h \
|
||||
lj_opt_narrow.c lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c \
|
||||
lj_opt_sink.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_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_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c \
|
||||
lib_ffi.c lib_init.c
|
||||
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 \
|
||||
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_ircall.h lj_ir.h lj_jit.h lj_frame.h lj_bc.h lj_dispatch.h lj_ctype.h \
|
||||
lj_gc.h lj_ccall.h lj_ctype.h luajit.h \
|
||||
gen/buildvm_arch.h lj_traceerr.h
|
||||
host/buildvm_arch.h lj_traceerr.h
|
||||
host/buildvm_asm.o: host/buildvm_asm.c host/buildvm.h lj_def.h lua.h luaconf.h \
|
||||
lj_arch.h lj_bc.h lj_def.h lj_arch.h
|
||||
host/buildvm_fold.o: host/buildvm_fold.c host/buildvm.h lj_def.h lua.h \
|
||||
luaconf.h lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_ir.h lj_obj.h
|
||||
host/buildvm_lib.o: host/buildvm_lib.c host/buildvm.h lj_def.h lua.h luaconf.h \
|
||||
lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_lib.h lj_obj.h
|
||||
lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_bc.h lj_lib.h lj_obj.h \
|
||||
host/buildvm_libbc.h
|
||||
host/buildvm_peobj.o: host/buildvm_peobj.c host/buildvm.h lj_def.h lua.h \
|
||||
luaconf.h lj_arch.h lj_bc.h lj_def.h lj_arch.h
|
||||
host/minilua.o: host/minilua.c
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
minilua
|
||||
buildvm
|
||||
buildvm_arch.h
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** LuaJIT VM builder.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** This is a tool to build the hand-tuned assembler code required for
|
||||
** LuaJIT's bytecode interpreter. It supports a variety of output formats
|
||||
|
@ -59,10 +59,10 @@ static int collect_reloc(BuildCtx *ctx, uint8_t *addr, int idx, int type);
|
|||
#include "../dynasm/dasm_x86.h"
|
||||
#elif LJ_TARGET_ARM
|
||||
#include "../dynasm/dasm_arm.h"
|
||||
#elif LJ_TARGET_ARM64
|
||||
#include "../dynasm/dasm_arm64.h"
|
||||
#elif LJ_TARGET_PPC
|
||||
#include "../dynasm/dasm_ppc.h"
|
||||
#elif LJ_TARGET_PPCSPE
|
||||
#include "../dynasm/dasm_ppc.h"
|
||||
#elif LJ_TARGET_MIPS
|
||||
#include "../dynasm/dasm_mips.h"
|
||||
#else
|
||||
|
@ -110,11 +110,11 @@ static const char *sym_decorate(BuildCtx *ctx,
|
|||
if (p) {
|
||||
#if LJ_TARGET_X86ORX64
|
||||
if (!LJ_64 && (ctx->mode == BUILD_coffasm || ctx->mode == BUILD_peobj))
|
||||
name[0] = '@';
|
||||
name[0] = name[1] == 'R' ? '_' : '@'; /* Just for _RtlUnwind@16. */
|
||||
else
|
||||
*p = '\0';
|
||||
#elif (LJ_TARGET_PPC || LJ_TARGET_PPCSPE) && !LJ_TARGET_CONSOLE
|
||||
/* Keep @plt. */
|
||||
#elif LJ_TARGET_PPC && !LJ_TARGET_CONSOLE
|
||||
/* Keep @plt etc. */
|
||||
#else
|
||||
*p = '\0';
|
||||
#endif
|
||||
|
@ -179,6 +179,7 @@ static int build_code(BuildCtx *ctx)
|
|||
ctx->nreloc = 0;
|
||||
|
||||
ctx->globnames = globnames;
|
||||
ctx->extnames = extnames;
|
||||
ctx->relocsym = (const char **)malloc(NRELOCSYM*sizeof(const char *));
|
||||
ctx->nrelocsym = 0;
|
||||
for (i = 0; i < (int)NRELOCSYM; i++) relocmap[i] = -1;
|
||||
|
@ -320,20 +321,20 @@ static void emit_vmdef(BuildCtx *ctx)
|
|||
char buf[80];
|
||||
int i;
|
||||
fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\n\n");
|
||||
fprintf(ctx->fp, "module(...)\n\n");
|
||||
fprintf(ctx->fp, "return {\n\n");
|
||||
|
||||
fprintf(ctx->fp, "bcnames = \"");
|
||||
for (i = 0; bc_names[i]; i++) fprintf(ctx->fp, "%-6s", bc_names[i]);
|
||||
fprintf(ctx->fp, "\"\n\n");
|
||||
fprintf(ctx->fp, "\",\n\n");
|
||||
|
||||
fprintf(ctx->fp, "irnames = \"");
|
||||
for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]);
|
||||
fprintf(ctx->fp, "\"\n\n");
|
||||
fprintf(ctx->fp, "\",\n\n");
|
||||
|
||||
fprintf(ctx->fp, "irfpm = { [0]=");
|
||||
for (i = 0; irfpm_names[i]; i++)
|
||||
fprintf(ctx->fp, "\"%s\", ", lower(buf, irfpm_names[i]));
|
||||
fprintf(ctx->fp, "}\n\n");
|
||||
fprintf(ctx->fp, "},\n\n");
|
||||
|
||||
fprintf(ctx->fp, "irfield = { [0]=");
|
||||
for (i = 0; irfield_names[i]; i++) {
|
||||
|
@ -343,17 +344,17 @@ static void emit_vmdef(BuildCtx *ctx)
|
|||
if (p) *p = '.';
|
||||
fprintf(ctx->fp, "\"%s\", ", buf);
|
||||
}
|
||||
fprintf(ctx->fp, "}\n\n");
|
||||
fprintf(ctx->fp, "},\n\n");
|
||||
|
||||
fprintf(ctx->fp, "ircall = {\n[0]=");
|
||||
for (i = 0; ircall_names[i]; i++)
|
||||
fprintf(ctx->fp, "\"%s\",\n", ircall_names[i]);
|
||||
fprintf(ctx->fp, "}\n\n");
|
||||
fprintf(ctx->fp, "},\n\n");
|
||||
|
||||
fprintf(ctx->fp, "traceerr = {\n[0]=");
|
||||
for (i = 0; trace_errors[i]; i++)
|
||||
fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]);
|
||||
fprintf(ctx->fp, "}\n\n");
|
||||
fprintf(ctx->fp, "},\n\n");
|
||||
}
|
||||
|
||||
/* -- Argument parsing ---------------------------------------------------- */
|
||||
|
@ -490,6 +491,7 @@ int main(int argc, char **argv)
|
|||
case BUILD_vmdef:
|
||||
emit_vmdef(ctx);
|
||||
emit_lib(ctx);
|
||||
fprintf(ctx->fp, "}\n\n");
|
||||
break;
|
||||
case BUILD_ffdef:
|
||||
case BUILD_libdef:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** LuaJIT VM builder.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _BUILDVM_H
|
||||
|
@ -82,6 +82,7 @@ typedef struct BuildCtx {
|
|||
const char *beginsym;
|
||||
/* Strings generated by DynASM. */
|
||||
const char *const *globnames;
|
||||
const char *const *extnames;
|
||||
const char *dasm_ident;
|
||||
const char *dasm_arch;
|
||||
/* Relocations. */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** LuaJIT VM builder: Assembler source code emitter.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#include "buildvm.h"
|
||||
|
@ -51,8 +51,8 @@ static const char *const jccnames[] = {
|
|||
"js", "jns", "jpe", "jpo", "jl", "jge", "jle", "jg"
|
||||
};
|
||||
|
||||
/* Emit relocation for the incredibly stupid OSX assembler. */
|
||||
static void emit_asm_reloc_mach(BuildCtx *ctx, uint8_t *cp, int n,
|
||||
/* Emit x86/x64 text relocations. */
|
||||
static void emit_asm_reloc_text(BuildCtx *ctx, uint8_t *cp, int n,
|
||||
const char *sym)
|
||||
{
|
||||
const char *opname = NULL;
|
||||
|
@ -71,6 +71,20 @@ err:
|
|||
exit(1);
|
||||
}
|
||||
emit_asm_bytes(ctx, cp, n);
|
||||
if (strncmp(sym+(*sym == '_'), LABEL_PREFIX, sizeof(LABEL_PREFIX)-1)) {
|
||||
/* Various fixups for external symbols outside of our binary. */
|
||||
if (ctx->mode == BUILD_elfasm) {
|
||||
if (LJ_32)
|
||||
fprintf(ctx->fp, "#if __PIC__\n\t%s lj_wrap_%s\n#else\n", opname, sym);
|
||||
fprintf(ctx->fp, "\t%s %s@PLT\n", opname, sym);
|
||||
if (LJ_32)
|
||||
fprintf(ctx->fp, "#endif\n");
|
||||
return;
|
||||
} else if (LJ_32 && ctx->mode == BUILD_machasm) {
|
||||
fprintf(ctx->fp, "\t%s L%s$stub\n", opname, sym);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fprintf(ctx->fp, "\t%s %s\n", opname, sym);
|
||||
}
|
||||
#else
|
||||
|
@ -79,10 +93,14 @@ static void emit_asm_words(BuildCtx *ctx, uint8_t *p, int n)
|
|||
{
|
||||
int i;
|
||||
for (i = 0; i < n; i += 4) {
|
||||
uint32_t ins = *(uint32_t *)(p+i);
|
||||
#if LJ_TARGET_ARM64 && LJ_BE
|
||||
ins = lj_bswap(ins); /* ARM64 instructions are always little-endian. */
|
||||
#endif
|
||||
if ((i & 15) == 0)
|
||||
fprintf(ctx->fp, "\t.long 0x%08x", *(uint32_t *)(p+i));
|
||||
fprintf(ctx->fp, "\t.long 0x%08x", ins);
|
||||
else
|
||||
fprintf(ctx->fp, ",0x%08x", *(uint32_t *)(p+i));
|
||||
fprintf(ctx->fp, ",0x%08x", ins);
|
||||
if ((i & 15) == 12) putc('\n', ctx->fp);
|
||||
}
|
||||
if ((n & 15) != 0) putc('\n', ctx->fp);
|
||||
|
@ -107,7 +125,16 @@ static void emit_asm_wordreloc(BuildCtx *ctx, uint8_t *p, int n,
|
|||
ins, sym);
|
||||
exit(1);
|
||||
}
|
||||
#elif LJ_TARGET_PPC || LJ_TARGET_PPCSPE
|
||||
#elif LJ_TARGET_ARM64
|
||||
if ((ins >> 26) == 0x25u) {
|
||||
fprintf(ctx->fp, "\tbl %s\n", sym);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Error: unsupported opcode %08x for %s symbol relocation.\n",
|
||||
ins, sym);
|
||||
exit(1);
|
||||
}
|
||||
#elif LJ_TARGET_PPC
|
||||
#if LJ_TARGET_PS3
|
||||
#define TOCPREFIX "."
|
||||
#else
|
||||
|
@ -117,6 +144,14 @@ static void emit_asm_wordreloc(BuildCtx *ctx, uint8_t *p, int n,
|
|||
fprintf(ctx->fp, "\t%s %d, %d, " TOCPREFIX "%s\n",
|
||||
(ins & 1) ? "bcl" : "bc", (ins >> 21) & 31, (ins >> 16) & 31, sym);
|
||||
} else if ((ins >> 26) == 18) {
|
||||
#if LJ_ARCH_PPC64
|
||||
const char *suffix = strchr(sym, '@');
|
||||
if (suffix && suffix[1] == 'h') {
|
||||
fprintf(ctx->fp, "\taddis 11, 2, %s\n", sym);
|
||||
} else if (suffix && suffix[1] == 'l') {
|
||||
fprintf(ctx->fp, "\tld 12, %s\n", sym);
|
||||
} else
|
||||
#endif
|
||||
fprintf(ctx->fp, "\t%s " TOCPREFIX "%s\n", (ins & 1) ? "bl" : "b", sym);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
|
@ -183,7 +218,8 @@ static void emit_asm_label(BuildCtx *ctx, const char *name, int size, int isfunc
|
|||
case BUILD_machasm:
|
||||
fprintf(ctx->fp,
|
||||
"\n\t.private_extern %s\n"
|
||||
"%s:\n", name, name);
|
||||
"\t.no_dead_strip %s\n"
|
||||
"%s:\n", name, name, name);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -214,6 +250,9 @@ void emit_asm(BuildCtx *ctx)
|
|||
int i, rel;
|
||||
|
||||
fprintf(ctx->fp, "\t.file \"buildvm_%s.dasc\"\n", ctx->dasm_arch);
|
||||
#if LJ_ARCH_PPC64
|
||||
fprintf(ctx->fp, "\t.abiversion 2\n");
|
||||
#endif
|
||||
fprintf(ctx->fp, "\t.text\n");
|
||||
emit_asm_align(ctx, 4);
|
||||
|
||||
|
@ -227,11 +266,20 @@ void emit_asm(BuildCtx *ctx)
|
|||
|
||||
#if LJ_TARGET_ARM && defined(__GNUC__) && !LJ_NO_UNWIND
|
||||
/* This should really be moved into buildvm_arm.dasc. */
|
||||
#if LJ_ARCH_HASFPU
|
||||
fprintf(ctx->fp,
|
||||
".fnstart\n"
|
||||
".save {r5, r6, r7, r8, r9, r10, r11, lr}\n"
|
||||
".vsave {d8-d15}\n"
|
||||
".save {r4}\n"
|
||||
".pad #28\n");
|
||||
#else
|
||||
fprintf(ctx->fp,
|
||||
".fnstart\n"
|
||||
".save {r4, r5, r6, r7, r8, r9, r10, r11, lr}\n"
|
||||
".pad #28\n");
|
||||
#endif
|
||||
#endif
|
||||
#if LJ_TARGET_MIPS
|
||||
fprintf(ctx->fp, ".set nomips16\n.abicalls\n.set noreorder\n.set nomacro\n");
|
||||
#endif
|
||||
|
@ -254,8 +302,9 @@ void emit_asm(BuildCtx *ctx)
|
|||
BuildReloc *r = &ctx->reloc[rel];
|
||||
int n = r->ofs - ofs;
|
||||
#if LJ_TARGET_X86ORX64
|
||||
if (ctx->mode == BUILD_machasm && r->type != 0) {
|
||||
emit_asm_reloc_mach(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]);
|
||||
if (r->type != 0 &&
|
||||
(ctx->mode == BUILD_elfasm || ctx->mode == BUILD_machasm)) {
|
||||
emit_asm_reloc_text(ctx, ctx->code+ofs, n, ctx->relocsym[r->sym]);
|
||||
} else {
|
||||
emit_asm_bytes(ctx, ctx->code+ofs, n);
|
||||
emit_asm_reloc(ctx, r->type, ctx->relocsym[r->sym]);
|
||||
|
@ -289,10 +338,7 @@ void emit_asm(BuildCtx *ctx)
|
|||
#if !(LJ_TARGET_PS3 || LJ_TARGET_PSVITA)
|
||||
fprintf(ctx->fp, "\t.section .note.GNU-stack,\"\"," ELFASM_PX "progbits\n");
|
||||
#endif
|
||||
#if LJ_TARGET_PPCSPE
|
||||
/* Soft-float ABI + SPE. */
|
||||
fprintf(ctx->fp, "\t.gnu_attribute 4, 2\n\t.gnu_attribute 8, 3\n");
|
||||
#elif LJ_TARGET_PPC && !LJ_TARGET_PS3
|
||||
#if LJ_TARGET_PPC && !LJ_TARGET_PS3
|
||||
/* Hard-float ABI. */
|
||||
fprintf(ctx->fp, "\t.gnu_attribute 4, 1\n");
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** LuaJIT VM builder: IR folding hash table generator.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#include "buildvm.h"
|
||||
|
@ -9,7 +9,7 @@
|
|||
|
||||
/* Context for the folding hash table generator. */
|
||||
static int lineno;
|
||||
static int funcidx;
|
||||
static uint32_t funcidx;
|
||||
static uint32_t foldkeys[BUILD_MAX_FOLD];
|
||||
static uint32_t nkeys;
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
/*
|
||||
** LuaJIT VM builder: library definition compiler.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#include "buildvm.h"
|
||||
#include "lj_obj.h"
|
||||
#include "lj_bc.h"
|
||||
#include "lj_lib.h"
|
||||
#include "buildvm_libbc.h"
|
||||
|
||||
/* Context for library definitions. */
|
||||
static uint8_t obuf[8192];
|
||||
|
@ -151,6 +153,62 @@ static void libdef_func(BuildCtx *ctx, char *p, int arg)
|
|||
regfunc = REGFUNC_OK;
|
||||
}
|
||||
|
||||
static uint8_t *libdef_uleb128(uint8_t *p, uint32_t *vv)
|
||||
{
|
||||
uint32_t v = *p++;
|
||||
if (v >= 0x80) {
|
||||
int sh = 0; v &= 0x7f;
|
||||
do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80);
|
||||
}
|
||||
*vv = v;
|
||||
return p;
|
||||
}
|
||||
|
||||
static void libdef_fixupbc(uint8_t *p)
|
||||
{
|
||||
uint32_t i, sizebc;
|
||||
p += 4;
|
||||
p = libdef_uleb128(p, &sizebc);
|
||||
p = libdef_uleb128(p, &sizebc);
|
||||
p = libdef_uleb128(p, &sizebc);
|
||||
for (i = 0; i < sizebc; i++, p += 4) {
|
||||
uint8_t op = p[libbc_endian ? 3 : 0];
|
||||
uint8_t ra = p[libbc_endian ? 2 : 1];
|
||||
uint8_t rc = p[libbc_endian ? 1 : 2];
|
||||
uint8_t rb = p[libbc_endian ? 0 : 3];
|
||||
if (!LJ_DUALNUM && op == BC_ISTYPE && rc == ~LJ_TNUMX+1) {
|
||||
op = BC_ISNUM; rc++;
|
||||
}
|
||||
p[LJ_ENDIAN_SELECT(0, 3)] = op;
|
||||
p[LJ_ENDIAN_SELECT(1, 2)] = ra;
|
||||
p[LJ_ENDIAN_SELECT(2, 1)] = rc;
|
||||
p[LJ_ENDIAN_SELECT(3, 0)] = rb;
|
||||
}
|
||||
}
|
||||
|
||||
static void libdef_lua(BuildCtx *ctx, char *p, int arg)
|
||||
{
|
||||
UNUSED(arg);
|
||||
if (ctx->mode == BUILD_libdef) {
|
||||
int i;
|
||||
for (i = 0; libbc_map[i].name != NULL; i++) {
|
||||
if (!strcmp(libbc_map[i].name, p)) {
|
||||
int ofs = libbc_map[i].ofs;
|
||||
int len = libbc_map[i+1].ofs - ofs;
|
||||
obuf[2]++; /* Bump hash table size. */
|
||||
*optr++ = LIBINIT_LUA;
|
||||
libdef_name(p, 0);
|
||||
memcpy(optr, libbc_code + ofs, len);
|
||||
libdef_fixupbc(optr);
|
||||
optr += len;
|
||||
return;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Error: missing libbc definition for %s\n", p);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t find_rec(char *name)
|
||||
{
|
||||
char *p = (char *)obuf;
|
||||
|
@ -277,6 +335,7 @@ static const LibDefHandler libdef_handlers[] = {
|
|||
{ "CF(", ")", libdef_func, LIBINIT_CF },
|
||||
{ "ASM(", ")", libdef_func, LIBINIT_ASM },
|
||||
{ "ASM_(", ")", libdef_func, LIBINIT_ASM_ },
|
||||
{ "LUA(", ")", libdef_lua, 0 },
|
||||
{ "REC(", ")", libdef_rec, 0 },
|
||||
{ "PUSH(", ")", libdef_push, 0 },
|
||||
{ "SET(", ")", libdef_set, 0 },
|
||||
|
@ -373,7 +432,7 @@ void emit_lib(BuildCtx *ctx)
|
|||
"#ifndef FF_NUM_ASMFUNC\n#define FF_NUM_ASMFUNC %d\n#endif\n\n",
|
||||
ffasmfunc);
|
||||
} else if (ctx->mode == BUILD_vmdef) {
|
||||
fprintf(ctx->fp, "}\n\n");
|
||||
fprintf(ctx->fp, "},\n\n");
|
||||
} else if (ctx->mode == BUILD_bcdef) {
|
||||
int i;
|
||||
fprintf(ctx->fp, "\n};\n\n");
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
/* This is a generated file. DO NOT EDIT! */
|
||||
|
||||
static const int libbc_endian = 0;
|
||||
|
||||
static const uint8_t libbc_code[] = {
|
||||
#if LJ_FR2
|
||||
0,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0,
|
||||
0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3,
|
||||
16,0,5,0,21,1,0,0,76,1,2,0,0,2,10,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3,
|
||||
0,0,41,4,1,0,77,2,8,128,18,6,1,0,18,8,5,0,59,9,5,0,66,6,3,2,10,6,0,0,88,7,1,
|
||||
128,76,6,2,0,79,2,248,127,75,0,1,0,0,2,11,0,0,0,16,16,0,12,0,16,1,9,0,43,2,
|
||||
0,0,18,3,0,0,41,4,0,0,88,5,7,128,18,7,1,0,18,9,5,0,18,10,6,0,66,7,3,2,10,7,
|
||||
0,0,88,8,1,128,76,7,2,0,70,5,3,3,82,5,247,127,75,0,1,0,0,1,2,0,0,0,3,16,0,12,
|
||||
0,21,1,0,0,76,1,2,0,0,2,10,0,0,2,30,16,0,12,0,21,2,0,0,11,1,0,0,88,3,7,128,
|
||||
8,2,0,0,88,3,23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,16,1,14,
|
||||
0,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2,
|
||||
0,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4,
|
||||
2,0,76,3,2,0,75,0,1,0,0,2,0,5,12,0,0,0,35,16,0,12,0,16,1,14,0,16,2,14,0,16,
|
||||
3,14,0,11,4,0,0,88,5,1,128,18,4,0,0,16,4,12,0,3,1,2,0,88,5,24,128,33,5,1,3,
|
||||
0,2,3,0,88,6,4,128,2,3,1,0,88,6,2,128,4,4,0,0,88,6,9,128,18,6,1,0,18,7,2,0,
|
||||
41,8,1,0,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,6,252,127,88,6,8,128,
|
||||
18,6,2,0,18,7,1,0,41,8,255,255,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,
|
||||
6,252,127,76,4,2,0,0
|
||||
#else
|
||||
0,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0,
|
||||
0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3,
|
||||
16,0,5,0,21,1,0,0,76,1,2,0,0,2,9,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3,
|
||||
0,0,41,4,1,0,77,2,8,128,18,6,1,0,18,7,5,0,59,8,5,0,66,6,3,2,10,6,0,0,88,7,1,
|
||||
128,76,6,2,0,79,2,248,127,75,0,1,0,0,2,10,0,0,0,16,16,0,12,0,16,1,9,0,43,2,
|
||||
0,0,18,3,0,0,41,4,0,0,88,5,7,128,18,7,1,0,18,8,5,0,18,9,6,0,66,7,3,2,10,7,0,
|
||||
0,88,8,1,128,76,7,2,0,70,5,3,3,82,5,247,127,75,0,1,0,0,1,2,0,0,0,3,16,0,12,
|
||||
0,21,1,0,0,76,1,2,0,0,2,10,0,0,2,30,16,0,12,0,21,2,0,0,11,1,0,0,88,3,7,128,
|
||||
8,2,0,0,88,3,23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,16,1,14,
|
||||
0,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2,
|
||||
0,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4,
|
||||
2,0,76,3,2,0,75,0,1,0,0,2,0,5,12,0,0,0,35,16,0,12,0,16,1,14,0,16,2,14,0,16,
|
||||
3,14,0,11,4,0,0,88,5,1,128,18,4,0,0,16,4,12,0,3,1,2,0,88,5,24,128,33,5,1,3,
|
||||
0,2,3,0,88,6,4,128,2,3,1,0,88,6,2,128,4,4,0,0,88,6,9,128,18,6,1,0,18,7,2,0,
|
||||
41,8,1,0,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,6,252,127,88,6,8,128,
|
||||
18,6,2,0,18,7,1,0,41,8,255,255,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,
|
||||
6,252,127,76,4,2,0,0
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct { const char *name; int ofs; } libbc_map[] = {
|
||||
{"math_deg",0},
|
||||
{"math_rad",25},
|
||||
{"string_len",50},
|
||||
{"table_foreachi",69},
|
||||
{"table_foreach",136},
|
||||
{"table_getn",207},
|
||||
{"table_remove",226},
|
||||
{"table_move",355},
|
||||
{NULL,502}
|
||||
};
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** LuaJIT VM builder: PE object emitter.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Only used for building on Windows, since we cannot assume the presence
|
||||
** of a suitable assembler. The host and target byte order must match.
|
||||
|
@ -109,6 +109,8 @@ enum {
|
|||
#if LJ_TARGET_X64
|
||||
PEOBJ_SECT_PDATA,
|
||||
PEOBJ_SECT_XDATA,
|
||||
#elif LJ_TARGET_X86
|
||||
PEOBJ_SECT_SXDATA,
|
||||
#endif
|
||||
PEOBJ_SECT_RDATA_Z,
|
||||
PEOBJ_NSECTIONS
|
||||
|
@ -208,6 +210,13 @@ void emit_peobj(BuildCtx *ctx)
|
|||
sofs += (pesect[PEOBJ_SECT_XDATA].nreloc = 1) * PEOBJ_RELOC_SIZE;
|
||||
/* Flags: 40 = read, 30 = align4, 40 = initialized data. */
|
||||
pesect[PEOBJ_SECT_XDATA].flags = 0x40300040;
|
||||
#elif LJ_TARGET_X86
|
||||
memcpy(pesect[PEOBJ_SECT_SXDATA].name, ".sxdata", sizeof(".sxdata")-1);
|
||||
pesect[PEOBJ_SECT_SXDATA].ofs = sofs;
|
||||
sofs += (pesect[PEOBJ_SECT_SXDATA].size = 4);
|
||||
pesect[PEOBJ_SECT_SXDATA].relocofs = sofs;
|
||||
/* Flags: 40 = read, 30 = align4, 02 = lnk_info, 40 = initialized data. */
|
||||
pesect[PEOBJ_SECT_SXDATA].flags = 0x40300240;
|
||||
#endif
|
||||
|
||||
memcpy(pesect[PEOBJ_SECT_RDATA_Z].name, ".rdata$Z", sizeof(".rdata$Z")-1);
|
||||
|
@ -232,7 +241,7 @@ void emit_peobj(BuildCtx *ctx)
|
|||
nrsym = ctx->nrelocsym;
|
||||
pehdr.nsyms = 1+PEOBJ_NSECTIONS*2 + 1+ctx->nsym + nrsym;
|
||||
#if LJ_TARGET_X64
|
||||
pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win64. */
|
||||
pehdr.nsyms += 1; /* Symbol for lj_err_unwind_win. */
|
||||
#endif
|
||||
|
||||
/* Write PE object header and all sections. */
|
||||
|
@ -312,6 +321,19 @@ void emit_peobj(BuildCtx *ctx)
|
|||
reloc.type = PEOBJ_RELOC_ADDR32NB;
|
||||
owrite(ctx, &reloc, PEOBJ_RELOC_SIZE);
|
||||
}
|
||||
#elif LJ_TARGET_X86
|
||||
/* Write .sxdata section. */
|
||||
for (i = 0; i < nrsym; i++) {
|
||||
if (!strcmp(ctx->relocsym[i], "_lj_err_unwind_win")) {
|
||||
uint32_t symidx = 1+2+i;
|
||||
owrite(ctx, &symidx, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == nrsym) {
|
||||
fprintf(stderr, "Error: extern lj_err_unwind_win not used\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Write .rdata$Z section. */
|
||||
|
@ -333,8 +355,10 @@ void emit_peobj(BuildCtx *ctx)
|
|||
#if LJ_TARGET_X64
|
||||
emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_PDATA);
|
||||
emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_XDATA);
|
||||
emit_peobj_sym(ctx, "lj_err_unwind_win64", 0,
|
||||
emit_peobj_sym(ctx, "lj_err_unwind_win", 0,
|
||||
PEOBJ_SECT_UNDEF, PEOBJ_TYPE_FUNC, PEOBJ_SCL_EXTERN);
|
||||
#elif LJ_TARGET_X86
|
||||
emit_peobj_sym_sect(ctx, pesect, PEOBJ_SECT_SXDATA);
|
||||
#endif
|
||||
|
||||
emit_peobj_sym(ctx, ctx->beginsym, 0,
|
||||
|
|
|
@ -0,0 +1,197 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- 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.
|
||||
----------------------------------------------------------------------------
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
local ffi = require("ffi")
|
||||
local bit = require("bit")
|
||||
local vmdef = require("jit.vmdef")
|
||||
local bcnames = vmdef.bcnames
|
||||
|
||||
local format = string.format
|
||||
|
||||
local isbe = (string.byte(string.dump(function() end), 5) % 2 == 1)
|
||||
|
||||
local function usage(arg)
|
||||
io.stderr:write("Usage: ", arg and arg[0] or "genlibbc",
|
||||
" [-o buildvm_libbc.h] lib_*.c\n")
|
||||
os.exit(1)
|
||||
end
|
||||
|
||||
local function parse_arg(arg)
|
||||
local outfile = "-"
|
||||
if not (arg and arg[1]) then
|
||||
usage(arg)
|
||||
end
|
||||
if arg[1] == "-o" then
|
||||
outfile = arg[2]
|
||||
if not outfile then usage(arg) end
|
||||
table.remove(arg, 1)
|
||||
table.remove(arg, 1)
|
||||
end
|
||||
return outfile
|
||||
end
|
||||
|
||||
local function read_files(names)
|
||||
local src = ""
|
||||
for _,name in ipairs(names) do
|
||||
local fp = assert(io.open(name))
|
||||
src = src .. fp:read("*a")
|
||||
fp:close()
|
||||
end
|
||||
return src
|
||||
end
|
||||
|
||||
local function transform_lua(code)
|
||||
local fixup = {}
|
||||
local n = -30000
|
||||
code = string.gsub(code, "CHECK_(%w*)%((.-)%)", function(tp, var)
|
||||
n = n + 1
|
||||
fixup[n] = { "CHECK", tp }
|
||||
return format("%s=%d", var, n)
|
||||
end)
|
||||
code = string.gsub(code, "PAIRS%((.-)%)", function(var)
|
||||
fixup.PAIRS = true
|
||||
return format("nil, %s, 0", var)
|
||||
end)
|
||||
return "return "..code, fixup
|
||||
end
|
||||
|
||||
local function read_uleb128(p)
|
||||
local v = p[0]; p = p + 1
|
||||
if v >= 128 then
|
||||
local sh = 7; v = v - 128
|
||||
repeat
|
||||
local r = p[0]
|
||||
v = v + bit.lshift(bit.band(r, 127), sh)
|
||||
sh = sh + 7
|
||||
p = p + 1
|
||||
until r < 128
|
||||
end
|
||||
return p, v
|
||||
end
|
||||
|
||||
-- ORDER LJ_T
|
||||
local name2itype = {
|
||||
str = 5, func = 9, tab = 12, int = 14, num = 15
|
||||
}
|
||||
|
||||
local BC = {}
|
||||
for i=0,#bcnames/6-1 do
|
||||
BC[string.gsub(string.sub(bcnames, i*6+1, i*6+6), " ", "")] = i
|
||||
end
|
||||
local xop, xra = isbe and 3 or 0, isbe and 2 or 1
|
||||
local xrc, xrb = isbe and 1 or 2, isbe and 0 or 3
|
||||
|
||||
local function fixup_dump(dump, fixup)
|
||||
local buf = ffi.new("uint8_t[?]", #dump+1, dump)
|
||||
local p = buf+5
|
||||
local n, sizebc
|
||||
p, n = read_uleb128(p)
|
||||
local start = p
|
||||
p = p + 4
|
||||
p = read_uleb128(p)
|
||||
p = read_uleb128(p)
|
||||
p, sizebc = read_uleb128(p)
|
||||
local rawtab = {}
|
||||
for i=0,sizebc-1 do
|
||||
local op = p[xop]
|
||||
if op == BC.KSHORT then
|
||||
local rd = p[xrc] + 256*p[xrb]
|
||||
rd = bit.arshift(bit.lshift(rd, 16), 16)
|
||||
local f = fixup[rd]
|
||||
if f then
|
||||
if f[1] == "CHECK" then
|
||||
local tp = f[2]
|
||||
if tp == "tab" then rawtab[p[xra]] = true end
|
||||
p[xop] = tp == "num" and BC.ISNUM or BC.ISTYPE
|
||||
p[xrb] = 0
|
||||
p[xrc] = name2itype[tp]
|
||||
else
|
||||
error("unhandled fixup type: "..f[1])
|
||||
end
|
||||
end
|
||||
elseif op == BC.TGETV then
|
||||
if rawtab[p[xrb]] then
|
||||
p[xop] = BC.TGETR
|
||||
end
|
||||
elseif op == BC.TSETV then
|
||||
if rawtab[p[xrb]] then
|
||||
p[xop] = BC.TSETR
|
||||
end
|
||||
elseif op == BC.ITERC then
|
||||
if fixup.PAIRS then
|
||||
p[xop] = BC.ITERN
|
||||
end
|
||||
end
|
||||
p = p + 4
|
||||
end
|
||||
return ffi.string(start, n)
|
||||
end
|
||||
|
||||
local function find_defs(src)
|
||||
local defs = {}
|
||||
for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do
|
||||
local env = {}
|
||||
local tcode, fixup = transform_lua(code)
|
||||
local func = assert(load(tcode, "", nil, env))()
|
||||
defs[name] = fixup_dump(string.dump(func, true), fixup)
|
||||
defs[#defs+1] = name
|
||||
end
|
||||
return defs
|
||||
end
|
||||
|
||||
local function gen_header(defs)
|
||||
local t = {}
|
||||
local function w(x) t[#t+1] = x end
|
||||
w("/* This is a generated file. DO NOT EDIT! */\n\n")
|
||||
w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n")
|
||||
local s = ""
|
||||
for _,name in ipairs(defs) do
|
||||
s = s .. defs[name]
|
||||
end
|
||||
w("static const uint8_t libbc_code[] = {\n")
|
||||
local n = 0
|
||||
for i=1,#s do
|
||||
local x = string.byte(s, i)
|
||||
w(x); w(",")
|
||||
n = n + (x < 10 and 2 or (x < 100 and 3 or 4))
|
||||
if n >= 75 then n = 0; w("\n") end
|
||||
end
|
||||
w("0\n};\n\n")
|
||||
w("static const struct { const char *name; int ofs; } libbc_map[] = {\n")
|
||||
local m = 0
|
||||
for _,name in ipairs(defs) do
|
||||
w('{"'); w(name); w('",'); w(m) w('},\n')
|
||||
m = m + #defs[name]
|
||||
end
|
||||
w("{NULL,"); w(m); w("}\n};\n\n")
|
||||
return table.concat(t)
|
||||
end
|
||||
|
||||
local function write_file(name, data)
|
||||
if name == "-" then
|
||||
assert(io.write(data))
|
||||
assert(io.flush())
|
||||
else
|
||||
local fp = io.open(name)
|
||||
if fp then
|
||||
local old = fp:read("*a")
|
||||
fp:close()
|
||||
if data == old then return end
|
||||
end
|
||||
fp = assert(io.open(name, "w"))
|
||||
assert(fp:write(data))
|
||||
assert(fp:close())
|
||||
end
|
||||
end
|
||||
|
||||
local outfile = parse_arg(arg)
|
||||
local src = read_files(arg)
|
||||
local defs = find_defs(src)
|
||||
local hdr = gen_header(defs)
|
||||
write_file(outfile, hdr)
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
-- Lua script to generate a customized, minified version of Lua.
|
||||
-- The resulting 'minilua' is used for the build process of LuaJIT.
|
||||
----------------------------------------------------------------------------
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
|
@ -157,11 +157,11 @@ local function merge_includes(src)
|
|||
if includes[name] then return "" end
|
||||
includes[name] = true
|
||||
local fp = assert(io.open(LUA_SOURCE..name, "r"))
|
||||
local src = fp:read("*a")
|
||||
local inc = fp:read("*a")
|
||||
assert(fp:close())
|
||||
src = gsub(src, "#ifndef%s+%w+_h\n#define%s+%w+_h\n", "")
|
||||
src = gsub(src, "#endif%s*$", "")
|
||||
return merge_includes(src)
|
||||
inc = gsub(inc, "#ifndef%s+%w+_h\n#define%s+%w+_h\n", "")
|
||||
inc = gsub(inc, "#endif%s*$", "")
|
||||
return merge_includes(inc)
|
||||
end)
|
||||
end
|
||||
|
||||
|
@ -300,6 +300,7 @@ local function strip_unused3(src)
|
|||
src = gsub(src, "if%([^\n]*hookmask[^\n]*&&\n[^\n]*%b{}\n", "")
|
||||
src = gsub(src, "(twoto%b()%()", "%1(size_t)")
|
||||
src = gsub(src, "i<sizenode", "i<(int)sizenode")
|
||||
src = gsub(src, "cast%(unsigned int,key%-1%)", "cast(unsigned int,key)-1")
|
||||
return gsub(src, "\n\n+", "\n")
|
||||
end
|
||||
|
||||
|
|
|
@ -1606,7 +1606,7 @@ luaC_barriert(L,t,key);
|
|||
return gval(mp);
|
||||
}
|
||||
static const TValue*luaH_getnum(Table*t,int key){
|
||||
if(cast(unsigned int,key-1)<cast(unsigned int,t->sizearray))
|
||||
if(cast(unsigned int,key)-1<cast(unsigned int,t->sizearray))
|
||||
return&t->array[key-1];
|
||||
else{
|
||||
lua_Number nk=cast_num(key);
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
vmdef.lua
|
|
@ -1,7 +1,7 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT bytecode listing module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
|
@ -41,7 +41,7 @@
|
|||
|
||||
-- Cache some library functions and objects.
|
||||
local jit = require("jit")
|
||||
assert(jit.version_num == 20004, "LuaJIT core/library version mismatch")
|
||||
assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
|
||||
local jutil = require("jit.util")
|
||||
local vmdef = require("jit.vmdef")
|
||||
local bit = require("bit")
|
||||
|
@ -179,13 +179,12 @@ local function bcliston(outfile)
|
|||
end
|
||||
|
||||
-- Public module functions.
|
||||
module(...)
|
||||
|
||||
line = bcline
|
||||
dump = bcdump
|
||||
targets = bctargets
|
||||
|
||||
on = bcliston
|
||||
off = bclistoff
|
||||
start = bcliston -- For -j command line option.
|
||||
return {
|
||||
line = bcline,
|
||||
dump = bcdump,
|
||||
targets = bctargets,
|
||||
on = bcliston,
|
||||
off = bclistoff,
|
||||
start = bcliston -- For -j command line option.
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT module to save/list bytecode.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
|
@ -11,7 +11,7 @@
|
|||
------------------------------------------------------------------------------
|
||||
|
||||
local jit = require("jit")
|
||||
assert(jit.version_num == 20004, "LuaJIT core/library version mismatch")
|
||||
assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
|
||||
local bit = require("bit")
|
||||
|
||||
-- Symbol name prefix for LuaJIT bytecode.
|
||||
|
@ -63,8 +63,8 @@ local map_type = {
|
|||
}
|
||||
|
||||
local map_arch = {
|
||||
x86 = true, x64 = true, arm = true, ppc = true, ppcspe = true,
|
||||
mips = true, mipsel = true,
|
||||
x86 = true, x64 = true, arm = true, arm64 = true, arm64be = true,
|
||||
ppc = true, mips = true, mipsel = true,
|
||||
}
|
||||
|
||||
local map_os = {
|
||||
|
@ -125,12 +125,12 @@ extern "C"
|
|||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
const char %s%s[] = {
|
||||
const unsigned char %s%s[] = {
|
||||
]], LJBC_PREFIX, ctx.modname))
|
||||
else
|
||||
fp:write(string.format([[
|
||||
#define %s%s_SIZE %d
|
||||
static const char %s%s[] = {
|
||||
static const unsigned char %s%s[] = {
|
||||
]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname))
|
||||
end
|
||||
local t, n, m = {}, 0, 0
|
||||
|
@ -200,9 +200,9 @@ typedef struct {
|
|||
]]
|
||||
local symname = LJBC_PREFIX..ctx.modname
|
||||
local is64, isbe = false, false
|
||||
if ctx.arch == "x64" then
|
||||
if ctx.arch == "x64" or ctx.arch == "arm64" or ctx.arch == "arm64be" then
|
||||
is64 = true
|
||||
elseif ctx.arch == "ppc" or ctx.arch == "ppcspe" or ctx.arch == "mips" then
|
||||
elseif ctx.arch == "ppc" or ctx.arch == "mips" then
|
||||
isbe = true
|
||||
end
|
||||
|
||||
|
@ -237,9 +237,9 @@ typedef struct {
|
|||
hdr.eendian = isbe and 2 or 1
|
||||
hdr.eversion = 1
|
||||
hdr.type = f16(1)
|
||||
hdr.machine = f16(({ x86=3, x64=62, arm=40, ppc=20, ppcspe=20, mips=8, mipsel=8 })[ctx.arch])
|
||||
hdr.machine = f16(({ x86=3, x64=62, arm=40, arm64=183, arm64be=183, ppc=20, mips=8, mipsel=8 })[ctx.arch])
|
||||
if ctx.arch == "mips" or ctx.arch == "mipsel" then
|
||||
hdr.flags = 0x50001006
|
||||
hdr.flags = f32(0x50001006)
|
||||
end
|
||||
hdr.version = f32(1)
|
||||
hdr.shofs = fofs(ffi.offsetof(o, "sect"))
|
||||
|
@ -477,13 +477,13 @@ typedef struct {
|
|||
} mach_obj_64;
|
||||
typedef struct {
|
||||
mach_fat_header fat;
|
||||
mach_fat_arch fat_arch[4];
|
||||
mach_fat_arch fat_arch[2];
|
||||
struct {
|
||||
mach_header hdr;
|
||||
mach_segment_command seg;
|
||||
mach_section sec;
|
||||
mach_symtab_command sym;
|
||||
} arch[4];
|
||||
} arch[2];
|
||||
mach_nlist sym_entry;
|
||||
uint8_t space[4096];
|
||||
} mach_fat_obj;
|
||||
|
@ -494,6 +494,8 @@ typedef struct {
|
|||
is64, align, mobj = true, 8, "mach_obj_64"
|
||||
elseif ctx.arch == "arm" then
|
||||
isfat, mobj = true, "mach_fat_obj"
|
||||
elseif ctx.arch == "arm64" then
|
||||
is64, align, isfat, mobj = true, 8, true, "mach_fat_obj"
|
||||
else
|
||||
check(ctx.arch == "x86", "unsupported architecture for OSX")
|
||||
end
|
||||
|
@ -503,8 +505,8 @@ typedef struct {
|
|||
-- Create Mach-O object and fill in header.
|
||||
local o = ffi.new(mobj)
|
||||
local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align)
|
||||
local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12,12,12} })[ctx.arch]
|
||||
local cpusubtype = ({ x86={3}, x64={3}, arm={3,6,9,11} })[ctx.arch]
|
||||
local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12}, arm64={0x01000007,0x0100000c} })[ctx.arch]
|
||||
local cpusubtype = ({ x86={3}, x64={3}, arm={3,9}, arm64={3,0} })[ctx.arch]
|
||||
if isfat then
|
||||
o.fat.magic = be32(0xcafebabe)
|
||||
o.fat.nfat_arch = be32(#cpusubtype)
|
||||
|
@ -653,7 +655,7 @@ end
|
|||
------------------------------------------------------------------------------
|
||||
|
||||
-- Public module functions.
|
||||
module(...)
|
||||
|
||||
start = docmd -- Process -b command line option.
|
||||
return {
|
||||
start = docmd -- Process -b command line option.
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT ARM disassembler module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||
|
@ -12,7 +12,7 @@
|
|||
|
||||
local type = type
|
||||
local sub, byte, format = string.sub, string.byte, string.format
|
||||
local match, gmatch, gsub = string.match, string.gmatch, string.gsub
|
||||
local match, gmatch = string.match, string.gmatch
|
||||
local concat = table.concat
|
||||
local bit = require("bit")
|
||||
local band, bor, ror, tohex = bit.band, bit.bor, bit.ror, bit.tohex
|
||||
|
@ -658,7 +658,7 @@ local function disass_block(ctx, ofs, len)
|
|||
end
|
||||
|
||||
-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
|
||||
local function create_(code, addr, out)
|
||||
local function create(code, addr, out)
|
||||
local ctx = {}
|
||||
ctx.code = code
|
||||
ctx.addr = addr or 0
|
||||
|
@ -670,20 +670,20 @@ local function create_(code, addr, out)
|
|||
end
|
||||
|
||||
-- Simple API: disassemble code (a string) at address and output via out.
|
||||
local function disass_(code, addr, out)
|
||||
create_(code, addr, out):disass()
|
||||
local function disass(code, addr, out)
|
||||
create(code, addr, out):disass()
|
||||
end
|
||||
|
||||
-- Return register name for RID.
|
||||
local function regname_(r)
|
||||
local function regname(r)
|
||||
if r < 16 then return map_gpr[r] end
|
||||
return "d"..(r-16)
|
||||
end
|
||||
|
||||
-- Public module functions.
|
||||
module(...)
|
||||
|
||||
create = create_
|
||||
disass = disass_
|
||||
regname = regname_
|
||||
return {
|
||||
create = create,
|
||||
disass = disass,
|
||||
regname = regname
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,12 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT ARM64BE disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- ARM64 instructions are always little-endian. So just forward to the
|
||||
-- common ARM64 disassembler module. All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
return require((string.match(..., ".*%.") or "").."dis_arm64")
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT MIPS disassembler module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- 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.
|
||||
|
@ -11,8 +11,8 @@
|
|||
------------------------------------------------------------------------------
|
||||
|
||||
local type = type
|
||||
local sub, byte, format = string.sub, string.byte, string.format
|
||||
local match, gmatch, gsub = string.match, string.gmatch, string.gsub
|
||||
local byte, format = string.byte, string.format
|
||||
local match, gmatch = string.match, string.gmatch
|
||||
local concat = table.concat
|
||||
local bit = require("bit")
|
||||
local band, bor, tohex = bit.band, bit.bor, bit.tohex
|
||||
|
@ -34,15 +34,17 @@ local map_special = {
|
|||
"jrS", "jalrD1S", "movzDST", "movnDST",
|
||||
"syscallY", "breakY", false, "sync",
|
||||
"mfhiD", "mthiS", "mfloD", "mtloS",
|
||||
false, false, false, false,
|
||||
"dsllvDST", false, "dsrlvDST", "dsravDST",
|
||||
"multST", "multuST", "divST", "divuST",
|
||||
false, false, false, false,
|
||||
"dmultST", "dmultuST", "ddivST", "ddivuST",
|
||||
"addDST", "addu|moveDST0", "subDST", "subu|neguDS0T",
|
||||
"andDST", "orDST", "xorDST", "nor|notDST0",
|
||||
"andDST", "or|moveDST0", "xorDST", "nor|notDST0",
|
||||
false, false, "sltDST", "sltuDST",
|
||||
false, false, false, false,
|
||||
"daddDST", "dadduDST", "dsubDST", "dsubuDST",
|
||||
"tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ",
|
||||
"teqSTZ", false, "tneSTZ",
|
||||
"teqSTZ", false, "tneSTZ", false,
|
||||
"dsllDTA", false, "dsrlDTA", "dsraDTA",
|
||||
"dsll32DTA", false, "dsrl32DTA", "dsra32DTA",
|
||||
}
|
||||
|
||||
local map_special2 = {
|
||||
|
@ -60,11 +62,17 @@ local map_bshfl = {
|
|||
[24] = "sehDT",
|
||||
}
|
||||
|
||||
local map_dbshfl = {
|
||||
shift = 6, mask = 31,
|
||||
[2] = "dsbhDT",
|
||||
[5] = "dshdDT",
|
||||
}
|
||||
|
||||
local map_special3 = {
|
||||
shift = 0, mask = 63,
|
||||
[0] = "extTSAK", [4] = "insTSAL",
|
||||
[32] = map_bshfl,
|
||||
[59] = "rdhwrTD",
|
||||
[0] = "extTSAK", [1] = "dextmTSAP", [3] = "dextTSAK",
|
||||
[4] = "insTSAL", [6] = "dinsuTSEQ", [7] = "dinsTSAL",
|
||||
[32] = map_bshfl, [36] = map_dbshfl, [59] = "rdhwrTD",
|
||||
}
|
||||
|
||||
local map_regimm = {
|
||||
|
@ -178,8 +186,8 @@ local map_cop1bc = {
|
|||
|
||||
local map_cop1 = {
|
||||
shift = 21, mask = 31,
|
||||
[0] = "mfc1TG", false, "cfc1TG", "mfhc1TG",
|
||||
"mtc1TG", false, "ctc1TG", "mthc1TG",
|
||||
[0] = "mfc1TG", "dmfc1TG", "cfc1TG", "mfhc1TG",
|
||||
"mtc1TG", "dmtc1TG", "ctc1TG", "mthc1TG",
|
||||
map_cop1bc, false, false, false,
|
||||
false, false, false, false,
|
||||
map_cop1s, map_cop1d, false, false,
|
||||
|
@ -213,16 +221,16 @@ local map_pri = {
|
|||
"andiTSU", "ori|liTS0U", "xoriTSU", "luiTU",
|
||||
map_cop0, map_cop1, false, map_cop1x,
|
||||
"beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB",
|
||||
false, false, false, false,
|
||||
map_special2, false, false, map_special3,
|
||||
"daddiTSI", "daddiuTSI", false, false,
|
||||
map_special2, "jalxJ", false, map_special3,
|
||||
"lbTSO", "lhTSO", "lwlTSO", "lwTSO",
|
||||
"lbuTSO", "lhuTSO", "lwrTSO", false,
|
||||
"sbTSO", "shTSO", "swlTSO", "swTSO",
|
||||
false, false, "swrTSO", "cacheNSO",
|
||||
"llTSO", "lwc1HSO", "lwc2TSO", "prefNSO",
|
||||
false, "ldc1HSO", "ldc2TSO", false,
|
||||
false, "ldc1HSO", "ldc2TSO", "ldTSO",
|
||||
"scTSO", "swc1HSO", "swc2TSO", false,
|
||||
false, "sdc1HSO", "sdc2TSO", false,
|
||||
false, "sdc1HSO", "sdc2TSO", "sdTSO",
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
@ -306,6 +314,8 @@ local function disass_ins(ctx)
|
|||
x = "f"..band(rshift(op, 21), 31)
|
||||
elseif p == "A" then
|
||||
x = band(rshift(op, 6), 31)
|
||||
elseif p == "E" then
|
||||
x = band(rshift(op, 6), 31) + 32
|
||||
elseif p == "M" then
|
||||
x = band(rshift(op, 11), 31)
|
||||
elseif p == "N" then
|
||||
|
@ -315,8 +325,12 @@ local function disass_ins(ctx)
|
|||
if x == 0 then x = nil end
|
||||
elseif p == "K" then
|
||||
x = band(rshift(op, 11), 31) + 1
|
||||
elseif p == "P" then
|
||||
x = band(rshift(op, 11), 31) + 33
|
||||
elseif p == "L" then
|
||||
x = band(rshift(op, 11), 31) - last + 1
|
||||
elseif p == "Q" then
|
||||
x = band(rshift(op, 11), 31) - last + 33
|
||||
elseif p == "I" then
|
||||
x = arshift(lshift(op, 16), 16)
|
||||
elseif p == "U" then
|
||||
|
@ -330,11 +344,12 @@ local function disass_ins(ctx)
|
|||
elseif p == "B" then
|
||||
x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 16)*4 + 4
|
||||
ctx.rel = x
|
||||
x = "0x"..tohex(x)
|
||||
x = format("0x%08x", x)
|
||||
elseif p == "J" then
|
||||
x = band(ctx.addr + ctx.pos, 0xf0000000) + band(op, 0x03ffffff)*4
|
||||
local a = ctx.addr + ctx.pos
|
||||
x = a - band(a, 0x0fffffff) + band(op, 0x03ffffff)*4
|
||||
ctx.rel = x
|
||||
x = "0x"..tohex(x)
|
||||
x = format("0x%08x", x)
|
||||
elseif p == "V" then
|
||||
x = band(rshift(op, 8), 7)
|
||||
if x == 0 then x = nil end
|
||||
|
@ -384,7 +399,7 @@ local function disass_block(ctx, ofs, len)
|
|||
end
|
||||
|
||||
-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
|
||||
local function create_(code, addr, out)
|
||||
local function create(code, addr, out)
|
||||
local ctx = {}
|
||||
ctx.code = code
|
||||
ctx.addr = addr or 0
|
||||
|
@ -396,33 +411,33 @@ local function create_(code, addr, out)
|
|||
return ctx
|
||||
end
|
||||
|
||||
local function create_el_(code, addr, out)
|
||||
local ctx = create_(code, addr, out)
|
||||
local function create_el(code, addr, out)
|
||||
local ctx = create(code, addr, out)
|
||||
ctx.get = get_le
|
||||
return ctx
|
||||
end
|
||||
|
||||
-- Simple API: disassemble code (a string) at address and output via out.
|
||||
local function disass_(code, addr, out)
|
||||
create_(code, addr, out):disass()
|
||||
local function disass(code, addr, out)
|
||||
create(code, addr, out):disass()
|
||||
end
|
||||
|
||||
local function disass_el_(code, addr, out)
|
||||
create_el_(code, addr, out):disass()
|
||||
local function disass_el(code, addr, out)
|
||||
create_el(code, addr, out):disass()
|
||||
end
|
||||
|
||||
-- Return register name for RID.
|
||||
local function regname_(r)
|
||||
local function regname(r)
|
||||
if r < 32 then return map_gpr[r] end
|
||||
return "f"..(r-32)
|
||||
end
|
||||
|
||||
-- Public module functions.
|
||||
module(...)
|
||||
|
||||
create = create_
|
||||
create_el = create_el_
|
||||
disass = disass_
|
||||
disass_el = disass_el_
|
||||
regname = regname_
|
||||
return {
|
||||
create = create,
|
||||
create_el = create_el,
|
||||
disass = disass,
|
||||
disass_el = disass_el,
|
||||
regname = regname
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT MIPS64 disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This module just exports the big-endian functions from the
|
||||
-- MIPS disassembler module. All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
|
||||
return {
|
||||
create = dis_mips.create,
|
||||
disass = dis_mips.disass,
|
||||
regname = dis_mips.regname
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT MIPS64EL disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This module just exports the little-endian functions from the
|
||||
-- MIPS disassembler module. All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
|
||||
return {
|
||||
create = dis_mips.create_el,
|
||||
disass = dis_mips.disass_el,
|
||||
regname = dis_mips.regname
|
||||
}
|
||||
|
|
@ -1,20 +1,17 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT MIPSEL disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This module just exports the little-endian functions from the
|
||||
-- MIPS disassembler module. All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local require = require
|
||||
|
||||
module(...)
|
||||
|
||||
local dis_mips = require(_PACKAGE.."dis_mips")
|
||||
|
||||
create = dis_mips.create_el
|
||||
disass = dis_mips.disass_el
|
||||
regname = dis_mips.regname
|
||||
local dis_mips = require((string.match(..., ".*%.") or "").."dis_mips")
|
||||
return {
|
||||
create = dis_mips.create_el,
|
||||
disass = dis_mips.disass_el,
|
||||
regname = dis_mips.regname
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT PPC disassembler module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- 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.
|
||||
|
@ -13,7 +13,7 @@
|
|||
------------------------------------------------------------------------------
|
||||
|
||||
local type = type
|
||||
local sub, byte, format = string.sub, string.byte, string.format
|
||||
local byte, format = string.byte, string.format
|
||||
local match, gmatch, gsub = string.match, string.gmatch, string.gsub
|
||||
local concat = table.concat
|
||||
local bit = require("bit")
|
||||
|
@ -560,7 +560,7 @@ local function disass_block(ctx, ofs, len)
|
|||
end
|
||||
|
||||
-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
|
||||
local function create_(code, addr, out)
|
||||
local function create(code, addr, out)
|
||||
local ctx = {}
|
||||
ctx.code = code
|
||||
ctx.addr = addr or 0
|
||||
|
@ -572,20 +572,20 @@ local function create_(code, addr, out)
|
|||
end
|
||||
|
||||
-- Simple API: disassemble code (a string) at address and output via out.
|
||||
local function disass_(code, addr, out)
|
||||
create_(code, addr, out):disass()
|
||||
local function disass(code, addr, out)
|
||||
create(code, addr, out):disass()
|
||||
end
|
||||
|
||||
-- Return register name for RID.
|
||||
local function regname_(r)
|
||||
local function regname(r)
|
||||
if r < 32 then return map_gpr[r] end
|
||||
return "f"..(r-32)
|
||||
end
|
||||
|
||||
-- Public module functions.
|
||||
module(...)
|
||||
|
||||
create = create_
|
||||
disass = disass_
|
||||
regname = regname_
|
||||
return {
|
||||
create = create,
|
||||
disass = disass,
|
||||
regname = regname
|
||||
}
|
||||
|
||||
|
|
|
@ -1,20 +1,17 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT x64 disassembler wrapper module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This module just exports the 64 bit functions from the combined
|
||||
-- x86/x64 disassembler module. All the interesting stuff is there.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local require = require
|
||||
|
||||
module(...)
|
||||
|
||||
local dis_x86 = require(_PACKAGE.."dis_x86")
|
||||
|
||||
create = dis_x86.create64
|
||||
disass = dis_x86.disass64
|
||||
regname = dis_x86.regname64
|
||||
local dis_x86 = require((string.match(..., ".*%.") or "").."dis_x86")
|
||||
return {
|
||||
create = dis_x86.create64,
|
||||
disass = dis_x86.disass64,
|
||||
regname = dis_x86.regname64
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT x86/x64 disassembler module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
-- This is a helper module used by the LuaJIT machine code dumper module.
|
||||
|
@ -15,19 +15,20 @@
|
|||
-- Intel and AMD manuals. The supported instruction set is quite extensive
|
||||
-- and reflects what a current generation Intel or AMD CPU implements in
|
||||
-- 32 bit and 64 bit mode. Yes, this includes MMX, SSE, SSE2, SSE3, SSSE3,
|
||||
-- SSE4.1, SSE4.2, SSE4a and even privileged and hypervisor (VMX/SVM)
|
||||
-- instructions.
|
||||
-- SSE4.1, SSE4.2, SSE4a, AVX, AVX2 and even privileged and hypervisor
|
||||
-- (VMX/SVM) instructions.
|
||||
--
|
||||
-- Notes:
|
||||
-- * The (useless) a16 prefix, 3DNow and pre-586 opcodes are unsupported.
|
||||
-- * No attempt at optimization has been made -- it's fast enough for my needs.
|
||||
-- * The public API may change when more architectures are added.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local type = type
|
||||
local sub, byte, format = string.sub, string.byte, string.format
|
||||
local match, gmatch, gsub = string.match, string.gmatch, string.gsub
|
||||
local lower, rep = string.lower, string.rep
|
||||
local bit = require("bit")
|
||||
local tohex = bit.tohex
|
||||
|
||||
-- Map for 1st opcode byte in 32 bit mode. Ugly? Well ... read on.
|
||||
local map_opc1_32 = {
|
||||
|
@ -76,7 +77,7 @@ local map_opc1_32 = {
|
|||
"movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi",
|
||||
"movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI",
|
||||
--Cx
|
||||
"shift!Bmu","shift!Vmu","retBw","ret","$lesVrm","$ldsVrm","movBmi","movVmi",
|
||||
"shift!Bmu","shift!Vmu","retBw","ret","vex*3$lesVrm","vex*2$ldsVrm","movBmi","movVmi",
|
||||
"enterBwu","leave","retfBw","retf","int3","intBu","into","iretVS",
|
||||
--Dx
|
||||
"shift!Bm1","shift!Vm1","shift!Bmc","shift!Vmc","aamBu","aadBu","salc","xlatb",
|
||||
|
@ -101,7 +102,7 @@ local map_opc1_64 = setmetatable({
|
|||
[0x44]="rex*r", [0x45]="rex*rb", [0x46]="rex*rx", [0x47]="rex*rxb",
|
||||
[0x48]="rex*w", [0x49]="rex*wb", [0x4a]="rex*wx", [0x4b]="rex*wxb",
|
||||
[0x4c]="rex*wr", [0x4d]="rex*wrb", [0x4e]="rex*wrx", [0x4f]="rex*wrxb",
|
||||
[0x82]=false, [0x9a]=false, [0xc4]=false, [0xc5]=false, [0xce]=false,
|
||||
[0x82]=false, [0x9a]=false, [0xc4]="vex*3", [0xc5]="vex*2", [0xce]=false,
|
||||
[0xd4]=false, [0xd5]=false, [0xd6]=false, [0xea]=false,
|
||||
}, { __index = map_opc1_32 })
|
||||
|
||||
|
@ -112,12 +113,12 @@ local map_opc2 = {
|
|||
[0]="sldt!Dmp","sgdt!Ump","larVrm","lslVrm",nil,"syscall","clts","sysret",
|
||||
"invd","wbinvd",nil,"ud1",nil,"$prefetch!Bm","femms","3dnowMrmu",
|
||||
--1x
|
||||
"movupsXrm|movssXrm|movupdXrm|movsdXrm",
|
||||
"movupsXmr|movssXmr|movupdXmr|movsdXmr",
|
||||
"movupsXrm|movssXrvm|movupdXrm|movsdXrvm",
|
||||
"movupsXmr|movssXmvr|movupdXmr|movsdXmvr",
|
||||
"movhlpsXrm$movlpsXrm|movsldupXrm|movlpdXrm|movddupXrm",
|
||||
"movlpsXmr||movlpdXmr",
|
||||
"unpcklpsXrm||unpcklpdXrm",
|
||||
"unpckhpsXrm||unpckhpdXrm",
|
||||
"unpcklpsXrvm||unpcklpdXrvm",
|
||||
"unpckhpsXrvm||unpckhpdXrvm",
|
||||
"movlhpsXrm$movhpsXrm|movshdupXrm|movhpdXrm",
|
||||
"movhpsXmr||movhpdXmr",
|
||||
"$prefetcht!Bm","hintnopVm","hintnopVm","hintnopVm",
|
||||
|
@ -126,7 +127,7 @@ local map_opc2 = {
|
|||
"movUmx$","movUmy$","movUxm$","movUym$","movUmz$",nil,"movUzm$",nil,
|
||||
"movapsXrm||movapdXrm",
|
||||
"movapsXmr||movapdXmr",
|
||||
"cvtpi2psXrMm|cvtsi2ssXrVmt|cvtpi2pdXrMm|cvtsi2sdXrVmt",
|
||||
"cvtpi2psXrMm|cvtsi2ssXrvVmt|cvtpi2pdXrMm|cvtsi2sdXrvVmt",
|
||||
"movntpsXmr|movntssXmr|movntpdXmr|movntsdXmr",
|
||||
"cvttps2piMrXm|cvttss2siVrXm|cvttpd2piMrXm|cvttsd2siVrXm",
|
||||
"cvtps2piMrXm|cvtss2siVrXm|cvtpd2piMrXm|cvtsd2siVrXm",
|
||||
|
@ -142,27 +143,27 @@ local map_opc2 = {
|
|||
"cmovlVrm","cmovgeVrm","cmovleVrm","cmovgVrm",
|
||||
--5x
|
||||
"movmskpsVrXm$||movmskpdVrXm$","sqrtpsXrm|sqrtssXrm|sqrtpdXrm|sqrtsdXrm",
|
||||
"rsqrtpsXrm|rsqrtssXrm","rcppsXrm|rcpssXrm",
|
||||
"andpsXrm||andpdXrm","andnpsXrm||andnpdXrm",
|
||||
"orpsXrm||orpdXrm","xorpsXrm||xorpdXrm",
|
||||
"addpsXrm|addssXrm|addpdXrm|addsdXrm","mulpsXrm|mulssXrm|mulpdXrm|mulsdXrm",
|
||||
"cvtps2pdXrm|cvtss2sdXrm|cvtpd2psXrm|cvtsd2ssXrm",
|
||||
"rsqrtpsXrm|rsqrtssXrvm","rcppsXrm|rcpssXrvm",
|
||||
"andpsXrvm||andpdXrvm","andnpsXrvm||andnpdXrvm",
|
||||
"orpsXrvm||orpdXrvm","xorpsXrvm||xorpdXrvm",
|
||||
"addpsXrvm|addssXrvm|addpdXrvm|addsdXrvm","mulpsXrvm|mulssXrvm|mulpdXrvm|mulsdXrvm",
|
||||
"cvtps2pdXrm|cvtss2sdXrvm|cvtpd2psXrm|cvtsd2ssXrvm",
|
||||
"cvtdq2psXrm|cvttps2dqXrm|cvtps2dqXrm",
|
||||
"subpsXrm|subssXrm|subpdXrm|subsdXrm","minpsXrm|minssXrm|minpdXrm|minsdXrm",
|
||||
"divpsXrm|divssXrm|divpdXrm|divsdXrm","maxpsXrm|maxssXrm|maxpdXrm|maxsdXrm",
|
||||
"subpsXrvm|subssXrvm|subpdXrvm|subsdXrvm","minpsXrvm|minssXrvm|minpdXrvm|minsdXrvm",
|
||||
"divpsXrvm|divssXrvm|divpdXrvm|divsdXrvm","maxpsXrvm|maxssXrvm|maxpdXrvm|maxsdXrvm",
|
||||
--6x
|
||||
"punpcklbwPrm","punpcklwdPrm","punpckldqPrm","packsswbPrm",
|
||||
"pcmpgtbPrm","pcmpgtwPrm","pcmpgtdPrm","packuswbPrm",
|
||||
"punpckhbwPrm","punpckhwdPrm","punpckhdqPrm","packssdwPrm",
|
||||
"||punpcklqdqXrm","||punpckhqdqXrm",
|
||||
"punpcklbwPrvm","punpcklwdPrvm","punpckldqPrvm","packsswbPrvm",
|
||||
"pcmpgtbPrvm","pcmpgtwPrvm","pcmpgtdPrvm","packuswbPrvm",
|
||||
"punpckhbwPrvm","punpckhwdPrvm","punpckhdqPrvm","packssdwPrvm",
|
||||
"||punpcklqdqXrvm","||punpckhqdqXrvm",
|
||||
"movPrVSm","movqMrm|movdquXrm|movdqaXrm",
|
||||
--7x
|
||||
"pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pmu",
|
||||
"pshiftd!Pmu","pshiftq!Mmu||pshiftdq!Xmu",
|
||||
"pcmpeqbPrm","pcmpeqwPrm","pcmpeqdPrm","emms|",
|
||||
"pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pvmu",
|
||||
"pshiftd!Pvmu","pshiftq!Mvmu||pshiftdq!Xvmu",
|
||||
"pcmpeqbPrvm","pcmpeqwPrvm","pcmpeqdPrvm","emms*|",
|
||||
"vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$",
|
||||
nil,nil,
|
||||
"||haddpdXrm|haddpsXrm","||hsubpdXrm|hsubpsXrm",
|
||||
"||haddpdXrvm|haddpsXrvm","||hsubpdXrvm|hsubpsXrvm",
|
||||
"movVSmMr|movqXrm|movVSmXr","movqMmr|movdquXmr|movdqaXmr",
|
||||
--8x
|
||||
"joVj","jnoVj","jbVj","jnbVj","jzVj","jnzVj","jbeVj","jaVj",
|
||||
|
@ -180,27 +181,27 @@ nil,nil,
|
|||
"bsfVrm","bsrVrm|lzcntVrm|bsrWrm","movsxVrBmt","movsxVrWmt",
|
||||
--Cx
|
||||
"xaddBmr","xaddVmr",
|
||||
"cmppsXrmu|cmpssXrmu|cmppdXrmu|cmpsdXrmu","$movntiVmr|",
|
||||
"pinsrwPrWmu","pextrwDrPmu",
|
||||
"shufpsXrmu||shufpdXrmu","$cmpxchg!Qmp",
|
||||
"cmppsXrvmu|cmpssXrvmu|cmppdXrvmu|cmpsdXrvmu","$movntiVmr|",
|
||||
"pinsrwPrvWmu","pextrwDrPmu",
|
||||
"shufpsXrvmu||shufpdXrvmu","$cmpxchg!Qmp",
|
||||
"bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR",
|
||||
--Dx
|
||||
"||addsubpdXrm|addsubpsXrm","psrlwPrm","psrldPrm","psrlqPrm",
|
||||
"paddqPrm","pmullwPrm",
|
||||
"||addsubpdXrvm|addsubpsXrvm","psrlwPrvm","psrldPrvm","psrlqPrvm",
|
||||
"paddqPrvm","pmullwPrvm",
|
||||
"|movq2dqXrMm|movqXmr|movdq2qMrXm$","pmovmskbVrMm||pmovmskbVrXm",
|
||||
"psubusbPrm","psubuswPrm","pminubPrm","pandPrm",
|
||||
"paddusbPrm","padduswPrm","pmaxubPrm","pandnPrm",
|
||||
"psubusbPrvm","psubuswPrvm","pminubPrvm","pandPrvm",
|
||||
"paddusbPrvm","padduswPrvm","pmaxubPrvm","pandnPrvm",
|
||||
--Ex
|
||||
"pavgbPrm","psrawPrm","psradPrm","pavgwPrm",
|
||||
"pmulhuwPrm","pmulhwPrm",
|
||||
"pavgbPrvm","psrawPrvm","psradPrvm","pavgwPrvm",
|
||||
"pmulhuwPrvm","pmulhwPrvm",
|
||||
"|cvtdq2pdXrm|cvttpd2dqXrm|cvtpd2dqXrm","$movntqMmr||$movntdqXmr",
|
||||
"psubsbPrm","psubswPrm","pminswPrm","porPrm",
|
||||
"paddsbPrm","paddswPrm","pmaxswPrm","pxorPrm",
|
||||
"psubsbPrvm","psubswPrvm","pminswPrvm","porPrvm",
|
||||
"paddsbPrvm","paddswPrvm","pmaxswPrvm","pxorPrvm",
|
||||
--Fx
|
||||
"|||lddquXrm","psllwPrm","pslldPrm","psllqPrm",
|
||||
"pmuludqPrm","pmaddwdPrm","psadbwPrm","maskmovqMrm||maskmovdquXrm$",
|
||||
"psubbPrm","psubwPrm","psubdPrm","psubqPrm",
|
||||
"paddbPrm","paddwPrm","padddPrm","ud",
|
||||
"|||lddquXrm","psllwPrvm","pslldPrvm","psllqPrvm",
|
||||
"pmuludqPrvm","pmaddwdPrvm","psadbwPrvm","maskmovqMrm||maskmovdquXrm$",
|
||||
"psubbPrvm","psubwPrvm","psubdPrvm","psubqPrvm",
|
||||
"paddbPrvm","paddwPrvm","padddPrvm","ud",
|
||||
}
|
||||
assert(map_opc2[255] == "ud")
|
||||
|
||||
|
@ -208,49 +209,73 @@ assert(map_opc2[255] == "ud")
|
|||
local map_opc3 = {
|
||||
["38"] = { -- [66] 0f 38 xx
|
||||
--0x
|
||||
[0]="pshufbPrm","phaddwPrm","phadddPrm","phaddswPrm",
|
||||
"pmaddubswPrm","phsubwPrm","phsubdPrm","phsubswPrm",
|
||||
"psignbPrm","psignwPrm","psigndPrm","pmulhrswPrm",
|
||||
nil,nil,nil,nil,
|
||||
[0]="pshufbPrvm","phaddwPrvm","phadddPrvm","phaddswPrvm",
|
||||
"pmaddubswPrvm","phsubwPrvm","phsubdPrvm","phsubswPrvm",
|
||||
"psignbPrvm","psignwPrvm","psigndPrvm","pmulhrswPrvm",
|
||||
"||permilpsXrvm","||permilpdXrvm",nil,nil,
|
||||
--1x
|
||||
"||pblendvbXrma",nil,nil,nil,
|
||||
"||blendvpsXrma","||blendvpdXrma",nil,"||ptestXrm",
|
||||
nil,nil,nil,nil,
|
||||
"||blendvpsXrma","||blendvpdXrma","||permpsXrvm","||ptestXrm",
|
||||
"||broadcastssXrm","||broadcastsdXrm","||broadcastf128XrlXm",nil,
|
||||
"pabsbPrm","pabswPrm","pabsdPrm",nil,
|
||||
--2x
|
||||
"||pmovsxbwXrm","||pmovsxbdXrm","||pmovsxbqXrm","||pmovsxwdXrm",
|
||||
"||pmovsxwqXrm","||pmovsxdqXrm",nil,nil,
|
||||
"||pmuldqXrm","||pcmpeqqXrm","||$movntdqaXrm","||packusdwXrm",
|
||||
nil,nil,nil,nil,
|
||||
"||pmuldqXrvm","||pcmpeqqXrvm","||$movntdqaXrm","||packusdwXrvm",
|
||||
"||maskmovpsXrvm","||maskmovpdXrvm","||maskmovpsXmvr","||maskmovpdXmvr",
|
||||
--3x
|
||||
"||pmovzxbwXrm","||pmovzxbdXrm","||pmovzxbqXrm","||pmovzxwdXrm",
|
||||
"||pmovzxwqXrm","||pmovzxdqXrm",nil,"||pcmpgtqXrm",
|
||||
"||pminsbXrm","||pminsdXrm","||pminuwXrm","||pminudXrm",
|
||||
"||pmaxsbXrm","||pmaxsdXrm","||pmaxuwXrm","||pmaxudXrm",
|
||||
"||pmovzxwqXrm","||pmovzxdqXrm","||permdXrvm","||pcmpgtqXrvm",
|
||||
"||pminsbXrvm","||pminsdXrvm","||pminuwXrvm","||pminudXrvm",
|
||||
"||pmaxsbXrvm","||pmaxsdXrvm","||pmaxuwXrvm","||pmaxudXrvm",
|
||||
--4x
|
||||
"||pmulddXrm","||phminposuwXrm",
|
||||
"||pmulddXrvm","||phminposuwXrm",nil,nil,
|
||||
nil,"||psrlvVSXrvm","||psravdXrvm","||psllvVSXrvm",
|
||||
--5x
|
||||
[0x58] = "||pbroadcastdXrlXm",[0x59] = "||pbroadcastqXrlXm",
|
||||
[0x5a] = "||broadcasti128XrlXm",
|
||||
--7x
|
||||
[0x78] = "||pbroadcastbXrlXm",[0x79] = "||pbroadcastwXrlXm",
|
||||
--8x
|
||||
[0x8c] = "||pmaskmovXrvVSm",
|
||||
[0x8e] = "||pmaskmovVSmXvr",
|
||||
--Dx
|
||||
[0xdc] = "||aesencXrvm", [0xdd] = "||aesenclastXrvm",
|
||||
[0xde] = "||aesdecXrvm", [0xdf] = "||aesdeclastXrvm",
|
||||
--Fx
|
||||
[0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt",
|
||||
[0xf7] = "| sarxVrmv| shlxVrmv| shrxVrmv",
|
||||
},
|
||||
|
||||
["3a"] = { -- [66] 0f 3a xx
|
||||
--0x
|
||||
[0x00]=nil,nil,nil,nil,nil,nil,nil,nil,
|
||||
"||roundpsXrmu","||roundpdXrmu","||roundssXrmu","||roundsdXrmu",
|
||||
"||blendpsXrmu","||blendpdXrmu","||pblendwXrmu","palignrPrmu",
|
||||
[0x00]="||permqXrmu","||permpdXrmu","||pblenddXrvmu",nil,
|
||||
"||permilpsXrmu","||permilpdXrmu","||perm2f128Xrvmu",nil,
|
||||
"||roundpsXrmu","||roundpdXrmu","||roundssXrvmu","||roundsdXrvmu",
|
||||
"||blendpsXrvmu","||blendpdXrvmu","||pblendwXrvmu","palignrPrvmu",
|
||||
--1x
|
||||
nil,nil,nil,nil,
|
||||
"||pextrbVmXru","||pextrwVmXru","||pextrVmSXru","||extractpsVmXru",
|
||||
nil,nil,nil,nil,nil,nil,nil,nil,
|
||||
"||insertf128XrvlXmu","||extractf128XlXmYru",nil,nil,
|
||||
nil,nil,nil,nil,
|
||||
--2x
|
||||
"||pinsrbXrVmu","||insertpsXrmu","||pinsrXrVmuS",nil,
|
||||
"||pinsrbXrvVmu","||insertpsXrvmu","||pinsrXrvVmuS",nil,
|
||||
--3x
|
||||
[0x38] = "||inserti128Xrvmu",[0x39] = "||extracti128XlXmYru",
|
||||
--4x
|
||||
[0x40] = "||dppsXrmu",
|
||||
[0x41] = "||dppdXrmu",
|
||||
[0x42] = "||mpsadbwXrmu",
|
||||
[0x40] = "||dppsXrvmu",
|
||||
[0x41] = "||dppdXrvmu",
|
||||
[0x42] = "||mpsadbwXrvmu",
|
||||
[0x44] = "||pclmulqdqXrvmu",
|
||||
[0x46] = "||perm2i128Xrvmu",
|
||||
[0x4a] = "||blendvpsXrvmb",[0x4b] = "||blendvpdXrvmb",
|
||||
[0x4c] = "||pblendvbXrvmb",
|
||||
--6x
|
||||
[0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu",
|
||||
[0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu",
|
||||
[0xdf] = "||aeskeygenassistXrmu",
|
||||
--Fx
|
||||
[0xf0] = "||| rorxVrmu",
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -354,17 +379,19 @@ local map_regs = {
|
|||
"mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, -- No x64 ext!
|
||||
X = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
|
||||
"xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" },
|
||||
Y = { "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7",
|
||||
"ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15" },
|
||||
}
|
||||
local map_segregs = { "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7" }
|
||||
|
||||
-- Maps for size names.
|
||||
local map_sz2n = {
|
||||
B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16,
|
||||
B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16, Y = 32,
|
||||
}
|
||||
local map_sz2prefix = {
|
||||
B = "byte", W = "word", D = "dword",
|
||||
Q = "qword",
|
||||
M = "qword", X = "xword",
|
||||
M = "qword", X = "xword", Y = "yword",
|
||||
F = "dword", G = "qword", -- No need for sizes/register names for these two.
|
||||
}
|
||||
|
||||
|
@ -387,10 +414,13 @@ local function putop(ctx, text, operands)
|
|||
if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end
|
||||
if ctx.rex then
|
||||
local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "")..
|
||||
(ctx.rexx and "x" or "")..(ctx.rexb and "b" or "")
|
||||
if t ~= "" then text = "rex."..t.." "..text end
|
||||
(ctx.rexx and "x" or "")..(ctx.rexb and "b" or "")..
|
||||
(ctx.vexl and "l" or "")
|
||||
if ctx.vexv and ctx.vexv ~= 0 then t = t.."v"..ctx.vexv end
|
||||
if t ~= "" then text = ctx.rex.."."..t.." "..gsub(text, "^ ", "")
|
||||
elseif ctx.rex == "vex" then text = gsub("v"..text, "^v ", "") end
|
||||
ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false
|
||||
ctx.rex = false
|
||||
ctx.rex = false; ctx.vexl = false; ctx.vexv = false
|
||||
end
|
||||
if ctx.seg then
|
||||
local text2, n = gsub(text, "%[", "["..ctx.seg..":")
|
||||
|
@ -405,6 +435,7 @@ local function putop(ctx, text, operands)
|
|||
end
|
||||
ctx.out(format("%08x %s%s\n", ctx.addr+ctx.start, hex, text))
|
||||
ctx.mrm = false
|
||||
ctx.vexv = false
|
||||
ctx.start = pos
|
||||
ctx.imm = nil
|
||||
end
|
||||
|
@ -413,7 +444,7 @@ end
|
|||
local function clearprefixes(ctx)
|
||||
ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false
|
||||
ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false
|
||||
ctx.rex = false; ctx.a32 = false
|
||||
ctx.rex = false; ctx.a32 = false; ctx.vexl = false
|
||||
end
|
||||
|
||||
-- Fallback for incomplete opcodes at the end.
|
||||
|
@ -450,9 +481,9 @@ end
|
|||
-- Process pattern string and generate the operands.
|
||||
local function putpat(ctx, name, pat)
|
||||
local operands, regs, sz, mode, sp, rm, sc, rx, sdisp
|
||||
local code, pos, stop = ctx.code, ctx.pos, ctx.stop
|
||||
local code, pos, stop, vexl = ctx.code, ctx.pos, ctx.stop, ctx.vexl
|
||||
|
||||
-- Chars used: 1DFGIMPQRSTUVWXacdfgijmoprstuwxyz
|
||||
-- Chars used: 1DFGIMPQRSTUVWXYabcdfgijlmoprstuvwxyz
|
||||
for p in gmatch(pat, ".") do
|
||||
local x = nil
|
||||
if p == "V" or p == "U" then
|
||||
|
@ -467,11 +498,13 @@ local function putpat(ctx, name, pat)
|
|||
elseif p == "B" then
|
||||
sz = "B"
|
||||
regs = ctx.rex and map_regs.B64 or map_regs.B
|
||||
elseif match(p, "[WDQMXFG]") then
|
||||
elseif match(p, "[WDQMXYFG]") then
|
||||
sz = p
|
||||
if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end
|
||||
regs = map_regs[sz]
|
||||
elseif p == "P" then
|
||||
sz = ctx.o16 and "X" or "M"; ctx.o16 = false
|
||||
if sz == "X" and vexl then sz = "Y"; ctx.vexl = false end
|
||||
regs = map_regs[sz]
|
||||
elseif p == "S" then
|
||||
name = name..lower(sz)
|
||||
|
@ -484,6 +517,10 @@ local function putpat(ctx, name, pat)
|
|||
local imm = getimm(ctx, pos, 1); if not imm then return end
|
||||
x = format("0x%02x", imm)
|
||||
pos = pos+1
|
||||
elseif p == "b" then
|
||||
local imm = getimm(ctx, pos, 1); if not imm then return end
|
||||
x = regs[imm/16+1]
|
||||
pos = pos+1
|
||||
elseif p == "w" then
|
||||
local imm = getimm(ctx, pos, 2); if not imm then return end
|
||||
x = format("0x%x", imm)
|
||||
|
@ -532,7 +569,7 @@ local function putpat(ctx, name, pat)
|
|||
local lo = imm % 0x1000000
|
||||
x = format("0x%02x%06x", (imm-lo) / 0x1000000, lo)
|
||||
else
|
||||
x = format("0x%08x", imm)
|
||||
x = "0x"..tohex(imm)
|
||||
end
|
||||
elseif p == "R" then
|
||||
local r = byte(code, pos-1, pos-1)%8
|
||||
|
@ -616,8 +653,13 @@ local function putpat(ctx, name, pat)
|
|||
else
|
||||
x = "CR"..sp
|
||||
end
|
||||
elseif p == "v" then
|
||||
if ctx.vexv then
|
||||
x = regs[ctx.vexv+1]; ctx.vexv = false
|
||||
end
|
||||
elseif p == "y" then x = "DR"..sp
|
||||
elseif p == "z" then x = "TR"..sp
|
||||
elseif p == "l" then vexl = false
|
||||
elseif p == "t" then
|
||||
else
|
||||
error("bad pattern `"..pat.."'")
|
||||
|
@ -692,7 +734,7 @@ map_act = {
|
|||
B = putpat, W = putpat, D = putpat, Q = putpat,
|
||||
V = putpat, U = putpat, T = putpat,
|
||||
M = putpat, X = putpat, P = putpat,
|
||||
F = putpat, G = putpat,
|
||||
F = putpat, G = putpat, Y = putpat,
|
||||
|
||||
-- Collect prefixes.
|
||||
[":"] = function(ctx, name, pat)
|
||||
|
@ -753,15 +795,68 @@ map_act = {
|
|||
|
||||
-- REX prefix.
|
||||
rex = function(ctx, name, pat)
|
||||
if ctx.rex then return unknown(ctx) end -- Only 1 REX prefix allowed.
|
||||
if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed.
|
||||
for p in gmatch(pat, ".") do ctx["rex"..p] = true end
|
||||
ctx.rex = true
|
||||
ctx.rex = "rex"
|
||||
end,
|
||||
|
||||
-- VEX prefix.
|
||||
vex = function(ctx, name, pat)
|
||||
if ctx.rex then return unknown(ctx) end -- Only 1 REX or VEX prefix allowed.
|
||||
ctx.rex = "vex"
|
||||
local pos = ctx.pos
|
||||
if ctx.mrm then
|
||||
ctx.mrm = nil
|
||||
pos = pos-1
|
||||
end
|
||||
local b = byte(ctx.code, pos, pos)
|
||||
if not b then return incomplete(ctx) end
|
||||
pos = pos+1
|
||||
if b < 128 then ctx.rexr = true end
|
||||
local m = 1
|
||||
if pat == "3" then
|
||||
m = b%32; b = (b-m)/32
|
||||
local nb = b%2; b = (b-nb)/2
|
||||
if nb == 0 then ctx.rexb = true end
|
||||
local nx = b%2
|
||||
if nx == 0 then ctx.rexx = true end
|
||||
b = byte(ctx.code, pos, pos)
|
||||
if not b then return incomplete(ctx) end
|
||||
pos = pos+1
|
||||
if b >= 128 then ctx.rexw = true end
|
||||
end
|
||||
ctx.pos = pos
|
||||
local map
|
||||
if m == 1 then map = map_opc2
|
||||
elseif m == 2 then map = map_opc3["38"]
|
||||
elseif m == 3 then map = map_opc3["3a"]
|
||||
else return unknown(ctx) end
|
||||
local p = b%4; b = (b-p)/4
|
||||
if p == 1 then ctx.o16 = "o16"
|
||||
elseif p == 2 then ctx.rep = "rep"
|
||||
elseif p == 3 then ctx.rep = "repne" end
|
||||
local l = b%2; b = (b-l)/2
|
||||
if l ~= 0 then ctx.vexl = true end
|
||||
ctx.vexv = (-1-b)%16
|
||||
return dispatchmap(ctx, map)
|
||||
end,
|
||||
|
||||
-- Special case for nop with REX prefix.
|
||||
nop = function(ctx, name, pat)
|
||||
return dispatch(ctx, ctx.rex and pat or "nop")
|
||||
end,
|
||||
|
||||
-- Special case for 0F 77.
|
||||
emms = function(ctx, name, pat)
|
||||
if ctx.rex ~= "vex" then
|
||||
return putop(ctx, "emms")
|
||||
elseif ctx.vexl then
|
||||
ctx.vexl = false
|
||||
return putop(ctx, "zeroall")
|
||||
else
|
||||
return putop(ctx, "zeroupper")
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
@ -782,7 +877,7 @@ local function disass_block(ctx, ofs, len)
|
|||
end
|
||||
|
||||
-- Extended API: create a disassembler context. Then call ctx:disass(ofs, len).
|
||||
local function create_(code, addr, out)
|
||||
local function create(code, addr, out)
|
||||
local ctx = {}
|
||||
ctx.code = code
|
||||
ctx.addr = (addr or 0) - 1
|
||||
|
@ -796,8 +891,8 @@ local function create_(code, addr, out)
|
|||
return ctx
|
||||
end
|
||||
|
||||
local function create64_(code, addr, out)
|
||||
local ctx = create_(code, addr, out)
|
||||
local function create64(code, addr, out)
|
||||
local ctx = create(code, addr, out)
|
||||
ctx.x64 = true
|
||||
ctx.map1 = map_opc1_64
|
||||
ctx.aregs = map_regs.Q
|
||||
|
@ -805,32 +900,32 @@ local function create64_(code, addr, out)
|
|||
end
|
||||
|
||||
-- Simple API: disassemble code (a string) at address and output via out.
|
||||
local function disass_(code, addr, out)
|
||||
create_(code, addr, out):disass()
|
||||
local function disass(code, addr, out)
|
||||
create(code, addr, out):disass()
|
||||
end
|
||||
|
||||
local function disass64_(code, addr, out)
|
||||
create64_(code, addr, out):disass()
|
||||
local function disass64(code, addr, out)
|
||||
create64(code, addr, out):disass()
|
||||
end
|
||||
|
||||
-- Return register name for RID.
|
||||
local function regname_(r)
|
||||
local function regname(r)
|
||||
if r < 8 then return map_regs.D[r+1] end
|
||||
return map_regs.X[r-7]
|
||||
end
|
||||
|
||||
local function regname64_(r)
|
||||
local function regname64(r)
|
||||
if r < 16 then return map_regs.Q[r+1] end
|
||||
return map_regs.X[r-15]
|
||||
end
|
||||
|
||||
-- Public module functions.
|
||||
module(...)
|
||||
|
||||
create = create_
|
||||
create64 = create64_
|
||||
disass = disass_
|
||||
disass64 = disass64_
|
||||
regname = regname_
|
||||
regname64 = regname64_
|
||||
return {
|
||||
create = create,
|
||||
create64 = create64,
|
||||
disass = disass,
|
||||
disass64 = disass64,
|
||||
regname = regname,
|
||||
regname64 = regname64
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT compiler dump module.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
|
@ -55,7 +55,7 @@
|
|||
|
||||
-- Cache some library functions and objects.
|
||||
local jit = require("jit")
|
||||
assert(jit.version_num == 20004, "LuaJIT core/library version mismatch")
|
||||
assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
|
||||
local jutil = require("jit.util")
|
||||
local vmdef = require("jit.vmdef")
|
||||
local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc
|
||||
|
@ -63,9 +63,9 @@ local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek
|
|||
local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap
|
||||
local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr
|
||||
local bit = require("bit")
|
||||
local band, shl, shr = bit.band, bit.lshift, bit.rshift
|
||||
local band, shr, tohex = bit.band, bit.rshift, bit.tohex
|
||||
local sub, gsub, format = string.sub, string.gsub, string.format
|
||||
local byte, char, rep = string.byte, string.char, string.rep
|
||||
local byte, rep = string.byte, string.rep
|
||||
local type, tostring = type, tostring
|
||||
local stdout, stderr = io.stdout, io.stderr
|
||||
|
||||
|
@ -85,12 +85,13 @@ local nexitsym = 0
|
|||
local function fillsymtab_tr(tr, nexit)
|
||||
local t = {}
|
||||
symtabmt.__index = t
|
||||
if jit.arch == "mips" or jit.arch == "mipsel" then
|
||||
if jit.arch:sub(1, 4) == "mips" then
|
||||
t[traceexitstub(tr, 0)] = "exit"
|
||||
return
|
||||
end
|
||||
for i=0,nexit-1 do
|
||||
local addr = traceexitstub(tr, i)
|
||||
if addr < 0 then addr = addr + 2^32 end
|
||||
t[addr] = tostring(i)
|
||||
end
|
||||
local addr = traceexitstub(tr, nexit)
|
||||
|
@ -104,7 +105,10 @@ local function fillsymtab(tr, nexit)
|
|||
local ircall = vmdef.ircall
|
||||
for i=0,#ircall do
|
||||
local addr = ircalladdr(i)
|
||||
if addr ~= 0 then t[addr] = ircall[i] end
|
||||
if addr ~= 0 then
|
||||
if addr < 0 then addr = addr + 2^32 end
|
||||
t[addr] = ircall[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
if nexitsym == 1000000 then -- Per-trace exit stubs.
|
||||
|
@ -118,6 +122,7 @@ local function fillsymtab(tr, nexit)
|
|||
nexit = 1000000
|
||||
break
|
||||
end
|
||||
if addr < 0 then addr = addr + 2^32 end
|
||||
t[addr] = tostring(i)
|
||||
end
|
||||
nexitsym = nexit
|
||||
|
@ -136,6 +141,7 @@ local function dump_mcode(tr)
|
|||
local mcode, addr, loop = tracemc(tr)
|
||||
if not mcode then return end
|
||||
if not disass then disass = require("jit.dis_"..jit.arch) end
|
||||
if addr < 0 then addr = addr + 2^32 end
|
||||
out:write("---- TRACE ", tr, " mcode ", #mcode, "\n")
|
||||
local ctx = disass.create(mcode, addr, dumpwrite)
|
||||
ctx.hexdump = 0
|
||||
|
@ -207,7 +213,7 @@ local colortype_ansi = {
|
|||
"\027[35m%s\027[m",
|
||||
}
|
||||
|
||||
local function colorize_text(s, t)
|
||||
local function colorize_text(s)
|
||||
return s
|
||||
end
|
||||
|
||||
|
@ -270,8 +276,7 @@ local litname = {
|
|||
["CONV "] = setmetatable({}, { __index = function(t, mode)
|
||||
local s = irtype[band(mode, 31)]
|
||||
s = irtype[band(shr(mode, 5), 31)].."."..s
|
||||
if band(mode, 0x400) ~= 0 then s = s.." trunc"
|
||||
elseif band(mode, 0x800) ~= 0 then s = s.." sext" end
|
||||
if band(mode, 0x800) ~= 0 then s = s.." sext" end
|
||||
local c = shr(mode, 14)
|
||||
if c == 2 then s = s.." index" elseif c == 3 then s = s.." check" end
|
||||
t[mode] = s
|
||||
|
@ -280,6 +285,8 @@ local litname = {
|
|||
["FLOAD "] = vmdef.irfield,
|
||||
["FREF "] = vmdef.irfield,
|
||||
["FPMATH"] = vmdef.irfpm,
|
||||
["BUFHDR"] = { [0] = "RESET", "APPEND" },
|
||||
["TOSTR "] = { [0] = "INT", "NUM", "CHAR" },
|
||||
}
|
||||
|
||||
local function ctlsub(c)
|
||||
|
@ -303,15 +310,17 @@ local function fmtfunc(func, pc)
|
|||
end
|
||||
end
|
||||
|
||||
local function formatk(tr, idx)
|
||||
local function formatk(tr, idx, sn)
|
||||
local k, t, slot = tracek(tr, idx)
|
||||
local tn = type(k)
|
||||
local s
|
||||
if tn == "number" then
|
||||
if k == 2^52+2^51 then
|
||||
if band(sn or 0, 0x30000) ~= 0 then
|
||||
s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz"
|
||||
elseif k == 2^52+2^51 then
|
||||
s = "bias"
|
||||
else
|
||||
s = format("%+.14g", k)
|
||||
s = format(0 < k and k < 0x1p-1026 and "%+a" or "%+.14g", k)
|
||||
end
|
||||
elseif tn == "string" then
|
||||
s = format(#k > 20 and '"%.20s"~' or '"%s"', gsub(k, "%c", ctlsub))
|
||||
|
@ -324,11 +333,13 @@ local function formatk(tr, idx)
|
|||
s = format("userdata:%p", k)
|
||||
else
|
||||
s = format("[%p]", k)
|
||||
if s == "[0x00000000]" then s = "NULL" end
|
||||
if s == "[NULL]" then s = "NULL" end
|
||||
end
|
||||
elseif t == 21 then -- int64_t
|
||||
s = sub(tostring(k), 1, -3)
|
||||
if sub(s, 1, 1) ~= "-" then s = "+"..s end
|
||||
elseif sn == 0x1057fff then -- SNAP(1, SNAP_FRAME | SNAP_NORESTORE, REF_NIL)
|
||||
return "----" -- Special case for LJ_FR2 slot 1.
|
||||
else
|
||||
s = tostring(k) -- For primitives.
|
||||
end
|
||||
|
@ -347,7 +358,7 @@ local function printsnap(tr, snap)
|
|||
n = n + 1
|
||||
local ref = band(sn, 0xffff) - 0x8000 -- REF_BIAS
|
||||
if ref < 0 then
|
||||
out:write(formatk(tr, ref))
|
||||
out:write(formatk(tr, ref, sn))
|
||||
elseif band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM
|
||||
out:write(colorize(format("%04d/%04d", ref, ref+1), 14))
|
||||
else
|
||||
|
@ -545,7 +556,7 @@ local function dump_trace(what, tr, func, pc, otr, oex)
|
|||
if what == "start" then
|
||||
if dumpmode.H then out:write('<pre class="ljdump">\n') end
|
||||
out:write("---- TRACE ", tr, " ", what)
|
||||
if otr then out:write(" ", otr, "/", oex) end
|
||||
if otr then out:write(" ", otr, "/", oex == -1 and "stitch" or oex) end
|
||||
out:write(" ", fmtfunc(func, pc), "\n")
|
||||
elseif what == "stop" or what == "abort" then
|
||||
out:write("---- TRACE ", tr, " ", what)
|
||||
|
@ -564,6 +575,7 @@ local function dump_trace(what, tr, func, pc, otr, oex)
|
|||
end
|
||||
if dumpmode.H then out:write("</pre>\n\n") else out:write("\n") end
|
||||
else
|
||||
if what == "flush" then symtab, nexitsym = {}, 0 end
|
||||
out:write("---- TRACE ", what, "\n\n")
|
||||
end
|
||||
out:flush()
|
||||
|
@ -607,7 +619,7 @@ local function dump_texit(tr, ex, ngpr, nfpr, ...)
|
|||
end
|
||||
else
|
||||
for i=1,ngpr do
|
||||
out:write(format(" %08x", regs[i]))
|
||||
out:write(" ", tohex(regs[i]))
|
||||
if i % 8 == 0 then out:write("\n") end
|
||||
end
|
||||
end
|
||||
|
@ -643,7 +655,8 @@ end
|
|||
local function dumpon(opt, outfile)
|
||||
if active then dumpoff() end
|
||||
|
||||
local colormode = os.getenv("COLORTERM") and "A" or "T"
|
||||
local term = os.getenv("TERM")
|
||||
local colormode = (term and term:match("color") or os.getenv("COLORTERM")) and "A" or "T"
|
||||
if opt then
|
||||
opt = gsub(opt, "[TAH]", function(mode) colormode = mode; return ""; end)
|
||||
end
|
||||
|
@ -691,9 +704,9 @@ local function dumpon(opt, outfile)
|
|||
end
|
||||
|
||||
-- Public module functions.
|
||||
module(...)
|
||||
|
||||
on = dumpon
|
||||
off = dumpoff
|
||||
start = dumpon -- For -j command line option.
|
||||
return {
|
||||
on = dumpon,
|
||||
off = dumpoff,
|
||||
start = dumpon -- For -j command line option.
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,311 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT profiler.
|
||||
--
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
-- This module is a simple command line interface to the built-in
|
||||
-- low-overhead profiler of LuaJIT.
|
||||
--
|
||||
-- The lower-level API of the profiler is accessible via the "jit.profile"
|
||||
-- module or the luaJIT_profile_* C API.
|
||||
--
|
||||
-- Example usage:
|
||||
--
|
||||
-- luajit -jp myapp.lua
|
||||
-- luajit -jp=s myapp.lua
|
||||
-- luajit -jp=-s myapp.lua
|
||||
-- luajit -jp=vl myapp.lua
|
||||
-- luajit -jp=G,profile.txt myapp.lua
|
||||
--
|
||||
-- The following dump features are available:
|
||||
--
|
||||
-- f Stack dump: function name, otherwise module:line. Default mode.
|
||||
-- F Stack dump: ditto, but always prepend module.
|
||||
-- l Stack dump: module:line.
|
||||
-- <number> stack dump depth (callee < caller). Default: 1.
|
||||
-- -<number> Inverse stack dump depth (caller > callee).
|
||||
-- s Split stack dump after first stack level. Implies abs(depth) >= 2.
|
||||
-- p Show full path for module names.
|
||||
-- v Show VM states. Can be combined with stack dumps, e.g. vf or fv.
|
||||
-- z Show zones. Can be combined with stack dumps, e.g. zf or fz.
|
||||
-- r Show raw sample counts. Default: show percentages.
|
||||
-- a Annotate excerpts from source code files.
|
||||
-- A Annotate complete source code files.
|
||||
-- G Produce raw output suitable for graphical tools (e.g. flame graphs).
|
||||
-- m<number> Minimum sample percentage to be shown. Default: 3.
|
||||
-- i<number> Sampling interval in milliseconds. Default: 10.
|
||||
--
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
-- Cache some library functions and objects.
|
||||
local jit = require("jit")
|
||||
assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
|
||||
local profile = require("jit.profile")
|
||||
local vmdef = require("jit.vmdef")
|
||||
local math = math
|
||||
local pairs, ipairs, tonumber, floor = pairs, ipairs, tonumber, math.floor
|
||||
local sort, format = table.sort, string.format
|
||||
local stdout = io.stdout
|
||||
local zone -- Load jit.zone module on demand.
|
||||
|
||||
-- Output file handle.
|
||||
local out
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local prof_ud
|
||||
local prof_states, prof_split, prof_min, prof_raw, prof_fmt, prof_depth
|
||||
local prof_ann, prof_count1, prof_count2, prof_samples
|
||||
|
||||
local map_vmmode = {
|
||||
N = "Compiled",
|
||||
I = "Interpreted",
|
||||
C = "C code",
|
||||
G = "Garbage Collector",
|
||||
J = "JIT Compiler",
|
||||
}
|
||||
|
||||
-- Profiler callback.
|
||||
local function prof_cb(th, samples, vmmode)
|
||||
prof_samples = prof_samples + samples
|
||||
local key_stack, key_stack2, key_state
|
||||
-- Collect keys for sample.
|
||||
if prof_states then
|
||||
if prof_states == "v" then
|
||||
key_state = map_vmmode[vmmode] or vmmode
|
||||
else
|
||||
key_state = zone:get() or "(none)"
|
||||
end
|
||||
end
|
||||
if prof_fmt then
|
||||
key_stack = profile.dumpstack(th, prof_fmt, prof_depth)
|
||||
key_stack = key_stack:gsub("%[builtin#(%d+)%]", function(x)
|
||||
return vmdef.ffnames[tonumber(x)]
|
||||
end)
|
||||
if prof_split == 2 then
|
||||
local k1, k2 = key_stack:match("(.-) [<>] (.*)")
|
||||
if k2 then key_stack, key_stack2 = k1, k2 end
|
||||
elseif prof_split == 3 then
|
||||
key_stack2 = profile.dumpstack(th, "l", 1)
|
||||
end
|
||||
end
|
||||
-- Order keys.
|
||||
local k1, k2
|
||||
if prof_split == 1 then
|
||||
if key_state then
|
||||
k1 = key_state
|
||||
if key_stack then k2 = key_stack end
|
||||
end
|
||||
elseif key_stack then
|
||||
k1 = key_stack
|
||||
if key_stack2 then k2 = key_stack2 elseif key_state then k2 = key_state end
|
||||
end
|
||||
-- Coalesce samples in one or two levels.
|
||||
if k1 then
|
||||
local t1 = prof_count1
|
||||
t1[k1] = (t1[k1] or 0) + samples
|
||||
if k2 then
|
||||
local t2 = prof_count2
|
||||
local t3 = t2[k1]
|
||||
if not t3 then t3 = {}; t2[k1] = t3 end
|
||||
t3[k2] = (t3[k2] or 0) + samples
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- Show top N list.
|
||||
local function prof_top(count1, count2, samples, indent)
|
||||
local t, n = {}, 0
|
||||
for k in pairs(count1) do
|
||||
n = n + 1
|
||||
t[n] = k
|
||||
end
|
||||
sort(t, function(a, b) return count1[a] > count1[b] end)
|
||||
for i=1,n do
|
||||
local k = t[i]
|
||||
local v = count1[k]
|
||||
local pct = floor(v*100/samples + 0.5)
|
||||
if pct < prof_min then break end
|
||||
if not prof_raw then
|
||||
out:write(format("%s%2d%% %s\n", indent, pct, k))
|
||||
elseif prof_raw == "r" then
|
||||
out:write(format("%s%5d %s\n", indent, v, k))
|
||||
else
|
||||
out:write(format("%s %d\n", k, v))
|
||||
end
|
||||
if count2 then
|
||||
local r = count2[k]
|
||||
if r then
|
||||
prof_top(r, nil, v, (prof_split == 3 or prof_split == 1) and " -- " or
|
||||
(prof_depth < 0 and " -> " or " <- "))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Annotate source code
|
||||
local function prof_annotate(count1, samples)
|
||||
local files = {}
|
||||
local ms = 0
|
||||
for k, v in pairs(count1) do
|
||||
local pct = floor(v*100/samples + 0.5)
|
||||
ms = math.max(ms, v)
|
||||
if pct >= prof_min then
|
||||
local file, line = k:match("^(.*):(%d+)$")
|
||||
if not file then file = k; line = 0 end
|
||||
local fl = files[file]
|
||||
if not fl then fl = {}; files[file] = fl; files[#files+1] = file end
|
||||
line = tonumber(line)
|
||||
fl[line] = prof_raw and v or pct
|
||||
end
|
||||
end
|
||||
sort(files)
|
||||
local fmtv, fmtn = " %3d%% | %s\n", " | %s\n"
|
||||
if prof_raw then
|
||||
local n = math.max(5, math.ceil(math.log10(ms)))
|
||||
fmtv = "%"..n.."d | %s\n"
|
||||
fmtn = (" "):rep(n).." | %s\n"
|
||||
end
|
||||
local ann = prof_ann
|
||||
for _, file in ipairs(files) do
|
||||
local f0 = file:byte()
|
||||
if f0 == 40 or f0 == 91 then
|
||||
out:write(format("\n====== %s ======\n[Cannot annotate non-file]\n", file))
|
||||
break
|
||||
end
|
||||
local fp, err = io.open(file)
|
||||
if not fp then
|
||||
out:write(format("====== ERROR: %s: %s\n", file, err))
|
||||
break
|
||||
end
|
||||
out:write(format("\n====== %s ======\n", file))
|
||||
local fl = files[file]
|
||||
local n, show = 1, false
|
||||
if ann ~= 0 then
|
||||
for i=1,ann do
|
||||
if fl[i] then show = true; out:write("@@ 1 @@\n"); break end
|
||||
end
|
||||
end
|
||||
for line in fp:lines() do
|
||||
if line:byte() == 27 then
|
||||
out:write("[Cannot annotate bytecode file]\n")
|
||||
break
|
||||
end
|
||||
local v = fl[n]
|
||||
if ann ~= 0 then
|
||||
local v2 = fl[n+ann]
|
||||
if show then
|
||||
if v2 then show = n+ann elseif v then show = n
|
||||
elseif show+ann < n then show = false end
|
||||
elseif v2 then
|
||||
show = n+ann
|
||||
out:write(format("@@ %d @@\n", n))
|
||||
end
|
||||
if not show then goto next end
|
||||
end
|
||||
if v then
|
||||
out:write(format(fmtv, v, line))
|
||||
else
|
||||
out:write(format(fmtn, line))
|
||||
end
|
||||
::next::
|
||||
n = n + 1
|
||||
end
|
||||
fp:close()
|
||||
end
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
-- Finish profiling and dump result.
|
||||
local function prof_finish()
|
||||
if prof_ud then
|
||||
profile.stop()
|
||||
local samples = prof_samples
|
||||
if samples == 0 then
|
||||
if prof_raw ~= true then out:write("[No samples collected]\n") end
|
||||
return
|
||||
end
|
||||
if prof_ann then
|
||||
prof_annotate(prof_count1, samples)
|
||||
else
|
||||
prof_top(prof_count1, prof_count2, samples, "")
|
||||
end
|
||||
prof_count1 = nil
|
||||
prof_count2 = nil
|
||||
prof_ud = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Start profiling.
|
||||
local function prof_start(mode)
|
||||
local interval = ""
|
||||
mode = mode:gsub("i%d*", function(s) interval = s; return "" end)
|
||||
prof_min = 3
|
||||
mode = mode:gsub("m(%d+)", function(s) prof_min = tonumber(s); return "" end)
|
||||
prof_depth = 1
|
||||
mode = mode:gsub("%-?%d+", function(s) prof_depth = tonumber(s); return "" end)
|
||||
local m = {}
|
||||
for c in mode:gmatch(".") do m[c] = c end
|
||||
prof_states = m.z or m.v
|
||||
if prof_states == "z" then zone = require("jit.zone") end
|
||||
local scope = m.l or m.f or m.F or (prof_states and "" or "f")
|
||||
local flags = (m.p or "")
|
||||
prof_raw = m.r
|
||||
if m.s then
|
||||
prof_split = 2
|
||||
if prof_depth == -1 or m["-"] then prof_depth = -2
|
||||
elseif prof_depth == 1 then prof_depth = 2 end
|
||||
elseif mode:find("[fF].*l") then
|
||||
scope = "l"
|
||||
prof_split = 3
|
||||
else
|
||||
prof_split = (scope == "" or mode:find("[zv].*[lfF]")) and 1 or 0
|
||||
end
|
||||
prof_ann = m.A and 0 or (m.a and 3)
|
||||
if prof_ann then
|
||||
scope = "l"
|
||||
prof_fmt = "pl"
|
||||
prof_split = 0
|
||||
prof_depth = 1
|
||||
elseif m.G and scope ~= "" then
|
||||
prof_fmt = flags..scope.."Z;"
|
||||
prof_depth = -100
|
||||
prof_raw = true
|
||||
prof_min = 0
|
||||
elseif scope == "" then
|
||||
prof_fmt = false
|
||||
else
|
||||
local sc = prof_split == 3 and m.f or m.F or scope
|
||||
prof_fmt = flags..sc..(prof_depth >= 0 and "Z < " or "Z > ")
|
||||
end
|
||||
prof_count1 = {}
|
||||
prof_count2 = {}
|
||||
prof_samples = 0
|
||||
profile.start(scope:lower()..interval, prof_cb)
|
||||
prof_ud = newproxy(true)
|
||||
getmetatable(prof_ud).__gc = prof_finish
|
||||
end
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
local function start(mode, outfile)
|
||||
if not outfile then outfile = os.getenv("LUAJIT_PROFILEFILE") end
|
||||
if outfile then
|
||||
out = outfile == "-" and stdout or assert(io.open(outfile, "w"))
|
||||
else
|
||||
out = stdout
|
||||
end
|
||||
prof_start(mode or "f")
|
||||
end
|
||||
|
||||
-- Public module functions.
|
||||
return {
|
||||
start = start, -- For -j command line option.
|
||||
stop = prof_finish
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- Verbose mode of the LuaJIT compiler.
|
||||
--
|
||||
-- Copyright (C) 2005-2015 Mike Pall. All rights reserved.
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
|
@ -59,7 +59,7 @@
|
|||
|
||||
-- Cache some library functions and objects.
|
||||
local jit = require("jit")
|
||||
assert(jit.version_num == 20004, "LuaJIT core/library version mismatch")
|
||||
assert(jit.version_num == 20100, "LuaJIT core/library version mismatch")
|
||||
local jutil = require("jit.util")
|
||||
local vmdef = require("jit.vmdef")
|
||||
local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo
|
||||
|
@ -99,7 +99,7 @@ end
|
|||
local function dump_trace(what, tr, func, pc, otr, oex)
|
||||
if what == "start" then
|
||||
startloc = fmtfunc(func, pc)
|
||||
startex = otr and "("..otr.."/"..oex..") " or ""
|
||||
startex = otr and "("..otr.."/"..(oex == -1 and "stitch" or oex)..") " or ""
|
||||
else
|
||||
if what == "abort" then
|
||||
local loc = fmtfunc(func, pc)
|
||||
|
@ -116,6 +116,9 @@ local function dump_trace(what, tr, func, pc, otr, oex)
|
|||
if ltype == "interpreter" then
|
||||
out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n",
|
||||
tr, startex, startloc))
|
||||
elseif ltype == "stitch" then
|
||||
out:write(format("[TRACE %3s %s%s %s %s]\n",
|
||||
tr, startex, startloc, ltype, fmtfunc(func, pc)))
|
||||
elseif link == tr or link == 0 then
|
||||
out:write(format("[TRACE %3s %s%s %s]\n",
|
||||
tr, startex, startloc, ltype))
|
||||
|
@ -159,9 +162,9 @@ local function dumpon(outfile)
|
|||
end
|
||||
|
||||
-- Public module functions.
|
||||
module(...)
|
||||
|
||||
on = dumpon
|
||||
off = dumpoff
|
||||
start = dumpon -- For -j command line option.
|
||||
return {
|
||||
on = dumpon,
|
||||
off = dumpoff,
|
||||
start = dumpon -- For -j command line option.
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
----------------------------------------------------------------------------
|
||||
-- LuaJIT profiler zones.
|
||||
--
|
||||
-- Copyright (C) 2005-2017 Mike Pall. All rights reserved.
|
||||
-- Released under the MIT license. See Copyright Notice in luajit.h
|
||||
----------------------------------------------------------------------------
|
||||
--
|
||||
-- This module implements a simple hierarchical zone model.
|
||||
--
|
||||
-- Example usage:
|
||||
--
|
||||
-- local zone = require("jit.zone")
|
||||
-- zone("AI")
|
||||
-- ...
|
||||
-- zone("A*")
|
||||
-- ...
|
||||
-- print(zone:get()) --> "A*"
|
||||
-- ...
|
||||
-- zone()
|
||||
-- ...
|
||||
-- print(zone:get()) --> "AI"
|
||||
-- ...
|
||||
-- zone()
|
||||
--
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
local remove = table.remove
|
||||
|
||||
return setmetatable({
|
||||
flush = function(t)
|
||||
for i=#t,1,-1 do t[i] = nil end
|
||||
end,
|
||||
get = function(t)
|
||||
return t[#t]
|
||||
end
|
||||
}, {
|
||||
__call = function(t, zone)
|
||||
if zone then
|
||||
t[#t+1] = zone
|
||||
else
|
||||
return (assert(remove(t), "empty zone stack"))
|
||||
end
|
||||
end
|
||||
})
|
||||
|
|
@ -15,9 +15,6 @@
|
|||
#include "lua.h"
|
||||
|
||||
|
||||
#define luaL_getn(L,i) ((int)lua_objlen(L, i))
|
||||
#define luaL_setn(L,i,j) ((void)0) /* no op! */
|
||||
|
||||
/* extra error code for `luaL_load' */
|
||||
#define LUA_ERRFILE (LUA_ERRERR+1)
|
||||
|
||||
|
@ -58,6 +55,10 @@ LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);
|
|||
LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,
|
||||
const char *const lst[]);
|
||||
|
||||
/* pre-defined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
LUALIB_API int (luaL_ref) (lua_State *L, int t);
|
||||
LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);
|
||||
|
||||
|
@ -84,6 +85,11 @@ LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz,
|
|||
const char *name, const char *mode);
|
||||
LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
|
||||
int level);
|
||||
LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup);
|
||||
LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname,
|
||||
int sizehint);
|
||||
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
|
||||
LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -113,6 +119,11 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
|
|||
|
||||
#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))
|
||||
|
||||
/* From Lua 5.2. */
|
||||
#define luaL_newlibtable(L, l) \
|
||||
lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
|
||||
#define luaL_newlib(L, l) (luaL_newlibtable(L, l), luaL_setfuncs(L, l, 0))
|
||||
|
||||
/*
|
||||
** {======================================================
|
||||
** Generic Buffer manipulation
|
||||
|
@ -147,21 +158,4 @@ LUALIB_API void (luaL_pushresult) (luaL_Buffer *B);
|
|||
|
||||
/* }====================================================== */
|
||||
|
||||
|
||||
/* compatibility with ref system */
|
||||
|
||||
/* pre-defined references */
|
||||
#define LUA_NOREF (-2)
|
||||
#define LUA_REFNIL (-1)
|
||||
|
||||
#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \
|
||||
(lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0))
|
||||
|
||||
#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref))
|
||||
|
||||
#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))
|
||||
|
||||
|
||||
#define luaL_reg luaL_Reg
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Auxiliary library for the Lua/C API.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major parts taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
|
@ -107,38 +107,36 @@ LUALIB_API const char *luaL_findtable(lua_State *L, int idx,
|
|||
static int libsize(const luaL_Reg *l)
|
||||
{
|
||||
int size = 0;
|
||||
for (; l->name; l++) size++;
|
||||
for (; l && l->name; l++) size++;
|
||||
return size;
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_pushmodule(lua_State *L, const char *modname, int sizehint)
|
||||
{
|
||||
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
|
||||
lua_getfield(L, -1, modname);
|
||||
if (!lua_istable(L, -1)) {
|
||||
lua_pop(L, 1);
|
||||
if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, sizehint) != NULL)
|
||||
lj_err_callerv(L, LJ_ERR_BADMODN, modname);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, modname); /* _LOADED[modname] = new table. */
|
||||
}
|
||||
lua_remove(L, -2); /* Remove _LOADED table. */
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
|
||||
const luaL_Reg *l, int nup)
|
||||
{
|
||||
lj_lib_checkfpu(L);
|
||||
if (libname) {
|
||||
int size = libsize(l);
|
||||
/* check whether lib already exists */
|
||||
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
|
||||
lua_getfield(L, -1, libname); /* get _LOADED[libname] */
|
||||
if (!lua_istable(L, -1)) { /* not found? */
|
||||
lua_pop(L, 1); /* remove previous result */
|
||||
/* try global variable (and create one if it does not exist) */
|
||||
if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
|
||||
lj_err_callerv(L, LJ_ERR_BADMODN, libname);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
|
||||
}
|
||||
lua_remove(L, -2); /* remove _LOADED table */
|
||||
lua_insert(L, -(nup+1)); /* move library table to below upvalues */
|
||||
luaL_pushmodule(L, libname, libsize(l));
|
||||
lua_insert(L, -(nup + 1)); /* Move module table below upvalues. */
|
||||
}
|
||||
for (; l->name; l++) {
|
||||
int i;
|
||||
for (i = 0; i < nup; i++) /* copy upvalues to the top */
|
||||
lua_pushvalue(L, -nup);
|
||||
lua_pushcclosure(L, l->func, nup);
|
||||
lua_setfield(L, -(nup+2), l->name);
|
||||
}
|
||||
lua_pop(L, nup); /* remove upvalues */
|
||||
if (l)
|
||||
luaL_setfuncs(L, l, nup);
|
||||
else
|
||||
lua_pop(L, nup); /* Remove upvalues. */
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_register(lua_State *L, const char *libname,
|
||||
|
@ -147,6 +145,19 @@ LUALIB_API void luaL_register(lua_State *L, const char *libname,
|
|||
luaL_openlib(L, libname, l, 0);
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_setfuncs(lua_State *L, const luaL_Reg *l, int nup)
|
||||
{
|
||||
luaL_checkstack(L, nup, "too many upvalues");
|
||||
for (; l->name; l++) {
|
||||
int i;
|
||||
for (i = 0; i < nup; i++) /* Copy upvalues to the top. */
|
||||
lua_pushvalue(L, -nup);
|
||||
lua_pushcclosure(L, l->func, nup);
|
||||
lua_setfield(L, -(nup + 2), l->name);
|
||||
}
|
||||
lua_pop(L, nup); /* Remove upvalues. */
|
||||
}
|
||||
|
||||
LUALIB_API const char *luaL_gsub(lua_State *L, const char *s,
|
||||
const char *p, const char *r)
|
||||
{
|
||||
|
@ -302,7 +313,7 @@ static int panic(lua_State *L)
|
|||
|
||||
#ifdef LUAJIT_USE_SYSMALLOC
|
||||
|
||||
#if LJ_64 && !defined(LUAJIT_USE_VALGRIND)
|
||||
#if LJ_64 && !LJ_GC64 && !defined(LUAJIT_USE_VALGRIND)
|
||||
#error "Must use builtin allocator for 64 bit target"
|
||||
#endif
|
||||
|
||||
|
@ -334,7 +345,7 @@ LUALIB_API lua_State *luaL_newstate(void)
|
|||
lua_State *L;
|
||||
void *ud = lj_alloc_create();
|
||||
if (ud == NULL) return NULL;
|
||||
#if LJ_64
|
||||
#if LJ_64 && !LJ_GC64
|
||||
L = lj_state_newstate(lj_alloc_f, ud);
|
||||
#else
|
||||
L = lua_newstate(lj_alloc_f, ud);
|
||||
|
@ -343,7 +354,7 @@ LUALIB_API lua_State *luaL_newstate(void)
|
|||
return L;
|
||||
}
|
||||
|
||||
#if LJ_64
|
||||
#if LJ_64 && !LJ_GC64
|
||||
LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
|
||||
{
|
||||
UNUSED(f); UNUSED(ud);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Base and coroutine library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
|
@ -23,6 +23,7 @@
|
|||
#include "lj_tab.h"
|
||||
#include "lj_meta.h"
|
||||
#include "lj_state.h"
|
||||
#include "lj_frame.h"
|
||||
#if LJ_HASFFI
|
||||
#include "lj_ctype.h"
|
||||
#include "lj_cconv.h"
|
||||
|
@ -32,6 +33,7 @@
|
|||
#include "lj_dispatch.h"
|
||||
#include "lj_char.h"
|
||||
#include "lj_strscan.h"
|
||||
#include "lj_strfmt.h"
|
||||
#include "lj_lib.h"
|
||||
|
||||
/* -- Base library: checks ------------------------------------------------ */
|
||||
|
@ -86,10 +88,11 @@ static int ffh_pairs(lua_State *L, MMS mm)
|
|||
cTValue *mo = lj_meta_lookup(L, o, mm);
|
||||
if ((LJ_52 || tviscdata(o)) && !tvisnil(mo)) {
|
||||
L->top = o+1; /* Only keep one argument. */
|
||||
copyTV(L, L->base-1, mo); /* Replace callable. */
|
||||
copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */
|
||||
return FFH_TAILCALL;
|
||||
} else {
|
||||
if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE);
|
||||
if (LJ_FR2) { copyTV(L, o-1, o); o--; }
|
||||
setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1)));
|
||||
if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0);
|
||||
return FFH_RES(3);
|
||||
|
@ -100,7 +103,7 @@ static int ffh_pairs(lua_State *L, MMS mm)
|
|||
#endif
|
||||
|
||||
LJLIB_PUSH(lastcl)
|
||||
LJLIB_ASM(pairs)
|
||||
LJLIB_ASM(pairs) LJLIB_REC(xpairs 0)
|
||||
{
|
||||
return ffh_pairs(L, MM_pairs);
|
||||
}
|
||||
|
@ -113,7 +116,7 @@ LJLIB_NOREGUV LJLIB_ASM(ipairs_aux) LJLIB_REC(.)
|
|||
}
|
||||
|
||||
LJLIB_PUSH(lastcl)
|
||||
LJLIB_ASM(ipairs) LJLIB_REC(.)
|
||||
LJLIB_ASM(ipairs) LJLIB_REC(xpairs 1)
|
||||
{
|
||||
return ffh_pairs(L, MM_ipairs);
|
||||
}
|
||||
|
@ -131,11 +134,11 @@ LJLIB_ASM(setmetatable) LJLIB_REC(.)
|
|||
lj_err_caller(L, LJ_ERR_PROTMT);
|
||||
setgcref(t->metatable, obj2gco(mt));
|
||||
if (mt) { lj_gc_objbarriert(L, t, mt); }
|
||||
settabV(L, L->base-1, t);
|
||||
settabV(L, L->base-1-LJ_FR2, t);
|
||||
return FFH_RES(1);
|
||||
}
|
||||
|
||||
LJLIB_CF(getfenv)
|
||||
LJLIB_CF(getfenv) LJLIB_REC(.)
|
||||
{
|
||||
GCfunc *fn;
|
||||
cTValue *o = L->base;
|
||||
|
@ -144,6 +147,7 @@ LJLIB_CF(getfenv)
|
|||
o = lj_debug_frame(L, level, &level);
|
||||
if (o == NULL)
|
||||
lj_err_arg(L, 1, LJ_ERR_INVLVL);
|
||||
if (LJ_FR2) o--;
|
||||
}
|
||||
fn = &gcval(o)->fn;
|
||||
settabV(L, L->top++, isluafunc(fn) ? tabref(fn->l.env) : tabref(L->env));
|
||||
|
@ -165,6 +169,7 @@ LJLIB_CF(setfenv)
|
|||
o = lj_debug_frame(L, level, &level);
|
||||
if (o == NULL)
|
||||
lj_err_arg(L, 1, LJ_ERR_INVLVL);
|
||||
if (LJ_FR2) o--;
|
||||
}
|
||||
fn = &gcval(o)->fn;
|
||||
if (!isluafunc(fn))
|
||||
|
@ -257,7 +262,7 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
|
|||
if (base == 10) {
|
||||
TValue *o = lj_lib_checkany(L, 1);
|
||||
if (lj_strscan_numberobj(o)) {
|
||||
copyTV(L, L->base-1, o);
|
||||
copyTV(L, L->base-1-LJ_FR2, o);
|
||||
return FFH_RES(1);
|
||||
}
|
||||
#if LJ_HASFFI
|
||||
|
@ -270,11 +275,11 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
|
|||
ct->size <= 4 && !(ct->size == 4 && (ct->info & CTF_UNSIGNED))) {
|
||||
int32_t i;
|
||||
lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT32), (uint8_t *)&i, o, 0);
|
||||
setintV(L->base-1, i);
|
||||
setintV(L->base-1-LJ_FR2, i);
|
||||
return FFH_RES(1);
|
||||
}
|
||||
lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE),
|
||||
(uint8_t *)&(L->base-1)->n, o, 0);
|
||||
(uint8_t *)&(L->base-1-LJ_FR2)->n, o, 0);
|
||||
return FFH_RES(1);
|
||||
}
|
||||
}
|
||||
|
@ -290,45 +295,29 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
|
|||
while (lj_char_isspace((unsigned char)(*ep))) ep++;
|
||||
if (*ep == '\0') {
|
||||
if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u))
|
||||
setintV(L->base-1, (int32_t)ul);
|
||||
setintV(L->base-1-LJ_FR2, (int32_t)ul);
|
||||
else
|
||||
setnumV(L->base-1, (lua_Number)ul);
|
||||
setnumV(L->base-1-LJ_FR2, (lua_Number)ul);
|
||||
return FFH_RES(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
setnilV(L->base-1);
|
||||
setnilV(L->base-1-LJ_FR2);
|
||||
return FFH_RES(1);
|
||||
}
|
||||
|
||||
LJLIB_PUSH("nil")
|
||||
LJLIB_PUSH("false")
|
||||
LJLIB_PUSH("true")
|
||||
LJLIB_ASM(tostring) LJLIB_REC(.)
|
||||
{
|
||||
TValue *o = lj_lib_checkany(L, 1);
|
||||
cTValue *mo;
|
||||
L->top = o+1; /* Only keep one argument. */
|
||||
if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
|
||||
copyTV(L, L->base-1, mo); /* Replace callable. */
|
||||
copyTV(L, L->base-1-LJ_FR2, mo); /* Replace callable. */
|
||||
return FFH_TAILCALL;
|
||||
} else {
|
||||
GCstr *s;
|
||||
if (tvisnumber(o)) {
|
||||
s = lj_str_fromnumber(L, o);
|
||||
} else if (tvispri(o)) {
|
||||
s = strV(lj_lib_upvalue(L, -(int32_t)itype(o)));
|
||||
} else {
|
||||
if (tvisfunc(o) && isffunc(funcV(o)))
|
||||
lua_pushfstring(L, "function: builtin#%d", funcV(o)->c.ffid);
|
||||
else
|
||||
lua_pushfstring(L, "%s: %p", lj_typename(o), lua_topointer(L, 1));
|
||||
/* Note: lua_pushfstring calls the GC which may invalidate o. */
|
||||
s = strV(L->top-1);
|
||||
}
|
||||
setstrV(L, L->base-1, s);
|
||||
return FFH_RES(1);
|
||||
}
|
||||
lj_gc_check(L);
|
||||
setstrV(L, L->base-1-LJ_FR2, lj_strfmt_obj(L, L->base));
|
||||
return FFH_RES(1);
|
||||
}
|
||||
|
||||
/* -- Base library: throw and catch errors -------------------------------- */
|
||||
|
@ -357,7 +346,7 @@ LJLIB_ASM_(xpcall) LJLIB_REC(.)
|
|||
|
||||
static int load_aux(lua_State *L, int status, int envarg)
|
||||
{
|
||||
if (status == 0) {
|
||||
if (status == LUA_OK) {
|
||||
if (tvistab(L->base+envarg-1)) {
|
||||
GCfunc *fn = funcV(L->top-1);
|
||||
GCtab *t = tabV(L->base+envarg-1);
|
||||
|
@ -430,7 +419,7 @@ LJLIB_CF(dofile)
|
|||
GCstr *fname = lj_lib_optstr(L, 1);
|
||||
setnilV(L->top);
|
||||
L->top = L->base+1;
|
||||
if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != 0)
|
||||
if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != LUA_OK)
|
||||
lua_error(L);
|
||||
lua_call(L, 0, LUA_MULTRET);
|
||||
return (int)(L->top - L->base) - 1;
|
||||
|
@ -440,20 +429,20 @@ LJLIB_CF(dofile)
|
|||
|
||||
LJLIB_CF(gcinfo)
|
||||
{
|
||||
setintV(L->top++, (G(L)->gc.total >> 10));
|
||||
setintV(L->top++, (int32_t)(G(L)->gc.total >> 10));
|
||||
return 1;
|
||||
}
|
||||
|
||||
LJLIB_CF(collectgarbage)
|
||||
{
|
||||
int opt = lj_lib_checkopt(L, 1, LUA_GCCOLLECT, /* ORDER LUA_GC* */
|
||||
"\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul");
|
||||
"\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul\1\377\11isrunning");
|
||||
int32_t data = lj_lib_optint(L, 2, 0);
|
||||
if (opt == LUA_GCCOUNT) {
|
||||
setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0);
|
||||
} else {
|
||||
int res = lua_gc(L, opt, data);
|
||||
if (opt == LUA_GCSTEP)
|
||||
if (opt == LUA_GCSTEP || opt == LUA_GCISRUNNING)
|
||||
setboolV(L->top, res);
|
||||
else
|
||||
setintV(L->top, res);
|
||||
|
@ -506,21 +495,12 @@ LJLIB_CF(print)
|
|||
}
|
||||
shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring);
|
||||
for (i = 0; i < nargs; i++) {
|
||||
cTValue *o = &L->base[i];
|
||||
const char *str;
|
||||
size_t size;
|
||||
cTValue *o = &L->base[i];
|
||||
if (shortcut && tvisstr(o)) {
|
||||
str = strVdata(o);
|
||||
size = strV(o)->len;
|
||||
} else if (shortcut && tvisint(o)) {
|
||||
char buf[LJ_STR_INTBUF];
|
||||
char *p = lj_str_bufint(buf, intV(o));
|
||||
size = (size_t)(buf+LJ_STR_INTBUF-p);
|
||||
str = p;
|
||||
} else if (shortcut && tvisnum(o)) {
|
||||
char buf[LJ_STR_NUMBUF];
|
||||
size = lj_str_bufnum(buf, o);
|
||||
str = buf;
|
||||
MSize len;
|
||||
if (shortcut && (str = lj_strfmt_wstrnum(L, o, &len)) != NULL) {
|
||||
size = len;
|
||||
} else {
|
||||
copyTV(L, L->top+1, o);
|
||||
copyTV(L, L->top, L->top-1);
|
||||
|
@ -557,8 +537,8 @@ LJLIB_CF(coroutine_status)
|
|||
co = threadV(L->base);
|
||||
if (co == L) s = "running";
|
||||
else if (co->status == LUA_YIELD) s = "suspended";
|
||||
else if (co->status != 0) s = "dead";
|
||||
else if (co->base > tvref(co->stack)+1) s = "normal";
|
||||
else if (co->status != LUA_OK) s = "dead";
|
||||
else if (co->base > tvref(co->stack)+1+LJ_FR2) s = "normal";
|
||||
else if (co->top == co->base) s = "dead";
|
||||
else s = "suspended";
|
||||
lua_pushstring(L, s);
|
||||
|
@ -578,6 +558,12 @@ LJLIB_CF(coroutine_running)
|
|||
#endif
|
||||
}
|
||||
|
||||
LJLIB_CF(coroutine_isyieldable)
|
||||
{
|
||||
setboolV(L->top++, cframe_canyield(L->cframe));
|
||||
return 1;
|
||||
}
|
||||
|
||||
LJLIB_CF(coroutine_create)
|
||||
{
|
||||
lua_State *L1;
|
||||
|
@ -597,11 +583,11 @@ LJLIB_ASM(coroutine_yield)
|
|||
static int ffh_resume(lua_State *L, lua_State *co, int wrap)
|
||||
{
|
||||
if (co->cframe != NULL || co->status > LUA_YIELD ||
|
||||
(co->status == 0 && co->top == co->base)) {
|
||||
(co->status == LUA_OK && co->top == co->base)) {
|
||||
ErrMsg em = co->cframe ? LJ_ERR_CORUN : LJ_ERR_CODEAD;
|
||||
if (wrap) lj_err_caller(L, em);
|
||||
setboolV(L->base-1, 0);
|
||||
setstrV(L, L->base, lj_err_str(L, em));
|
||||
setboolV(L->base-1-LJ_FR2, 0);
|
||||
setstrV(L, L->base-LJ_FR2, lj_err_str(L, em));
|
||||
return FFH_RES(2);
|
||||
}
|
||||
lj_state_growstack(co, (MSize)(L->top - L->base));
|
||||
|
@ -642,9 +628,10 @@ static void setpc_wrap_aux(lua_State *L, GCfunc *fn);
|
|||
|
||||
LJLIB_CF(coroutine_wrap)
|
||||
{
|
||||
GCfunc *fn;
|
||||
lj_cf_coroutine_create(L);
|
||||
lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1);
|
||||
setpc_wrap_aux(L, funcV(L->top-1));
|
||||
fn = lj_lib_pushcc(L, lj_ffh_coroutine_wrap_aux, FF_coroutine_wrap_aux, 1);
|
||||
setpc_wrap_aux(L, fn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Bit manipulation library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#define lib_bit_c
|
||||
|
@ -12,26 +12,99 @@
|
|||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_err.h"
|
||||
#include "lj_str.h"
|
||||
#include "lj_buf.h"
|
||||
#include "lj_strscan.h"
|
||||
#include "lj_strfmt.h"
|
||||
#if LJ_HASFFI
|
||||
#include "lj_ctype.h"
|
||||
#include "lj_cdata.h"
|
||||
#include "lj_cconv.h"
|
||||
#include "lj_carith.h"
|
||||
#endif
|
||||
#include "lj_ff.h"
|
||||
#include "lj_lib.h"
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#define LJLIB_MODULE_bit
|
||||
|
||||
LJLIB_ASM(bit_tobit) LJLIB_REC(bit_unary IR_TOBIT)
|
||||
#if LJ_HASFFI
|
||||
static int bit_result64(lua_State *L, CTypeID id, uint64_t x)
|
||||
{
|
||||
GCcdata *cd = lj_cdata_new_(L, id, 8);
|
||||
*(uint64_t *)cdataptr(cd) = x;
|
||||
setcdataV(L, L->base-1-LJ_FR2, cd);
|
||||
return FFH_RES(1);
|
||||
}
|
||||
#else
|
||||
static int32_t bit_checkbit(lua_State *L, int narg)
|
||||
{
|
||||
TValue *o = L->base + narg-1;
|
||||
if (!(o < L->top && lj_strscan_numberobj(o)))
|
||||
lj_err_argt(L, narg, LUA_TNUMBER);
|
||||
if (LJ_LIKELY(tvisint(o))) {
|
||||
return intV(o);
|
||||
} else {
|
||||
int32_t i = lj_num2bit(numV(o));
|
||||
if (LJ_DUALNUM) setintV(o, i);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LJLIB_ASM(bit_tobit) LJLIB_REC(bit_tobit)
|
||||
{
|
||||
#if LJ_HASFFI
|
||||
CTypeID id = 0;
|
||||
setintV(L->base-1-LJ_FR2, (int32_t)lj_carith_check64(L, 1, &id));
|
||||
return FFH_RES(1);
|
||||
#else
|
||||
lj_lib_checknumber(L, 1);
|
||||
return FFH_RETRY;
|
||||
#endif
|
||||
}
|
||||
|
||||
LJLIB_ASM(bit_bnot) LJLIB_REC(bit_unary IR_BNOT)
|
||||
{
|
||||
#if LJ_HASFFI
|
||||
CTypeID id = 0;
|
||||
uint64_t x = lj_carith_check64(L, 1, &id);
|
||||
return id ? bit_result64(L, id, ~x) : FFH_RETRY;
|
||||
#else
|
||||
lj_lib_checknumber(L, 1);
|
||||
return FFH_RETRY;
|
||||
#endif
|
||||
}
|
||||
|
||||
LJLIB_ASM(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP)
|
||||
{
|
||||
#if LJ_HASFFI
|
||||
CTypeID id = 0;
|
||||
uint64_t x = lj_carith_check64(L, 1, &id);
|
||||
return id ? bit_result64(L, id, lj_bswap64(x)) : FFH_RETRY;
|
||||
#else
|
||||
lj_lib_checknumber(L, 1);
|
||||
return FFH_RETRY;
|
||||
#endif
|
||||
}
|
||||
LJLIB_ASM_(bit_bnot) LJLIB_REC(bit_unary IR_BNOT)
|
||||
LJLIB_ASM_(bit_bswap) LJLIB_REC(bit_unary IR_BSWAP)
|
||||
|
||||
LJLIB_ASM(bit_lshift) LJLIB_REC(bit_shift IR_BSHL)
|
||||
{
|
||||
lj_lib_checknumber(L, 1);
|
||||
lj_lib_checkbit(L, 2);
|
||||
#if LJ_HASFFI
|
||||
CTypeID id = 0, id2 = 0;
|
||||
uint64_t x = lj_carith_check64(L, 1, &id);
|
||||
int32_t sh = (int32_t)lj_carith_check64(L, 2, &id2);
|
||||
if (id) {
|
||||
x = lj_carith_shift64(x, sh, curr_func(L)->c.ffid - (int)FF_bit_lshift);
|
||||
return bit_result64(L, id, x);
|
||||
}
|
||||
if (id2) setintV(L->base+1, sh);
|
||||
return FFH_RETRY;
|
||||
#else
|
||||
lj_lib_checknumber(L, 1);
|
||||
bit_checkbit(L, 2);
|
||||
return FFH_RETRY;
|
||||
#endif
|
||||
}
|
||||
LJLIB_ASM_(bit_rshift) LJLIB_REC(bit_shift IR_BSHR)
|
||||
LJLIB_ASM_(bit_arshift) LJLIB_REC(bit_shift IR_BSAR)
|
||||
|
@ -40,25 +113,58 @@ LJLIB_ASM_(bit_ror) LJLIB_REC(bit_shift IR_BROR)
|
|||
|
||||
LJLIB_ASM(bit_band) LJLIB_REC(bit_nary IR_BAND)
|
||||
{
|
||||
#if LJ_HASFFI
|
||||
CTypeID id = 0;
|
||||
TValue *o = L->base, *top = L->top;
|
||||
int i = 0;
|
||||
do { lj_carith_check64(L, ++i, &id); } while (++o < top);
|
||||
if (id) {
|
||||
CTState *cts = ctype_cts(L);
|
||||
CType *ct = ctype_get(cts, id);
|
||||
int op = curr_func(L)->c.ffid - (int)FF_bit_bor;
|
||||
uint64_t x, y = op >= 0 ? 0 : ~(uint64_t)0;
|
||||
o = L->base;
|
||||
do {
|
||||
lj_cconv_ct_tv(cts, ct, (uint8_t *)&x, o, 0);
|
||||
if (op < 0) y &= x; else if (op == 0) y |= x; else y ^= x;
|
||||
} while (++o < top);
|
||||
return bit_result64(L, id, y);
|
||||
}
|
||||
return FFH_RETRY;
|
||||
#else
|
||||
int i = 0;
|
||||
do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top);
|
||||
return FFH_RETRY;
|
||||
#endif
|
||||
}
|
||||
LJLIB_ASM_(bit_bor) LJLIB_REC(bit_nary IR_BOR)
|
||||
LJLIB_ASM_(bit_bxor) LJLIB_REC(bit_nary IR_BXOR)
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
LJLIB_CF(bit_tohex)
|
||||
LJLIB_CF(bit_tohex) LJLIB_REC(.)
|
||||
{
|
||||
uint32_t b = (uint32_t)lj_lib_checkbit(L, 1);
|
||||
int32_t i, n = L->base+1 >= L->top ? 8 : lj_lib_checkbit(L, 2);
|
||||
const char *hexdigits = "0123456789abcdef";
|
||||
char buf[8];
|
||||
if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }
|
||||
if (n > 8) n = 8;
|
||||
for (i = n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; }
|
||||
lua_pushlstring(L, buf, (size_t)n);
|
||||
#if LJ_HASFFI
|
||||
CTypeID id = 0, id2 = 0;
|
||||
uint64_t b = lj_carith_check64(L, 1, &id);
|
||||
int32_t n = L->base+1>=L->top ? (id ? 16 : 8) :
|
||||
(int32_t)lj_carith_check64(L, 2, &id2);
|
||||
#else
|
||||
uint32_t b = (uint32_t)bit_checkbit(L, 1);
|
||||
int32_t n = L->base+1>=L->top ? 8 : bit_checkbit(L, 2);
|
||||
#endif
|
||||
SBuf *sb = lj_buf_tmp_(L);
|
||||
SFormat sf = (STRFMT_UINT|STRFMT_T_HEX);
|
||||
if (n < 0) { n = -n; sf |= STRFMT_F_UPPER; }
|
||||
sf |= ((SFormat)((n+1)&255) << STRFMT_SH_PREC);
|
||||
#if LJ_HASFFI
|
||||
if (n < 16) b &= ((uint64_t)1 << 4*n)-1;
|
||||
#else
|
||||
if (n < 8) b &= (1u << 4*n)-1;
|
||||
#endif
|
||||
sb = lj_strfmt_putfxint(sb, sf, b);
|
||||
setstrV(L, L->top-1, lj_buf_str(L, sb));
|
||||
lj_gc_check(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Debug library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
|
@ -29,7 +29,7 @@ LJLIB_CF(debug_getregistry)
|
|||
return 1;
|
||||
}
|
||||
|
||||
LJLIB_CF(debug_getmetatable)
|
||||
LJLIB_CF(debug_getmetatable) LJLIB_REC(.)
|
||||
{
|
||||
lj_lib_checkany(L, 1);
|
||||
if (!lua_getmetatable(L, 1)) {
|
||||
|
@ -283,13 +283,13 @@ LJLIB_CF(debug_setuservalue)
|
|||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static const char KEY_HOOK = 'h';
|
||||
#define KEY_HOOK ((void *)0x3004)
|
||||
|
||||
static void hookf(lua_State *L, lua_Debug *ar)
|
||||
{
|
||||
static const char *const hooknames[] =
|
||||
{"call", "return", "line", "count", "tail return"};
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
lua_pushlightuserdata(L, KEY_HOOK);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX);
|
||||
if (lua_isfunction(L, -1)) {
|
||||
lua_pushstring(L, hooknames[(int)ar->event]);
|
||||
|
@ -334,7 +334,7 @@ LJLIB_CF(debug_sethook)
|
|||
count = luaL_optint(L, arg+3, 0);
|
||||
func = hookf; mask = makemask(smask, count);
|
||||
}
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
lua_pushlightuserdata(L, KEY_HOOK);
|
||||
lua_pushvalue(L, arg+1);
|
||||
lua_rawset(L, LUA_REGISTRYINDEX);
|
||||
lua_sethook(L, func, mask, count);
|
||||
|
@ -349,7 +349,7 @@ LJLIB_CF(debug_gethook)
|
|||
if (hook != NULL && hook != hookf) { /* external hook? */
|
||||
lua_pushliteral(L, "external hook");
|
||||
} else {
|
||||
lua_pushlightuserdata(L, (void *)&KEY_HOOK);
|
||||
lua_pushlightuserdata(L, KEY_HOOK);
|
||||
lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
|
||||
}
|
||||
lua_pushstring(L, unmakemask(mask, buff));
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** FFI library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#define lib_ffi_c
|
||||
|
@ -29,6 +29,7 @@
|
|||
#include "lj_ccall.h"
|
||||
#include "lj_ccallback.h"
|
||||
#include "lj_clib.h"
|
||||
#include "lj_strfmt.h"
|
||||
#include "lj_ff.h"
|
||||
#include "lj_lib.h"
|
||||
|
||||
|
@ -137,7 +138,7 @@ static int ffi_index_meta(lua_State *L, CTState *cts, CType *ct, MMS mm)
|
|||
}
|
||||
}
|
||||
copyTV(L, base, L->top);
|
||||
tv = L->top-1;
|
||||
tv = L->top-1-LJ_FR2;
|
||||
}
|
||||
return lj_meta_tailcall(L, tv);
|
||||
}
|
||||
|
@ -318,7 +319,7 @@ LJLIB_CF(ffi_meta___tostring)
|
|||
}
|
||||
}
|
||||
}
|
||||
lj_str_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), p);
|
||||
lj_strfmt_pushf(L, msg, strdata(lj_ctype_repr(L, id, NULL)), p);
|
||||
checkgc:
|
||||
lj_gc_check(L);
|
||||
return 1;
|
||||
|
@ -504,10 +505,7 @@ LJLIB_CF(ffi_new) LJLIB_REC(.)
|
|||
}
|
||||
if (sz == CTSIZE_INVALID)
|
||||
lj_err_arg(L, 1, LJ_ERR_FFI_INVSIZE);
|
||||
if (!(info & CTF_VLA) && ctype_align(info) <= CT_MEMALIGN)
|
||||
cd = lj_cdata_new(cts, id, sz);
|
||||
else
|
||||
cd = lj_cdata_newv(cts, id, sz, ctype_align(info));
|
||||
cd = lj_cdata_newx(cts, id, sz, info);
|
||||
setcdataV(L, o-1, cd); /* Anchor the uninitialized cdata. */
|
||||
lj_cconv_ct_init(cts, ct, sz, cdataptr(cd),
|
||||
o, (MSize)(L->top - o)); /* Initialize cdata. */
|
||||
|
@ -558,6 +556,31 @@ LJLIB_CF(ffi_typeof) LJLIB_REC(.)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Internal and unsupported API. */
|
||||
LJLIB_CF(ffi_typeinfo)
|
||||
{
|
||||
CTState *cts = ctype_cts(L);
|
||||
CTypeID id = (CTypeID)ffi_checkint(L, 1);
|
||||
if (id > 0 && id < cts->top) {
|
||||
CType *ct = ctype_get(cts, id);
|
||||
GCtab *t;
|
||||
lua_createtable(L, 0, 4); /* Increment hash size if fields are added. */
|
||||
t = tabV(L->top-1);
|
||||
setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "info")), (int32_t)ct->info);
|
||||
if (ct->size != CTSIZE_INVALID)
|
||||
setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "size")), (int32_t)ct->size);
|
||||
if (ct->sib)
|
||||
setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "sib")), (int32_t)ct->sib);
|
||||
if (gcref(ct->name)) {
|
||||
GCstr *s = gco2str(gcref(ct->name));
|
||||
setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "name")), s);
|
||||
}
|
||||
lj_gc_check(L);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
LJLIB_CF(ffi_istype) LJLIB_REC(.)
|
||||
{
|
||||
CTState *cts = ctype_cts(L);
|
||||
|
@ -725,6 +748,9 @@ LJLIB_CF(ffi_abi) LJLIB_REC(.)
|
|||
case H_(4ab624a8,4ab624a8): b = 1; break; /* win */
|
||||
#endif
|
||||
case H_(3af93066,1f001464): b = 1; break; /* le/be */
|
||||
#if LJ_GC64
|
||||
case H_(9e89d2c9,13c83c92): b = 1; break; /* gc64 */
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -768,19 +794,11 @@ LJLIB_CF(ffi_gc) LJLIB_REC(.)
|
|||
GCcdata *cd = ffi_checkcdata(L, 1);
|
||||
TValue *fin = lj_lib_checkany(L, 2);
|
||||
CTState *cts = ctype_cts(L);
|
||||
GCtab *t = cts->finalizer;
|
||||
CType *ct = ctype_raw(cts, cd->ctypeid);
|
||||
if (!(ctype_isptr(ct->info) || ctype_isstruct(ct->info) ||
|
||||
ctype_isrefarray(ct->info)))
|
||||
lj_err_arg(L, 1, LJ_ERR_FFI_INVTYPE);
|
||||
if (gcref(t->metatable)) { /* Update finalizer table, if still enabled. */
|
||||
copyTV(L, lj_tab_set(L, t, L->base), fin);
|
||||
lj_gc_anybarriert(L, t);
|
||||
if (!tvisnil(fin))
|
||||
cd->marked |= LJ_GC_CDATA_FIN;
|
||||
else
|
||||
cd->marked &= ~LJ_GC_CDATA_FIN;
|
||||
}
|
||||
lj_cdata_setfin(L, cd, gcval(fin), itype(fin));
|
||||
L->top = L->base+1; /* Pass through the cdata object. */
|
||||
return 1;
|
||||
}
|
||||
|
@ -811,7 +829,7 @@ static GCtab *ffi_finalizer(lua_State *L)
|
|||
settabV(L, L->top++, t);
|
||||
setgcref(t->metatable, obj2gco(t));
|
||||
setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")),
|
||||
lj_str_newlit(L, "K"));
|
||||
lj_str_newlit(L, "k"));
|
||||
t->nomm = (uint8_t)(~(1u<<MM_mode));
|
||||
return t;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Library initialization.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major parts taken verbatim from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** I/O library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
|
@ -19,8 +19,10 @@
|
|||
#include "lj_obj.h"
|
||||
#include "lj_gc.h"
|
||||
#include "lj_err.h"
|
||||
#include "lj_buf.h"
|
||||
#include "lj_str.h"
|
||||
#include "lj_state.h"
|
||||
#include "lj_strfmt.h"
|
||||
#include "lj_ff.h"
|
||||
#include "lj_lib.h"
|
||||
|
||||
|
@ -96,13 +98,13 @@ static IOFileUD *io_file_open(lua_State *L, const char *mode)
|
|||
wchar_t wfname[MAX_PATH];
|
||||
wchar_t wmode[MAX_PATH];
|
||||
if (!widen(fname, wfname) || !widen(mode, wmode))
|
||||
luaL_argerror(L, 1, lj_str_pushf(L, "%s: failed to convert path to utf-16", fname));
|
||||
luaL_argerror(L, 1, lj_strfmt_pushf(L, "%s: failed to convert path to utf-16", fname));
|
||||
iof->fp = _wfopen(wfname, wmode);
|
||||
#else
|
||||
iof->fp = fopen(fname, mode);
|
||||
#endif
|
||||
if (iof->fp == NULL)
|
||||
luaL_argerror(L, 1, lj_str_pushf(L, "%s: %s", fname, strerror(errno)));
|
||||
luaL_argerror(L, 1, lj_strfmt_pushf(L, "%s: %s", fname, strerror(errno)));
|
||||
return iof;
|
||||
}
|
||||
|
||||
|
@ -115,7 +117,7 @@ static int io_file_close(lua_State *L, IOFileUD *iof)
|
|||
int stat = -1;
|
||||
#if LJ_TARGET_POSIX
|
||||
stat = pclose(iof->fp);
|
||||
#elif LJ_TARGET_WINDOWS
|
||||
#elif LJ_TARGET_WINDOWS && !LJ_TARGET_XBOXONE
|
||||
stat = _pclose(iof->fp);
|
||||
#else
|
||||
lua_assert(0);
|
||||
|
@ -163,7 +165,7 @@ static int io_file_readline(lua_State *L, FILE *fp, MSize chop)
|
|||
MSize m = LUAL_BUFFERSIZE, n = 0, ok = 0;
|
||||
char *buf;
|
||||
for (;;) {
|
||||
buf = lj_str_needbuf(L, &G(L)->tmpbuf, m);
|
||||
buf = lj_buf_tmp(L, m);
|
||||
if (fgets(buf+n, m-n, fp) == NULL) break;
|
||||
n += (MSize)strlen(buf+n);
|
||||
ok |= n;
|
||||
|
@ -179,7 +181,7 @@ static void io_file_readall(lua_State *L, FILE *fp)
|
|||
{
|
||||
MSize m, n;
|
||||
for (m = LUAL_BUFFERSIZE, n = 0; ; m += m) {
|
||||
char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, m);
|
||||
char *buf = lj_buf_tmp(L, m);
|
||||
n += (MSize)fread(buf+n, 1, m-n, fp);
|
||||
if (n != m) {
|
||||
setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
|
||||
|
@ -192,7 +194,7 @@ static void io_file_readall(lua_State *L, FILE *fp)
|
|||
static int io_file_readlen(lua_State *L, FILE *fp, MSize m)
|
||||
{
|
||||
if (m) {
|
||||
char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, m);
|
||||
char *buf = lj_buf_tmp(L, m);
|
||||
MSize n = (MSize)fread(buf, 1, m, fp);
|
||||
setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
|
||||
lj_gc_check(L);
|
||||
|
@ -219,13 +221,12 @@ static int io_file_read(lua_State *L, FILE *fp, int start)
|
|||
for (n = start; nargs-- && ok; n++) {
|
||||
if (tvisstr(L->base+n)) {
|
||||
const char *p = strVdata(L->base+n);
|
||||
if (p[0] != '*')
|
||||
lj_err_arg(L, n+1, LJ_ERR_INVOPT);
|
||||
if (p[1] == 'n')
|
||||
if (p[0] == '*') p++;
|
||||
if (p[0] == 'n')
|
||||
ok = io_file_readnum(L, fp);
|
||||
else if ((p[1] & ~0x20) == 'L')
|
||||
ok = io_file_readline(L, fp, (p[1] == 'l'));
|
||||
else if (p[1] == 'a')
|
||||
else if ((p[0] & ~0x20) == 'L')
|
||||
ok = io_file_readline(L, fp, (p[0] == 'l'));
|
||||
else if (p[0] == 'a')
|
||||
io_file_readall(L, fp);
|
||||
else
|
||||
lj_err_arg(L, n+1, LJ_ERR_INVFMT);
|
||||
|
@ -248,19 +249,11 @@ static int io_file_write(lua_State *L, FILE *fp, int start)
|
|||
cTValue *tv;
|
||||
int status = 1;
|
||||
for (tv = L->base+start; tv < L->top; tv++) {
|
||||
if (tvisstr(tv)) {
|
||||
MSize len = strV(tv)->len;
|
||||
status = status && (fwrite(strVdata(tv), 1, len, fp) == len);
|
||||
} else if (tvisint(tv)) {
|
||||
char buf[LJ_STR_INTBUF];
|
||||
char *p = lj_str_bufint(buf, intV(tv));
|
||||
size_t len = (size_t)(buf+LJ_STR_INTBUF-p);
|
||||
status = status && (fwrite(p, 1, len, fp) == len);
|
||||
} else if (tvisnum(tv)) {
|
||||
status = status && (fprintf(fp, LUA_NUMBER_FMT, numV(tv)) > 0);
|
||||
} else {
|
||||
MSize len;
|
||||
const char *p = lj_strfmt_wstrnum(L, tv, &len);
|
||||
if (!p)
|
||||
lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING);
|
||||
}
|
||||
status = status && (fwrite(p, 1, len, fp) == len);
|
||||
}
|
||||
if (LJ_52 && status) {
|
||||
L->top = L->base+1;
|
||||
|
@ -296,6 +289,15 @@ static int io_file_iter(lua_State *L)
|
|||
return n;
|
||||
}
|
||||
|
||||
static int io_file_lines(lua_State *L)
|
||||
{
|
||||
int n = (int)(L->top - L->base);
|
||||
if (n > LJ_MAX_UPVAL)
|
||||
lj_err_caller(L, LJ_ERR_UNPACK);
|
||||
lua_pushcclosure(L, io_file_iter, n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -- I/O file methods ---------------------------------------------------- */
|
||||
|
||||
#define LJLIB_MODULE_io_method
|
||||
|
@ -379,8 +381,7 @@ LJLIB_CF(io_method_setvbuf)
|
|||
LJLIB_CF(io_method_lines)
|
||||
{
|
||||
io_tofile(L);
|
||||
lua_pushcclosure(L, io_file_iter, (int)(L->top - L->base));
|
||||
return 1;
|
||||
return io_file_lines(L);
|
||||
}
|
||||
|
||||
LJLIB_CF(io_method___gc)
|
||||
|
@ -430,7 +431,7 @@ LJLIB_CF(io_open)
|
|||
|
||||
LJLIB_CF(io_popen)
|
||||
{
|
||||
#if LJ_TARGET_POSIX || LJ_TARGET_WINDOWS
|
||||
#if LJ_TARGET_POSIX || (LJ_TARGET_WINDOWS && !LJ_TARGET_XBOXONE)
|
||||
const char *fname = strdata(lj_lib_checkstr(L, 1));
|
||||
GCstr *s = lj_lib_optstr(L, 2);
|
||||
const char *mode = s ? strdata(s) : "r";
|
||||
|
@ -520,8 +521,7 @@ LJLIB_CF(io_lines)
|
|||
} else { /* io.lines() iterates over stdin. */
|
||||
setudataV(L, L->base, IOSTDF_UD(L, GCROOT_IO_INPUT));
|
||||
}
|
||||
lua_pushcclosure(L, io_file_iter, (int)(L->top - L->base));
|
||||
return 1;
|
||||
return io_file_lines(L);
|
||||
}
|
||||
|
||||
LJLIB_CF(io_type)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** JIT library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#define lib_jit_c
|
||||
|
@ -10,13 +10,17 @@
|
|||
#include "lauxlib.h"
|
||||
#include "lualib.h"
|
||||
|
||||
#include "lj_arch.h"
|
||||
#include "lj_obj.h"
|
||||
#include "lj_gc.h"
|
||||
#include "lj_err.h"
|
||||
#include "lj_debug.h"
|
||||
#include "lj_str.h"
|
||||
#include "lj_tab.h"
|
||||
#include "lj_state.h"
|
||||
#include "lj_bc.h"
|
||||
#if LJ_HASFFI
|
||||
#include "lj_ctype.h"
|
||||
#endif
|
||||
#if LJ_HASJIT
|
||||
#include "lj_ir.h"
|
||||
#include "lj_jit.h"
|
||||
|
@ -24,6 +28,7 @@
|
|||
#include "lj_iropt.h"
|
||||
#include "lj_target.h"
|
||||
#endif
|
||||
#include "lj_trace.h"
|
||||
#include "lj_dispatch.h"
|
||||
#include "lj_vm.h"
|
||||
#include "lj_vmevent.h"
|
||||
|
@ -199,6 +204,7 @@ LJLIB_CF(jit_util_funcinfo)
|
|||
lua_setfield(L, -2, "source");
|
||||
lj_debug_pushloc(L, pt, pc);
|
||||
lua_setfield(L, -2, "loc");
|
||||
setprotoV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "proto")), pt);
|
||||
} else {
|
||||
GCfunc *fn = funcV(L->base);
|
||||
GCtab *t;
|
||||
|
@ -279,7 +285,7 @@ static GCtrace *jit_checktrace(lua_State *L)
|
|||
/* Names of link types. ORDER LJ_TRLINK */
|
||||
static const char *const jit_trlinkname[] = {
|
||||
"none", "root", "loop", "tail-recursion", "up-recursion", "down-recursion",
|
||||
"interpreter", "return"
|
||||
"interpreter", "return", "stitch"
|
||||
};
|
||||
|
||||
/* local info = jit.util.traceinfo(tr) */
|
||||
|
@ -332,6 +338,13 @@ LJLIB_CF(jit_util_tracek)
|
|||
slot = ir->op2;
|
||||
ir = &T->ir[ir->op1];
|
||||
}
|
||||
#if LJ_HASFFI
|
||||
if (ir->o == IR_KINT64 && !ctype_ctsG(G(L))) {
|
||||
ptrdiff_t oldtop = savestack(L, L->top);
|
||||
luaopen_ffi(L); /* Load FFI library on-demand. */
|
||||
L->top = restorestack(L, oldtop);
|
||||
}
|
||||
#endif
|
||||
lj_ir_kvalue(L, L->top-2, ir);
|
||||
setintV(L->top-1, (int32_t)irt_type(ir->t));
|
||||
if (slot == -1)
|
||||
|
@ -416,6 +429,12 @@ LJLIB_CF(jit_util_ircalladdr)
|
|||
|
||||
#include "lj_libdef.h"
|
||||
|
||||
static int luaopen_jit_util(lua_State *L)
|
||||
{
|
||||
LJ_LIB_REG(L, NULL, jit_util);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* -- jit.opt module ------------------------------------------------------ */
|
||||
|
||||
#if LJ_HASJIT
|
||||
|
@ -513,6 +532,104 @@ LJLIB_CF(jit_opt_start)
|
|||
|
||||
#endif
|
||||
|
||||
/* -- jit.profile module -------------------------------------------------- */
|
||||
|
||||
#if LJ_HASPROFILE
|
||||
|
||||
#define LJLIB_MODULE_jit_profile
|
||||
|
||||
/* Not loaded by default, use: local profile = require("jit.profile") */
|
||||
|
||||
static const char KEY_PROFILE_THREAD = 't';
|
||||
static const char KEY_PROFILE_FUNC = 'f';
|
||||
|
||||
static void jit_profile_callback(lua_State *L2, lua_State *L, int samples,
|
||||
int vmstate)
|
||||
{
|
||||
TValue key;
|
||||
cTValue *tv;
|
||||
setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
|
||||
tv = lj_tab_get(L, tabV(registry(L)), &key);
|
||||
if (tvisfunc(tv)) {
|
||||
char vmst = (char)vmstate;
|
||||
int status;
|
||||
setfuncV(L2, L2->top++, funcV(tv));
|
||||
setthreadV(L2, L2->top++, L);
|
||||
setintV(L2->top++, samples);
|
||||
setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1));
|
||||
status = lua_pcall(L2, 3, 0, 0); /* callback(thread, samples, vmstate) */
|
||||
if (status) {
|
||||
if (G(L2)->panic) G(L2)->panic(L2);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
lj_trace_abort(G(L2));
|
||||
}
|
||||
}
|
||||
|
||||
/* profile.start(mode, cb) */
|
||||
LJLIB_CF(jit_profile_start)
|
||||
{
|
||||
GCtab *registry = tabV(registry(L));
|
||||
GCstr *mode = lj_lib_optstr(L, 1);
|
||||
GCfunc *func = lj_lib_checkfunc(L, 2);
|
||||
lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */
|
||||
TValue key;
|
||||
/* Anchor thread and function in registry. */
|
||||
setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
|
||||
setthreadV(L, lj_tab_set(L, registry, &key), L2);
|
||||
setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
|
||||
setfuncV(L, lj_tab_set(L, registry, &key), func);
|
||||
lj_gc_anybarriert(L, registry);
|
||||
luaJIT_profile_start(L, mode ? strdata(mode) : "",
|
||||
(luaJIT_profile_callback)jit_profile_callback, L2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* profile.stop() */
|
||||
LJLIB_CF(jit_profile_stop)
|
||||
{
|
||||
GCtab *registry;
|
||||
TValue key;
|
||||
luaJIT_profile_stop(L);
|
||||
registry = tabV(registry(L));
|
||||
setlightudV(&key, (void *)&KEY_PROFILE_THREAD);
|
||||
setnilV(lj_tab_set(L, registry, &key));
|
||||
setlightudV(&key, (void *)&KEY_PROFILE_FUNC);
|
||||
setnilV(lj_tab_set(L, registry, &key));
|
||||
lj_gc_anybarriert(L, registry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* dump = profile.dumpstack([thread,] fmt, depth) */
|
||||
LJLIB_CF(jit_profile_dumpstack)
|
||||
{
|
||||
lua_State *L2 = L;
|
||||
int arg = 0;
|
||||
size_t len;
|
||||
int depth;
|
||||
GCstr *fmt;
|
||||
const char *p;
|
||||
if (L->top > L->base && tvisthread(L->base)) {
|
||||
L2 = threadV(L->base);
|
||||
arg = 1;
|
||||
}
|
||||
fmt = lj_lib_checkstr(L, arg+1);
|
||||
depth = lj_lib_checkint(L, arg+2);
|
||||
p = luaJIT_profile_dumpstack(L2, strdata(fmt), depth, &len);
|
||||
lua_pushlstring(L, p, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include "lj_libdef.h"
|
||||
|
||||
static int luaopen_jit_profile(lua_State *L)
|
||||
{
|
||||
LJ_LIB_REG(L, NULL, jit_profile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* -- JIT compiler initialization ----------------------------------------- */
|
||||
|
||||
#if LJ_HASJIT
|
||||
|
@ -538,38 +655,31 @@ static uint32_t jit_cpudetect(lua_State *L)
|
|||
uint32_t features[4];
|
||||
if (lj_vm_cpuid(0, vendor) && lj_vm_cpuid(1, features)) {
|
||||
#if !LJ_HASJIT
|
||||
#define JIT_F_CMOV 1
|
||||
#define JIT_F_SSE2 2
|
||||
#endif
|
||||
flags |= ((features[3] >> 15)&1) * JIT_F_CMOV;
|
||||
flags |= ((features[3] >> 26)&1) * JIT_F_SSE2;
|
||||
#if LJ_HASJIT
|
||||
flags |= ((features[2] >> 0)&1) * JIT_F_SSE3;
|
||||
flags |= ((features[2] >> 19)&1) * JIT_F_SSE4_1;
|
||||
if (vendor[2] == 0x6c65746e) { /* Intel. */
|
||||
if ((features[0] & 0x0ff00f00) == 0x00000f00) /* P4. */
|
||||
flags |= JIT_F_P4; /* Currently unused. */
|
||||
else if ((features[0] & 0x0fff0ff0) == 0x000106c0) /* Atom. */
|
||||
if ((features[0] & 0x0fff0ff0) == 0x000106c0) /* Atom. */
|
||||
flags |= JIT_F_LEA_AGU;
|
||||
} else if (vendor[2] == 0x444d4163) { /* AMD. */
|
||||
uint32_t fam = (features[0] & 0x0ff00f00);
|
||||
if (fam == 0x00000f00) /* K8. */
|
||||
flags |= JIT_F_SPLIT_XMM;
|
||||
if (fam >= 0x00000f00) /* K8, K10. */
|
||||
flags |= JIT_F_PREFER_IMUL;
|
||||
}
|
||||
if (vendor[0] >= 7) {
|
||||
uint32_t xfeatures[4];
|
||||
lj_vm_cpuid(7, xfeatures);
|
||||
flags |= ((xfeatures[1] >> 8)&1) * JIT_F_BMI2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* Check for required instruction set support on x86 (unnecessary on x64). */
|
||||
#if LJ_TARGET_X86
|
||||
#if !defined(LUAJIT_CPU_NOCMOV)
|
||||
if (!(flags & JIT_F_CMOV))
|
||||
luaL_error(L, "CPU not supported");
|
||||
#endif
|
||||
#if defined(LUAJIT_CPU_SSE2)
|
||||
if (!(flags & JIT_F_SSE2))
|
||||
luaL_error(L, "CPU does not support SSE2 (recompile without -DLUAJIT_CPU_SSE2)");
|
||||
#endif
|
||||
luaL_error(L, "CPU with SSE2 required");
|
||||
#endif
|
||||
#elif LJ_TARGET_ARM
|
||||
#if LJ_HASJIT
|
||||
|
@ -591,6 +701,8 @@ static uint32_t jit_cpudetect(lua_State *L)
|
|||
ver >= 60 ? JIT_F_ARMV6_ : 0;
|
||||
flags |= LJ_ARCH_HASFPU == 0 ? 0 : ver >= 70 ? JIT_F_VFPV3 : JIT_F_VFPV2;
|
||||
#endif
|
||||
#elif LJ_TARGET_ARM64
|
||||
/* No optional CPU features to detect (for now). */
|
||||
#elif LJ_TARGET_PPC
|
||||
#if LJ_HASJIT
|
||||
#if LJ_ARCH_SQRT
|
||||
|
@ -600,21 +712,23 @@ static uint32_t jit_cpudetect(lua_State *L)
|
|||
flags |= JIT_F_ROUND;
|
||||
#endif
|
||||
#endif
|
||||
#elif LJ_TARGET_PPCSPE
|
||||
/* Nothing to do. */
|
||||
#elif LJ_TARGET_MIPS
|
||||
#if LJ_HASJIT
|
||||
/* Compile-time MIPS CPU detection. */
|
||||
#if LJ_ARCH_VERSION >= 20
|
||||
flags |= JIT_F_MIPS32R2;
|
||||
flags |= JIT_F_MIPSXXR2;
|
||||
#endif
|
||||
/* Runtime MIPS CPU detection. */
|
||||
#if defined(__GNUC__)
|
||||
if (!(flags & JIT_F_MIPS32R2)) {
|
||||
if (!(flags & JIT_F_MIPSXXR2)) {
|
||||
int x;
|
||||
#ifdef __mips16
|
||||
x = 0; /* Runtime detection is difficult. Ensure optimal -march flags. */
|
||||
#else
|
||||
/* On MIPS32R1 rotr is treated as srl. rotr r2,r2,1 -> srl r2,r2,1. */
|
||||
__asm__("li $2, 1\n\t.long 0x00221042\n\tmove %0, $2" : "=r"(x) : : "$2");
|
||||
if (x) flags |= JIT_F_MIPS32R2; /* Either 0x80000000 (R2) or 0 (R1). */
|
||||
#endif
|
||||
if (x) flags |= JIT_F_MIPSXXR2; /* Either 0x80000000 (R2) or 0 (R1). */
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -631,11 +745,7 @@ static void jit_init(lua_State *L)
|
|||
uint32_t flags = jit_cpudetect(L);
|
||||
#if LJ_HASJIT
|
||||
jit_State *J = L2J(L);
|
||||
#if LJ_TARGET_X86
|
||||
/* Silently turn off the JIT compiler on CPUs without SSE2. */
|
||||
if ((flags & JIT_F_SSE2))
|
||||
#endif
|
||||
J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT;
|
||||
J->flags = flags | JIT_F_ON | JIT_F_OPT_DEFAULT;
|
||||
memcpy(J->param, jit_param_default, sizeof(J->param));
|
||||
lj_dispatch_update(G(L));
|
||||
#else
|
||||
|
@ -645,19 +755,23 @@ static void jit_init(lua_State *L)
|
|||
|
||||
LUALIB_API int luaopen_jit(lua_State *L)
|
||||
{
|
||||
jit_init(L);
|
||||
lua_pushliteral(L, LJ_OS_NAME);
|
||||
lua_pushliteral(L, LJ_ARCH_NAME);
|
||||
lua_pushinteger(L, LUAJIT_VERSION_NUM);
|
||||
lua_pushliteral(L, LUAJIT_VERSION);
|
||||
LJ_LIB_REG(L, LUA_JITLIBNAME, jit);
|
||||
#if LJ_HASPROFILE
|
||||
lj_lib_prereg(L, LUA_JITLIBNAME ".profile", luaopen_jit_profile,
|
||||
tabref(L->env));
|
||||
#endif
|
||||
#ifndef LUAJIT_DISABLE_JITUTIL
|
||||
LJ_LIB_REG(L, "jit.util", jit_util);
|
||||
lj_lib_prereg(L, LUA_JITLIBNAME ".util", luaopen_jit_util, tabref(L->env));
|
||||
#endif
|
||||
#if LJ_HASJIT
|
||||
LJ_LIB_REG(L, "jit.opt", jit_opt);
|
||||
#endif
|
||||
L->top -= 2;
|
||||
jit_init(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Math library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
@ -47,12 +47,6 @@ LJLIB_ASM_(math_tanh) LJLIB_REC(math_htrig IRCALL_tanh)
|
|||
LJLIB_ASM_(math_frexp)
|
||||
LJLIB_ASM_(math_modf) LJLIB_REC(.)
|
||||
|
||||
LJLIB_PUSH(57.29577951308232)
|
||||
LJLIB_ASM_(math_deg) LJLIB_REC(math_degrad)
|
||||
|
||||
LJLIB_PUSH(0.017453292519943295)
|
||||
LJLIB_ASM_(math_rad) LJLIB_REC(math_degrad)
|
||||
|
||||
LJLIB_ASM(math_log) LJLIB_REC(math_log)
|
||||
{
|
||||
double x = lj_lib_checknum(L, 1);
|
||||
|
@ -63,12 +57,15 @@ LJLIB_ASM(math_log) LJLIB_REC(math_log)
|
|||
#else
|
||||
x = lj_vm_log2(x); y = 1.0 / lj_vm_log2(y);
|
||||
#endif
|
||||
setnumV(L->base-1, x*y); /* Do NOT join the expression to x / y. */
|
||||
setnumV(L->base-1-LJ_FR2, x*y); /* Do NOT join the expression to x / y. */
|
||||
return FFH_RES(1);
|
||||
}
|
||||
return FFH_RETRY;
|
||||
}
|
||||
|
||||
LJLIB_LUA(math_deg) /* function(x) return x * 57.29577951308232 end */
|
||||
LJLIB_LUA(math_rad) /* function(x) return x * 0.017453292519943295 end */
|
||||
|
||||
LJLIB_ASM(math_atan2) LJLIB_REC(.)
|
||||
{
|
||||
lj_lib_checknum(L, 1);
|
||||
|
@ -224,10 +221,6 @@ LUALIB_API int luaopen_math(lua_State *L)
|
|||
rs = (RandomState *)lua_newuserdata(L, sizeof(RandomState));
|
||||
rs->valid = 0; /* Use lazy initialization to save some time on startup. */
|
||||
LJ_LIB_REG(L, LUA_MATHLIBNAME, math);
|
||||
#if defined(LUA_COMPAT_MOD) && !LJ_52
|
||||
lua_getfield(L, -1, "fmod");
|
||||
lua_setfield(L, -2, "mod");
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** OS library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
|
@ -17,7 +17,10 @@
|
|||
#include "lualib.h"
|
||||
|
||||
#include "lj_obj.h"
|
||||
#include "lj_gc.h"
|
||||
#include "lj_err.h"
|
||||
#include "lj_buf.h"
|
||||
#include "lj_str.h"
|
||||
#include "lj_lib.h"
|
||||
|
||||
#if LJ_TARGET_POSIX
|
||||
|
@ -53,7 +56,7 @@ static wchar_t *widen_static(const char *narrow, int idx)
|
|||
|
||||
LJLIB_CF(os_execute)
|
||||
{
|
||||
#if LJ_TARGET_CONSOLE
|
||||
#if LJ_NO_SYSTEM
|
||||
#if LJ_52
|
||||
errno = ENOSYS;
|
||||
return luaL_fileresult(L, 0, NULL);
|
||||
|
@ -205,7 +208,7 @@ LJLIB_CF(os_date)
|
|||
#endif
|
||||
}
|
||||
if (stm == NULL) { /* Invalid date? */
|
||||
setnilV(L->top-1);
|
||||
setnilV(L->top++);
|
||||
} else if (strcmp(s, "*t") == 0) {
|
||||
lua_createtable(L, 0, 9); /* 9 = number of fields */
|
||||
setfield(L, "sec", stm->tm_sec);
|
||||
|
@ -217,23 +220,25 @@ LJLIB_CF(os_date)
|
|||
setfield(L, "wday", stm->tm_wday+1);
|
||||
setfield(L, "yday", stm->tm_yday+1);
|
||||
setboolfield(L, "isdst", stm->tm_isdst);
|
||||
} else {
|
||||
char cc[3];
|
||||
luaL_Buffer b;
|
||||
cc[0] = '%'; cc[2] = '\0';
|
||||
luaL_buffinit(L, &b);
|
||||
for (; *s; s++) {
|
||||
if (*s != '%' || *(s + 1) == '\0') { /* No conversion specifier? */
|
||||
luaL_addchar(&b, *s);
|
||||
} else {
|
||||
size_t reslen;
|
||||
char buff[200]; /* Should be big enough for any conversion result. */
|
||||
cc[1] = *(++s);
|
||||
reslen = strftime(buff, sizeof(buff), cc, stm);
|
||||
luaL_addlstring(&b, buff, reslen);
|
||||
} else if (*s) {
|
||||
SBuf *sb = &G(L)->tmpbuf;
|
||||
MSize sz = 0;
|
||||
const char *q;
|
||||
for (q = s; *q; q++)
|
||||
sz += (*q == '%') ? 30 : 1; /* Overflow doesn't matter. */
|
||||
setsbufL(sb, L);
|
||||
for (;;) {
|
||||
char *buf = lj_buf_need(sb, sz);
|
||||
size_t len = strftime(buf, sbufsz(sb), s, stm);
|
||||
if (len) {
|
||||
setstrV(L, L->top++, lj_str_new(L, buf, len));
|
||||
lj_gc_check(L);
|
||||
break;
|
||||
}
|
||||
sz += (sz|1);
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
} else {
|
||||
setstrV(L, L->top++, &G(L)->strempty);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Package library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2012 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
|
@ -96,9 +96,17 @@ static void setprogdir(lua_State *L)
|
|||
static void pusherror(lua_State *L)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
#if LJ_TARGET_XBOXONE
|
||||
wchar_t wbuffer[128];
|
||||
char buffer[128*2];
|
||||
if (FormatMessageW(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, error, 0, wbuffer, sizeof(wbuffer)/sizeof(wchar_t), NULL) &&
|
||||
WideCharToMultiByte(CP_ACP, 0, wbuffer, 128, buffer, 128*2, NULL, NULL))
|
||||
#else
|
||||
char buffer[128];
|
||||
if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, error, 0, buffer, sizeof(buffer), NULL))
|
||||
#endif
|
||||
lua_pushstring(L, buffer);
|
||||
else
|
||||
lua_pushfstring(L, "system error %d\n", error);
|
||||
|
@ -111,7 +119,7 @@ static void ll_unloadlib(void *lib)
|
|||
|
||||
static void *ll_load(lua_State *L, const char *path, int gl)
|
||||
{
|
||||
HINSTANCE lib = LoadLibraryA(path);
|
||||
HINSTANCE lib = LoadLibraryExA(path, NULL, 0);
|
||||
if (lib == NULL) pusherror(L);
|
||||
UNUSED(gl);
|
||||
return lib;
|
||||
|
@ -185,8 +193,7 @@ static void **ll_register(lua_State *L, const char *path)
|
|||
lua_pop(L, 1);
|
||||
plib = (void **)lua_newuserdata(L, sizeof(void *));
|
||||
*plib = NULL;
|
||||
luaL_getmetatable(L, "_LOADLIB");
|
||||
lua_setmetatable(L, -2);
|
||||
luaL_setmetatable(L, "_LOADLIB");
|
||||
lua_pushfstring(L, "LOADLIB: %s", path);
|
||||
lua_pushvalue(L, -2);
|
||||
lua_settable(L, LUA_REGISTRYINDEX);
|
||||
|
@ -226,7 +233,7 @@ static int ll_loadfunc(lua_State *L, const char *path, const char *name, int r)
|
|||
const char *bcdata = ll_bcsym(*reg, mksymname(L, name, SYMPREFIX_BC));
|
||||
lua_pop(L, 1);
|
||||
if (bcdata) {
|
||||
if (luaL_loadbuffer(L, bcdata, ~(size_t)0, name) != 0)
|
||||
if (luaL_loadbuffer(L, bcdata, LJ_MAX_BUF, name) != 0)
|
||||
return PACKAGE_ERR_LOAD;
|
||||
return 0;
|
||||
}
|
||||
|
@ -383,7 +390,7 @@ static int lj_cf_package_loader_preload(lua_State *L)
|
|||
if (lua_isnil(L, -1)) { /* Not found? */
|
||||
const char *bcname = mksymname(L, name, SYMPREFIX_BC);
|
||||
const char *bcdata = ll_bcsym(NULL, bcname);
|
||||
if (bcdata == NULL || luaL_loadbuffer(L, bcdata, ~(size_t)0, name) != 0)
|
||||
if (bcdata == NULL || luaL_loadbuffer(L, bcdata, LJ_MAX_BUF, name) != 0)
|
||||
lua_pushfstring(L, "\n\tno field package.preload['%s']", name);
|
||||
}
|
||||
return 1;
|
||||
|
@ -391,8 +398,7 @@ static int lj_cf_package_loader_preload(lua_State *L)
|
|||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static const int sentinel_ = 0;
|
||||
#define sentinel ((void *)&sentinel_)
|
||||
#define sentinel ((void *)0x4004)
|
||||
|
||||
static int lj_cf_package_require(lua_State *L)
|
||||
{
|
||||
|
@ -482,29 +488,19 @@ static void modinit(lua_State *L, const char *modname)
|
|||
static int lj_cf_package_module(lua_State *L)
|
||||
{
|
||||
const char *modname = luaL_checkstring(L, 1);
|
||||
int loaded = lua_gettop(L) + 1; /* index of _LOADED table */
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
|
||||
lua_getfield(L, loaded, modname); /* get _LOADED[modname] */
|
||||
if (!lua_istable(L, -1)) { /* not found? */
|
||||
lua_pop(L, 1); /* remove previous result */
|
||||
/* try global variable (and create one if it does not exist) */
|
||||
if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)
|
||||
lj_err_callerv(L, LJ_ERR_BADMODN, modname);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */
|
||||
}
|
||||
/* check whether table already has a _NAME field */
|
||||
int lastarg = (int)(L->top - L->base);
|
||||
luaL_pushmodule(L, modname, 1);
|
||||
lua_getfield(L, -1, "_NAME");
|
||||
if (!lua_isnil(L, -1)) { /* is table an initialized module? */
|
||||
if (!lua_isnil(L, -1)) { /* Module already initialized? */
|
||||
lua_pop(L, 1);
|
||||
} else { /* no; initialize it */
|
||||
} else {
|
||||
lua_pop(L, 1);
|
||||
modinit(L, modname);
|
||||
}
|
||||
lua_pushvalue(L, -1);
|
||||
setfenv(L);
|
||||
dooptions(L, loaded - 1);
|
||||
return 0;
|
||||
dooptions(L, lastarg);
|
||||
return LJ_52;
|
||||
}
|
||||
|
||||
static int lj_cf_package_seeall(lua_State *L)
|
||||
|
@ -575,13 +571,16 @@ LUALIB_API int luaopen_package(lua_State *L)
|
|||
lj_lib_pushcf(L, lj_cf_package_unloadlib, 1);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
luaL_register(L, LUA_LOADLIBNAME, package_lib);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_replace(L, LUA_ENVIRONINDEX);
|
||||
lua_copy(L, -1, LUA_ENVIRONINDEX);
|
||||
lua_createtable(L, sizeof(package_loaders)/sizeof(package_loaders[0])-1, 0);
|
||||
for (i = 0; package_loaders[i] != NULL; i++) {
|
||||
lj_lib_pushcf(L, package_loaders[i], 1);
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
#if LJ_52
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -3, "searchers");
|
||||
#endif
|
||||
lua_setfield(L, -2, "loaders");
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV");
|
||||
noenv = lua_toboolean(L, -1);
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
/*
|
||||
** String library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define lib_string_c
|
||||
#define LUA_LIB
|
||||
|
||||
|
@ -18,6 +16,7 @@
|
|||
#include "lj_obj.h"
|
||||
#include "lj_gc.h"
|
||||
#include "lj_err.h"
|
||||
#include "lj_buf.h"
|
||||
#include "lj_str.h"
|
||||
#include "lj_tab.h"
|
||||
#include "lj_meta.h"
|
||||
|
@ -25,17 +24,19 @@
|
|||
#include "lj_ff.h"
|
||||
#include "lj_bcdump.h"
|
||||
#include "lj_char.h"
|
||||
#include "lj_strfmt.h"
|
||||
#include "lj_lib.h"
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#define LJLIB_MODULE_string
|
||||
|
||||
LJLIB_ASM(string_len) LJLIB_REC(.)
|
||||
{
|
||||
lj_lib_checkstr(L, 1);
|
||||
return FFH_RETRY;
|
||||
}
|
||||
LJLIB_LUA(string_len) /*
|
||||
function(s)
|
||||
CHECK_str(s)
|
||||
return #s
|
||||
end
|
||||
*/
|
||||
|
||||
LJLIB_ASM(string_byte) LJLIB_REC(string_range 0)
|
||||
{
|
||||
|
@ -57,21 +58,21 @@ LJLIB_ASM(string_byte) LJLIB_REC(string_range 0)
|
|||
lj_state_checkstack(L, (MSize)n);
|
||||
p = (const unsigned char *)strdata(s) + start;
|
||||
for (i = 0; i < n; i++)
|
||||
setintV(L->base + i-1, p[i]);
|
||||
setintV(L->base + i-1-LJ_FR2, p[i]);
|
||||
return FFH_RES(n);
|
||||
}
|
||||
|
||||
LJLIB_ASM(string_char)
|
||||
LJLIB_ASM(string_char) LJLIB_REC(.)
|
||||
{
|
||||
int i, nargs = (int)(L->top - L->base);
|
||||
char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, (MSize)nargs);
|
||||
char *buf = lj_buf_tmp(L, (MSize)nargs);
|
||||
for (i = 1; i <= nargs; i++) {
|
||||
int32_t k = lj_lib_checkint(L, i);
|
||||
if (!checku8(k))
|
||||
lj_err_arg(L, i, LJ_ERR_BADVAL);
|
||||
buf[i-1] = (char)k;
|
||||
}
|
||||
setstrV(L, L->base-1, lj_str_new(L, buf, (size_t)nargs));
|
||||
setstrV(L, L->base-1-LJ_FR2, lj_str_new(L, buf, (size_t)nargs));
|
||||
return FFH_RES(1);
|
||||
}
|
||||
|
||||
|
@ -83,68 +84,38 @@ LJLIB_ASM(string_sub) LJLIB_REC(string_range 1)
|
|||
return FFH_RETRY;
|
||||
}
|
||||
|
||||
LJLIB_ASM(string_rep)
|
||||
LJLIB_CF(string_rep) LJLIB_REC(.)
|
||||
{
|
||||
GCstr *s = lj_lib_checkstr(L, 1);
|
||||
int32_t k = lj_lib_checkint(L, 2);
|
||||
int32_t rep = lj_lib_checkint(L, 2);
|
||||
GCstr *sep = lj_lib_optstr(L, 3);
|
||||
int32_t len = (int32_t)s->len;
|
||||
global_State *g = G(L);
|
||||
int64_t tlen;
|
||||
const char *src;
|
||||
char *buf;
|
||||
if (k <= 0) {
|
||||
empty:
|
||||
setstrV(L, L->base-1, &g->strempty);
|
||||
return FFH_RES(1);
|
||||
SBuf *sb = lj_buf_tmp_(L);
|
||||
if (sep && rep > 1) {
|
||||
GCstr *s2 = lj_buf_cat2str(L, sep, s);
|
||||
lj_buf_reset(sb);
|
||||
lj_buf_putstr(sb, s);
|
||||
s = s2;
|
||||
rep--;
|
||||
}
|
||||
if (sep) {
|
||||
tlen = (int64_t)len + sep->len;
|
||||
if (tlen > LJ_MAX_STR)
|
||||
lj_err_caller(L, LJ_ERR_STROV);
|
||||
tlen *= k;
|
||||
if (tlen > LJ_MAX_STR)
|
||||
lj_err_caller(L, LJ_ERR_STROV);
|
||||
} else {
|
||||
tlen = (int64_t)k * len;
|
||||
if (tlen > LJ_MAX_STR)
|
||||
lj_err_caller(L, LJ_ERR_STROV);
|
||||
}
|
||||
if (tlen == 0) goto empty;
|
||||
buf = lj_str_needbuf(L, &g->tmpbuf, (MSize)tlen);
|
||||
src = strdata(s);
|
||||
if (sep) {
|
||||
tlen -= sep->len; /* Ignore trailing separator. */
|
||||
if (k > 1) { /* Paste one string and one separator. */
|
||||
int32_t i;
|
||||
i = 0; while (i < len) *buf++ = src[i++];
|
||||
src = strdata(sep); len = sep->len;
|
||||
i = 0; while (i < len) *buf++ = src[i++];
|
||||
src = g->tmpbuf.buf; len += s->len; k--; /* Now copy that k-1 times. */
|
||||
}
|
||||
}
|
||||
do {
|
||||
int32_t i = 0;
|
||||
do { *buf++ = src[i++]; } while (i < len);
|
||||
} while (--k > 0);
|
||||
setstrV(L, L->base-1, lj_str_new(L, g->tmpbuf.buf, (size_t)tlen));
|
||||
return FFH_RES(1);
|
||||
sb = lj_buf_putstr_rep(sb, s, rep);
|
||||
setstrV(L, L->top-1, lj_buf_str(L, sb));
|
||||
lj_gc_check(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LJLIB_ASM(string_reverse)
|
||||
LJLIB_ASM(string_reverse) LJLIB_REC(string_op IRCALL_lj_buf_putstr_reverse)
|
||||
{
|
||||
GCstr *s = lj_lib_checkstr(L, 1);
|
||||
lj_str_needbuf(L, &G(L)->tmpbuf, s->len);
|
||||
lj_lib_checkstr(L, 1);
|
||||
return FFH_RETRY;
|
||||
}
|
||||
LJLIB_ASM_(string_lower)
|
||||
LJLIB_ASM_(string_upper)
|
||||
LJLIB_ASM_(string_lower) LJLIB_REC(string_op IRCALL_lj_buf_putstr_lower)
|
||||
LJLIB_ASM_(string_upper) LJLIB_REC(string_op IRCALL_lj_buf_putstr_upper)
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
static int writer_buf(lua_State *L, const void *p, size_t size, void *b)
|
||||
static int writer_buf(lua_State *L, const void *p, size_t size, void *sb)
|
||||
{
|
||||
luaL_addlstring((luaL_Buffer *)b, (const char *)p, size);
|
||||
lj_buf_putmem((SBuf *)sb, p, (MSize)size);
|
||||
UNUSED(L);
|
||||
return 0;
|
||||
}
|
||||
|
@ -153,12 +124,12 @@ LJLIB_CF(string_dump)
|
|||
{
|
||||
GCfunc *fn = lj_lib_checkfunc(L, 1);
|
||||
int strip = L->base+1 < L->top && tvistruecond(L->base+1);
|
||||
luaL_Buffer b;
|
||||
SBuf *sb = lj_buf_tmp_(L); /* Assumes lj_bcwrite() doesn't use tmpbuf. */
|
||||
L->top = L->base+1;
|
||||
luaL_buffinit(L, &b);
|
||||
if (!isluafunc(fn) || lj_bcwrite(L, funcproto(fn), writer_buf, &b, strip))
|
||||
if (!isluafunc(fn) || lj_bcwrite(L, funcproto(fn), writer_buf, sb, strip))
|
||||
lj_err_caller(L, LJ_ERR_STRDUMP);
|
||||
luaL_pushresult(&b);
|
||||
setstrV(L, L->top-1, lj_buf_str(L, sb));
|
||||
lj_gc_check(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -183,7 +154,6 @@ typedef struct MatchState {
|
|||
} MatchState;
|
||||
|
||||
#define L_ESC '%'
|
||||
#define SPECIALS "^$*+?.([%-"
|
||||
|
||||
static int check_capture(MatchState *ms, int l)
|
||||
{
|
||||
|
@ -450,30 +420,6 @@ static const char *match(MatchState *ms, const char *s, const char *p)
|
|||
return s;
|
||||
}
|
||||
|
||||
static const char *lmemfind(const char *s1, size_t l1,
|
||||
const char *s2, size_t l2)
|
||||
{
|
||||
if (l2 == 0) {
|
||||
return s1; /* empty strings are everywhere */
|
||||
} else if (l2 > l1) {
|
||||
return NULL; /* avoids a negative `l1' */
|
||||
} else {
|
||||
const char *init; /* to search for a `*s2' inside `s1' */
|
||||
l2--; /* 1st char will be checked by `memchr' */
|
||||
l1 = l1-l2; /* `s2' cannot be found after that */
|
||||
while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
|
||||
init++; /* 1st char is already checked */
|
||||
if (memcmp(init, s2+1, l2) == 0) {
|
||||
return init-1;
|
||||
} else { /* correct `l1' and `s1' to try again */
|
||||
l1 -= (size_t)(init-s1);
|
||||
s1 = init;
|
||||
}
|
||||
}
|
||||
return NULL; /* not found */
|
||||
}
|
||||
}
|
||||
|
||||
static void push_onecapture(MatchState *ms, int i, const char *s, const char *e)
|
||||
{
|
||||
if (i >= ms->level) {
|
||||
|
@ -501,64 +447,60 @@ static int push_captures(MatchState *ms, const char *s, const char *e)
|
|||
return nlevels; /* number of strings pushed */
|
||||
}
|
||||
|
||||
static ptrdiff_t posrelat(ptrdiff_t pos, size_t len)
|
||||
{
|
||||
/* relative string position: negative means back from end */
|
||||
if (pos < 0) pos += (ptrdiff_t)len + 1;
|
||||
return (pos >= 0) ? pos : 0;
|
||||
}
|
||||
|
||||
static int str_find_aux(lua_State *L, int find)
|
||||
{
|
||||
size_t l1, l2;
|
||||
const char *s = luaL_checklstring(L, 1, &l1);
|
||||
const char *p = luaL_checklstring(L, 2, &l2);
|
||||
ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
|
||||
if (init < 0) {
|
||||
init = 0;
|
||||
} else if ((size_t)(init) > l1) {
|
||||
GCstr *s = lj_lib_checkstr(L, 1);
|
||||
GCstr *p = lj_lib_checkstr(L, 2);
|
||||
int32_t start = lj_lib_optint(L, 3, 1);
|
||||
MSize st;
|
||||
if (start < 0) start += (int32_t)s->len; else start--;
|
||||
if (start < 0) start = 0;
|
||||
st = (MSize)start;
|
||||
if (st > s->len) {
|
||||
#if LJ_52
|
||||
setnilV(L->top-1);
|
||||
return 1;
|
||||
#else
|
||||
init = (ptrdiff_t)l1;
|
||||
st = s->len;
|
||||
#endif
|
||||
}
|
||||
if (find && (lua_toboolean(L, 4) || /* explicit request? */
|
||||
strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */
|
||||
/* do a plain search */
|
||||
const char *s2 = lmemfind(s+init, l1-(size_t)init, p, l2);
|
||||
if (s2) {
|
||||
lua_pushinteger(L, s2-s+1);
|
||||
lua_pushinteger(L, s2-s+(ptrdiff_t)l2);
|
||||
if (find && ((L->base+3 < L->top && tvistruecond(L->base+3)) ||
|
||||
!lj_str_haspattern(p))) { /* Search for fixed string. */
|
||||
const char *q = lj_str_find(strdata(s)+st, strdata(p), s->len-st, p->len);
|
||||
if (q) {
|
||||
setintV(L->top-2, (int32_t)(q-strdata(s)) + 1);
|
||||
setintV(L->top-1, (int32_t)(q-strdata(s)) + (int32_t)p->len);
|
||||
return 2;
|
||||
}
|
||||
} else {
|
||||
} else { /* Search for pattern. */
|
||||
MatchState ms;
|
||||
int anchor = (*p == '^') ? (p++, 1) : 0;
|
||||
const char *s1=s+init;
|
||||
const char *pstr = strdata(p);
|
||||
const char *sstr = strdata(s) + st;
|
||||
int anchor = 0;
|
||||
if (*pstr == '^') { pstr++; anchor = 1; }
|
||||
ms.L = L;
|
||||
ms.src_init = s;
|
||||
ms.src_end = s+l1;
|
||||
do {
|
||||
const char *res;
|
||||
ms.src_init = strdata(s);
|
||||
ms.src_end = strdata(s) + s->len;
|
||||
do { /* Loop through string and try to match the pattern. */
|
||||
const char *q;
|
||||
ms.level = ms.depth = 0;
|
||||
if ((res=match(&ms, s1, p)) != NULL) {
|
||||
q = match(&ms, sstr, pstr);
|
||||
if (q) {
|
||||
if (find) {
|
||||
lua_pushinteger(L, s1-s+1); /* start */
|
||||
lua_pushinteger(L, res-s); /* end */
|
||||
return push_captures(&ms, NULL, 0) + 2;
|
||||
setintV(L->top++, (int32_t)(sstr-(strdata(s)-1)));
|
||||
setintV(L->top++, (int32_t)(q-strdata(s)));
|
||||
return push_captures(&ms, NULL, NULL) + 2;
|
||||
} else {
|
||||
return push_captures(&ms, s1, res);
|
||||
return push_captures(&ms, sstr, q);
|
||||
}
|
||||
}
|
||||
} while (s1++ < ms.src_end && !anchor);
|
||||
} while (sstr++ < ms.src_end && !anchor);
|
||||
}
|
||||
lua_pushnil(L); /* not found */
|
||||
setnilV(L->top-1); /* Not found. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
LJLIB_CF(string_find)
|
||||
LJLIB_CF(string_find) LJLIB_REC(.)
|
||||
{
|
||||
return str_find_aux(L, 1);
|
||||
}
|
||||
|
@ -698,221 +640,91 @@ LJLIB_CF(string_gsub)
|
|||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
|
||||
#define MAX_FMTITEM 512
|
||||
/* valid flags in a format specification */
|
||||
#define FMT_FLAGS "-+ #0"
|
||||
/*
|
||||
** maximum size of each format specification (such as '%-099.99d')
|
||||
** (+10 accounts for %99.99x plus margin of error)
|
||||
*/
|
||||
#define MAX_FMTSPEC (sizeof(FMT_FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
|
||||
|
||||
static void addquoted(lua_State *L, luaL_Buffer *b, int arg)
|
||||
{
|
||||
GCstr *str = lj_lib_checkstr(L, arg);
|
||||
int32_t len = (int32_t)str->len;
|
||||
const char *s = strdata(str);
|
||||
luaL_addchar(b, '"');
|
||||
while (len--) {
|
||||
uint32_t c = uchar(*s);
|
||||
if (c == '"' || c == '\\' || c == '\n') {
|
||||
luaL_addchar(b, '\\');
|
||||
} else if (lj_char_iscntrl(c)) { /* This can only be 0-31 or 127. */
|
||||
uint32_t d;
|
||||
luaL_addchar(b, '\\');
|
||||
if (c >= 100 || lj_char_isdigit(uchar(s[1]))) {
|
||||
luaL_addchar(b, '0'+(c >= 100)); if (c >= 100) c -= 100;
|
||||
goto tens;
|
||||
} else if (c >= 10) {
|
||||
tens:
|
||||
d = (c * 205) >> 11; c -= d * 10; luaL_addchar(b, '0'+d);
|
||||
}
|
||||
c += '0';
|
||||
}
|
||||
luaL_addchar(b, c);
|
||||
s++;
|
||||
}
|
||||
luaL_addchar(b, '"');
|
||||
}
|
||||
|
||||
static const char *scanformat(lua_State *L, const char *strfrmt, char *form)
|
||||
{
|
||||
const char *p = strfrmt;
|
||||
while (*p != '\0' && strchr(FMT_FLAGS, *p) != NULL) p++; /* skip flags */
|
||||
if ((size_t)(p - strfrmt) >= sizeof(FMT_FLAGS))
|
||||
lj_err_caller(L, LJ_ERR_STRFMTR);
|
||||
if (lj_char_isdigit(uchar(*p))) p++; /* skip width */
|
||||
if (lj_char_isdigit(uchar(*p))) p++; /* (2 digits at most) */
|
||||
if (*p == '.') {
|
||||
p++;
|
||||
if (lj_char_isdigit(uchar(*p))) p++; /* skip precision */
|
||||
if (lj_char_isdigit(uchar(*p))) p++; /* (2 digits at most) */
|
||||
}
|
||||
if (lj_char_isdigit(uchar(*p)))
|
||||
lj_err_caller(L, LJ_ERR_STRFMTW);
|
||||
*(form++) = '%';
|
||||
strncpy(form, strfrmt, (size_t)(p - strfrmt + 1));
|
||||
form += p - strfrmt + 1;
|
||||
*form = '\0';
|
||||
return p;
|
||||
}
|
||||
|
||||
static void addintlen(char *form)
|
||||
{
|
||||
size_t l = strlen(form);
|
||||
char spec = form[l - 1];
|
||||
strcpy(form + l - 1, LUA_INTFRMLEN);
|
||||
form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
|
||||
form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
|
||||
}
|
||||
|
||||
static unsigned LUA_INTFRM_T num2intfrm(lua_State *L, int arg)
|
||||
{
|
||||
if (sizeof(LUA_INTFRM_T) == 4) {
|
||||
return (LUA_INTFRM_T)lj_lib_checkbit(L, arg);
|
||||
} else {
|
||||
cTValue *o;
|
||||
lj_lib_checknumber(L, arg);
|
||||
o = L->base+arg-1;
|
||||
if (tvisint(o))
|
||||
return (LUA_INTFRM_T)intV(o);
|
||||
else
|
||||
return (LUA_INTFRM_T)numV(o);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned LUA_INTFRM_T num2uintfrm(lua_State *L, int arg)
|
||||
{
|
||||
if (sizeof(LUA_INTFRM_T) == 4) {
|
||||
return (unsigned LUA_INTFRM_T)lj_lib_checkbit(L, arg);
|
||||
} else {
|
||||
cTValue *o;
|
||||
lj_lib_checknumber(L, arg);
|
||||
o = L->base+arg-1;
|
||||
if (tvisint(o))
|
||||
return (unsigned LUA_INTFRM_T)intV(o);
|
||||
else if ((int32_t)o->u32.hi < 0)
|
||||
return (unsigned LUA_INTFRM_T)(LUA_INTFRM_T)numV(o);
|
||||
else
|
||||
return (unsigned LUA_INTFRM_T)numV(o);
|
||||
}
|
||||
}
|
||||
|
||||
static GCstr *meta_tostring(lua_State *L, int arg)
|
||||
/* Emulate tostring() inline. */
|
||||
static GCstr *string_fmt_tostring(lua_State *L, int arg, int retry)
|
||||
{
|
||||
TValue *o = L->base+arg-1;
|
||||
cTValue *mo;
|
||||
lua_assert(o < L->top); /* Caller already checks for existence. */
|
||||
if (LJ_LIKELY(tvisstr(o)))
|
||||
return strV(o);
|
||||
if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
|
||||
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);
|
||||
L->top--;
|
||||
if (tvisstr(L->top))
|
||||
return strV(L->top);
|
||||
o = L->base+arg-1;
|
||||
copyTV(L, o, L->top);
|
||||
}
|
||||
if (tvisnumber(o)) {
|
||||
return lj_str_fromnumber(L, o);
|
||||
} else if (tvisnil(o)) {
|
||||
return lj_str_newlit(L, "nil");
|
||||
} else if (tvisfalse(o)) {
|
||||
return lj_str_newlit(L, "false");
|
||||
} else if (tvistrue(o)) {
|
||||
return lj_str_newlit(L, "true");
|
||||
} else {
|
||||
if (tvisfunc(o) && isffunc(funcV(o)))
|
||||
lj_str_pushf(L, "function: builtin#%d", funcV(o)->c.ffid);
|
||||
else
|
||||
lj_str_pushf(L, "%s: %p", lj_typename(o), lua_topointer(L, arg));
|
||||
L->top--;
|
||||
return strV(L->top);
|
||||
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_CF(string_format) LJLIB_REC(.)
|
||||
{
|
||||
int arg = 1, top = (int)(L->top - L->base);
|
||||
GCstr *fmt = lj_lib_checkstr(L, arg);
|
||||
const char *strfrmt = strdata(fmt);
|
||||
const char *strfrmt_end = strfrmt + fmt->len;
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
while (strfrmt < strfrmt_end) {
|
||||
if (*strfrmt != L_ESC) {
|
||||
luaL_addchar(&b, *strfrmt++);
|
||||
} else if (*++strfrmt == L_ESC) {
|
||||
luaL_addchar(&b, *strfrmt++); /* %% */
|
||||
} else { /* format item */
|
||||
char form[MAX_FMTSPEC]; /* to store the format (`%...') */
|
||||
char buff[MAX_FMTITEM]; /* to store the formatted item */
|
||||
int arg, top = (int)(L->top - L->base);
|
||||
GCstr *fmt;
|
||||
SBuf *sb;
|
||||
FormatState fs;
|
||||
SFormat sf;
|
||||
int retry = 0;
|
||||
again:
|
||||
arg = 1;
|
||||
sb = lj_buf_tmp_(L);
|
||||
fmt = lj_lib_checkstr(L, arg);
|
||||
lj_strfmt_init(&fs, strdata(fmt), fmt->len);
|
||||
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]);
|
||||
strfrmt = scanformat(L, strfrmt, form);
|
||||
switch (*strfrmt++) {
|
||||
case 'c':
|
||||
sprintf(buff, form, lj_lib_checkint(L, arg));
|
||||
break;
|
||||
case 'd': case 'i':
|
||||
addintlen(form);
|
||||
sprintf(buff, form, num2intfrm(L, arg));
|
||||
break;
|
||||
case 'o': case 'u': case 'x': case 'X':
|
||||
addintlen(form);
|
||||
sprintf(buff, form, num2uintfrm(L, arg));
|
||||
break;
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G': case 'a': case 'A': {
|
||||
TValue tv;
|
||||
tv.n = lj_lib_checknum(L, arg);
|
||||
if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) {
|
||||
/* Canonicalize output of non-finite values. */
|
||||
char *p, nbuf[LJ_STR_NUMBUF];
|
||||
size_t len = lj_str_bufnum(nbuf, &tv);
|
||||
if (strfrmt[-1] < 'a') {
|
||||
nbuf[len-3] = nbuf[len-3] - 0x20;
|
||||
nbuf[len-2] = nbuf[len-2] - 0x20;
|
||||
nbuf[len-1] = nbuf[len-1] - 0x20;
|
||||
}
|
||||
nbuf[len] = '\0';
|
||||
for (p = form; *p < 'A' && *p != '.'; p++) ;
|
||||
*p++ = 's'; *p = '\0';
|
||||
sprintf(buff, form, nbuf);
|
||||
break;
|
||||
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));
|
||||
}
|
||||
sprintf(buff, form, (double)tv.n);
|
||||
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 'q':
|
||||
addquoted(L, &b, arg);
|
||||
continue;
|
||||
case 'p':
|
||||
lj_str_pushf(L, "%p", lua_topointer(L, arg));
|
||||
luaL_addvalue(&b);
|
||||
continue;
|
||||
case 's': {
|
||||
GCstr *str = meta_tostring(L, arg);
|
||||
if (!strchr(form, '.') && str->len >= 100) {
|
||||
/* no precision and string is too long to be formatted;
|
||||
keep original string */
|
||||
setstrV(L, L->top++, str);
|
||||
luaL_addvalue(&b);
|
||||
continue;
|
||||
}
|
||||
sprintf(buff, form, strdata(str));
|
||||
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(L->base+arg-1));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
lj_err_callerv(L, LJ_ERR_STRFMTO, *(strfrmt -1));
|
||||
lua_assert(0);
|
||||
break;
|
||||
}
|
||||
luaL_addlstring(&b, buff, strlen(buff));
|
||||
}
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
if (retry++ == 1) goto again;
|
||||
setstrV(L, L->top-1, lj_buf_str(L, sb));
|
||||
lj_gc_check(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -925,10 +737,6 @@ LUALIB_API int luaopen_string(lua_State *L)
|
|||
GCtab *mt;
|
||||
global_State *g;
|
||||
LJ_LIB_REG(L, LUA_STRLIBNAME, string);
|
||||
#if defined(LUA_COMPAT_GFIND) && !LJ_52
|
||||
lua_getfield(L, -1, "gmatch");
|
||||
lua_setfield(L, -2, "gfind");
|
||||
#endif
|
||||
mt = lj_tab_new(L, 0, 1);
|
||||
/* NOBARRIER: basemt is a GC root. */
|
||||
g = G(L);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Table library.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
|
@ -16,57 +16,43 @@
|
|||
#include "lj_obj.h"
|
||||
#include "lj_gc.h"
|
||||
#include "lj_err.h"
|
||||
#include "lj_buf.h"
|
||||
#include "lj_tab.h"
|
||||
#include "lj_ff.h"
|
||||
#include "lj_lib.h"
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#define LJLIB_MODULE_table
|
||||
|
||||
LJLIB_CF(table_foreachi)
|
||||
{
|
||||
GCtab *t = lj_lib_checktab(L, 1);
|
||||
GCfunc *func = lj_lib_checkfunc(L, 2);
|
||||
MSize i, n = lj_tab_len(t);
|
||||
for (i = 1; i <= n; i++) {
|
||||
cTValue *val;
|
||||
setfuncV(L, L->top, func);
|
||||
setintV(L->top+1, i);
|
||||
val = lj_tab_getint(t, (int32_t)i);
|
||||
if (val) { copyTV(L, L->top+2, val); } else { setnilV(L->top+2); }
|
||||
L->top += 3;
|
||||
lua_call(L, 2, 1);
|
||||
if (!tvisnil(L->top-1))
|
||||
return 1;
|
||||
L->top--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
LJLIB_LUA(table_foreachi) /*
|
||||
function(t, f)
|
||||
CHECK_tab(t)
|
||||
CHECK_func(f)
|
||||
for i=1,#t do
|
||||
local r = f(i, t[i])
|
||||
if r ~= nil then return r end
|
||||
end
|
||||
end
|
||||
*/
|
||||
|
||||
LJLIB_CF(table_foreach)
|
||||
{
|
||||
GCtab *t = lj_lib_checktab(L, 1);
|
||||
GCfunc *func = lj_lib_checkfunc(L, 2);
|
||||
L->top = L->base+3;
|
||||
setnilV(L->top-1);
|
||||
while (lj_tab_next(L, t, L->top-1)) {
|
||||
copyTV(L, L->top+2, L->top);
|
||||
copyTV(L, L->top+1, L->top-1);
|
||||
setfuncV(L, L->top, func);
|
||||
L->top += 3;
|
||||
lua_call(L, 2, 1);
|
||||
if (!tvisnil(L->top-1))
|
||||
return 1;
|
||||
L->top--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
LJLIB_LUA(table_foreach) /*
|
||||
function(t, f)
|
||||
CHECK_tab(t)
|
||||
CHECK_func(f)
|
||||
for k, v in PAIRS(t) do
|
||||
local r = f(k, v)
|
||||
if r ~= nil then return r end
|
||||
end
|
||||
end
|
||||
*/
|
||||
|
||||
LJLIB_ASM(table_getn) LJLIB_REC(.)
|
||||
{
|
||||
lj_lib_checktab(L, 1);
|
||||
return FFH_UNREACHABLE;
|
||||
}
|
||||
LJLIB_LUA(table_getn) /*
|
||||
function(t)
|
||||
CHECK_tab(t)
|
||||
return #t
|
||||
end
|
||||
*/
|
||||
|
||||
LJLIB_CF(table_maxn)
|
||||
{
|
||||
|
@ -119,52 +105,67 @@ LJLIB_CF(table_insert) LJLIB_REC(.)
|
|||
return 0;
|
||||
}
|
||||
|
||||
LJLIB_CF(table_remove) LJLIB_REC(.)
|
||||
{
|
||||
GCtab *t = lj_lib_checktab(L, 1);
|
||||
int32_t e = (int32_t)lj_tab_len(t);
|
||||
int32_t pos = lj_lib_optint(L, 2, e);
|
||||
if (!(1 <= pos && pos <= e)) /* Nothing to remove? */
|
||||
return 0;
|
||||
lua_rawgeti(L, 1, pos); /* Get previous value. */
|
||||
/* NOBARRIER: This just moves existing elements around. */
|
||||
for (; pos < e; pos++) {
|
||||
cTValue *src = lj_tab_getint(t, pos+1);
|
||||
TValue *dst = lj_tab_setint(L, t, pos);
|
||||
if (src) {
|
||||
copyTV(L, dst, src);
|
||||
} else {
|
||||
setnilV(dst);
|
||||
}
|
||||
}
|
||||
setnilV(lj_tab_setint(L, t, e)); /* Remove (last) value. */
|
||||
return 1; /* Return previous value. */
|
||||
}
|
||||
LJLIB_LUA(table_remove) /*
|
||||
function(t, pos)
|
||||
CHECK_tab(t)
|
||||
local len = #t
|
||||
if pos == nil then
|
||||
if len ~= 0 then
|
||||
local old = t[len]
|
||||
t[len] = nil
|
||||
return old
|
||||
end
|
||||
else
|
||||
CHECK_int(pos)
|
||||
if pos >= 1 and pos <= len then
|
||||
local old = t[pos]
|
||||
for i=pos+1,len do
|
||||
t[i-1] = t[i]
|
||||
end
|
||||
t[len] = nil
|
||||
return old
|
||||
end
|
||||
end
|
||||
end
|
||||
*/
|
||||
|
||||
LJLIB_CF(table_concat)
|
||||
LJLIB_LUA(table_move) /*
|
||||
function(a1, f, e, t, a2)
|
||||
CHECK_tab(a1)
|
||||
CHECK_int(f)
|
||||
CHECK_int(e)
|
||||
CHECK_int(t)
|
||||
if a2 == nil then a2 = a1 end
|
||||
CHECK_tab(a2)
|
||||
if e >= f then
|
||||
local d = t - f
|
||||
if t > e or t <= f or a2 ~= a1 then
|
||||
for i=f,e do a2[i+d] = a1[i] end
|
||||
else
|
||||
for i=e,f,-1 do a2[i+d] = a1[i] end
|
||||
end
|
||||
end
|
||||
return a2
|
||||
end
|
||||
*/
|
||||
|
||||
LJLIB_CF(table_concat) LJLIB_REC(.)
|
||||
{
|
||||
luaL_Buffer b;
|
||||
GCtab *t = lj_lib_checktab(L, 1);
|
||||
GCstr *sep = lj_lib_optstr(L, 2);
|
||||
MSize seplen = sep ? sep->len : 0;
|
||||
int32_t i = lj_lib_optint(L, 3, 1);
|
||||
int32_t e = (L->base+3 < L->top && !tvisnil(L->base+3)) ?
|
||||
lj_lib_checkint(L, 4) : (int32_t)lj_tab_len(t);
|
||||
luaL_buffinit(L, &b);
|
||||
if (i <= e) {
|
||||
for (;;) {
|
||||
cTValue *o;
|
||||
lua_rawgeti(L, 1, i);
|
||||
o = L->top-1;
|
||||
if (!(tvisstr(o) || tvisnumber(o)))
|
||||
lj_err_callerv(L, LJ_ERR_TABCAT, lj_typename(o), i);
|
||||
luaL_addvalue(&b);
|
||||
if (i++ == e) break;
|
||||
if (seplen)
|
||||
luaL_addlstring(&b, strdata(sep), seplen);
|
||||
}
|
||||
SBuf *sb = lj_buf_tmp_(L);
|
||||
SBuf *sbx = lj_buf_puttab(sb, t, sep, i, e);
|
||||
if (LJ_UNLIKELY(!sbx)) { /* Error: bad element type. */
|
||||
int32_t idx = (int32_t)(intptr_t)sbufP(sb);
|
||||
cTValue *o = lj_tab_getint(t, idx);
|
||||
lj_err_callerv(L, LJ_ERR_TABCAT,
|
||||
lj_obj_itypename[o ? itypemap(o) : ~LJ_TNIL], idx);
|
||||
}
|
||||
luaL_pushresult(&b);
|
||||
setstrV(L, L->top-1, lj_buf_str(L, sbx));
|
||||
lj_gc_check(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -284,6 +285,30 @@ LJLIB_CF(table_pack)
|
|||
}
|
||||
#endif
|
||||
|
||||
LJLIB_NOREG LJLIB_CF(table_new) LJLIB_REC(.)
|
||||
{
|
||||
int32_t a = lj_lib_checkint(L, 1);
|
||||
int32_t h = lj_lib_checkint(L, 2);
|
||||
lua_createtable(L, a, h);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LJLIB_NOREG LJLIB_CF(table_clear) LJLIB_REC(.)
|
||||
{
|
||||
lj_tab_clear(lj_lib_checktab(L, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int luaopen_table_new(lua_State *L)
|
||||
{
|
||||
return lj_lib_postreg(L, lj_cf_table_new, FF_table_new, "new");
|
||||
}
|
||||
|
||||
static int luaopen_table_clear(lua_State *L)
|
||||
{
|
||||
return lj_lib_postreg(L, lj_cf_table_clear, FF_table_clear, "clear");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
#include "lj_libdef.h"
|
||||
|
@ -295,6 +320,8 @@ LUALIB_API int luaopen_table(lua_State *L)
|
|||
lua_getglobal(L, "unpack");
|
||||
lua_setfield(L, -2, "unpack");
|
||||
#endif
|
||||
lj_lib_prereg(L, LUA_TABLIBNAME ".new", luaopen_table_new, tabV(L->top-1));
|
||||
lj_lib_prereg(L, LUA_TABLIBNAME ".clear", luaopen_table_clear, tabV(L->top-1));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,3 +24,18 @@
|
|||
Memcheck:Cond
|
||||
fun:lj_str_new
|
||||
}
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Addr4
|
||||
fun:str_fastcmp
|
||||
}
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Addr1
|
||||
fun:str_fastcmp
|
||||
}
|
||||
{
|
||||
Optimized string compare
|
||||
Memcheck:Cond
|
||||
fun:str_fastcmp
|
||||
}
|
||||
|
|
|
@ -72,13 +72,56 @@
|
|||
|
||||
#define IS_DIRECT_BIT (SIZE_T_ONE)
|
||||
|
||||
|
||||
/* Determine system-specific block allocation method. */
|
||||
#if LJ_TARGET_WINDOWS
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#define LJ_ALLOC_VIRTUALALLOC 1
|
||||
|
||||
#if LJ_64 && !LJ_GC64
|
||||
#define LJ_ALLOC_NTAVM 1
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#include <errno.h>
|
||||
/* If this include fails, then rebuild with: -DLUAJIT_USE_SYSMALLOC */
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define LJ_ALLOC_MMAP 1
|
||||
|
||||
#if LJ_64
|
||||
|
||||
#define LJ_ALLOC_MMAP_PROBE 1
|
||||
|
||||
#if LJ_GC64
|
||||
#define LJ_ALLOC_MBITS 47 /* 128 TB in LJ_GC64 mode. */
|
||||
#elif LJ_TARGET_X64 && LJ_HASJIT
|
||||
/* Due to limitations in the x64 compiler backend. */
|
||||
#define LJ_ALLOC_MBITS 31 /* 2 GB on x64 with !LJ_GC64. */
|
||||
#else
|
||||
#define LJ_ALLOC_MBITS 32 /* 4 GB on other archs with !LJ_GC64. */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if LJ_64 && !LJ_GC64 && defined(MAP_32BIT)
|
||||
#define LJ_ALLOC_MMAP32 1
|
||||
#endif
|
||||
|
||||
#if LJ_TARGET_LINUX
|
||||
#define LJ_ALLOC_MREMAP 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if LJ_ALLOC_VIRTUALALLOC
|
||||
|
||||
#if LJ_ALLOC_NTAVM
|
||||
/* Undocumented, but hey, that's what we all love so much about Windows. */
|
||||
typedef long (*PNTAVM)(HANDLE handle, void **addr, ULONG zbits,
|
||||
size_t *size, ULONG alloctype, ULONG prot);
|
||||
|
@ -89,14 +132,15 @@ static PNTAVM ntavm;
|
|||
*/
|
||||
#define NTAVM_ZEROBITS 1
|
||||
|
||||
static void INIT_MMAP(void)
|
||||
static void init_mmap(void)
|
||||
{
|
||||
ntavm = (PNTAVM)GetProcAddress(GetModuleHandleA("ntdll.dll"),
|
||||
"NtAllocateVirtualMemory");
|
||||
}
|
||||
#define INIT_MMAP() init_mmap()
|
||||
|
||||
/* Win64 32 bit MMAP via NtAllocateVirtualMemory. */
|
||||
static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
static void *CALL_MMAP(size_t size)
|
||||
{
|
||||
DWORD olderr = GetLastError();
|
||||
void *ptr = NULL;
|
||||
|
@ -107,7 +151,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
|
|||
}
|
||||
|
||||
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
|
||||
static LJ_AINLINE void *DIRECT_MMAP(size_t size)
|
||||
static void *DIRECT_MMAP(size_t size)
|
||||
{
|
||||
DWORD olderr = GetLastError();
|
||||
void *ptr = NULL;
|
||||
|
@ -119,10 +163,8 @@ static LJ_AINLINE void *DIRECT_MMAP(size_t size)
|
|||
|
||||
#else
|
||||
|
||||
#define INIT_MMAP() ((void)0)
|
||||
|
||||
/* Win32 MMAP via VirtualAlloc */
|
||||
static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
static void *CALL_MMAP(size_t size)
|
||||
{
|
||||
DWORD olderr = GetLastError();
|
||||
void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
||||
|
@ -131,7 +173,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
|
|||
}
|
||||
|
||||
/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
|
||||
static LJ_AINLINE void *DIRECT_MMAP(size_t size)
|
||||
static void *DIRECT_MMAP(size_t size)
|
||||
{
|
||||
DWORD olderr = GetLastError();
|
||||
void *ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
|
||||
|
@ -143,7 +185,7 @@ static LJ_AINLINE void *DIRECT_MMAP(size_t size)
|
|||
#endif
|
||||
|
||||
/* This function supports releasing coalesed segments */
|
||||
static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
|
||||
static int CALL_MUNMAP(void *ptr, size_t size)
|
||||
{
|
||||
DWORD olderr = GetLastError();
|
||||
MEMORY_BASIC_INFORMATION minfo;
|
||||
|
@ -163,10 +205,7 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#elif LJ_ALLOC_MMAP
|
||||
|
||||
#define MMAP_PROT (PROT_READ|PROT_WRITE)
|
||||
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
|
||||
|
@ -174,105 +213,151 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
|
|||
#endif
|
||||
#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
|
||||
|
||||
#if LJ_64
|
||||
/* 64 bit mode needs special support for allocating memory in the lower 2GB. */
|
||||
#if LJ_ALLOC_MMAP_PROBE
|
||||
|
||||
#if defined(MAP_32BIT)
|
||||
|
||||
#if defined(__sun__)
|
||||
#define MMAP_REGION_START ((uintptr_t)0x1000)
|
||||
#ifdef MAP_TRYFIXED
|
||||
#define MMAP_FLAGS_PROBE (MMAP_FLAGS|MAP_TRYFIXED)
|
||||
#else
|
||||
/* Actually this only gives us max. 1GB in current Linux kernels. */
|
||||
#define MMAP_REGION_START ((uintptr_t)0)
|
||||
#define MMAP_FLAGS_PROBE MMAP_FLAGS
|
||||
#endif
|
||||
|
||||
static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
#define LJ_ALLOC_MMAP_PROBE_MAX 30
|
||||
#define LJ_ALLOC_MMAP_PROBE_LINEAR 5
|
||||
|
||||
#define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000)
|
||||
|
||||
/* No point in a giant ifdef mess. Just try to open /dev/urandom.
|
||||
** It doesn't really matter if this fails, since we get some ASLR bits from
|
||||
** every unsuitable allocation, too. And we prefer linear allocation, anyway.
|
||||
*/
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static uintptr_t mmap_probe_seed(void)
|
||||
{
|
||||
int olderr = errno;
|
||||
void *ptr = mmap((void *)MMAP_REGION_START, size, MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0);
|
||||
errno = olderr;
|
||||
return ptr;
|
||||
uintptr_t val;
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd != -1) {
|
||||
int ok = ((size_t)read(fd, &val, sizeof(val)) == sizeof(val));
|
||||
(void)close(fd);
|
||||
if (ok) return val;
|
||||
}
|
||||
return 1; /* Punt. */
|
||||
}
|
||||
|
||||
#elif LJ_TARGET_OSX || LJ_TARGET_PS4 || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun__)
|
||||
|
||||
/* OSX and FreeBSD mmap() use a naive first-fit linear search.
|
||||
** That's perfect for us. Except that -pagezero_size must be set for OSX,
|
||||
** otherwise the lower 4GB are blocked. And the 32GB RLIMIT_DATA needs
|
||||
** to be reduced to 250MB on FreeBSD.
|
||||
*/
|
||||
#if LJ_TARGET_OSX || defined(__DragonFly__)
|
||||
#define MMAP_REGION_START ((uintptr_t)0x10000)
|
||||
#elif LJ_TARGET_PS4
|
||||
#define MMAP_REGION_START ((uintptr_t)0x4000)
|
||||
#else
|
||||
#define MMAP_REGION_START ((uintptr_t)0x10000000)
|
||||
#endif
|
||||
#define MMAP_REGION_END ((uintptr_t)0x80000000)
|
||||
|
||||
#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
static void *mmap_probe(size_t size)
|
||||
{
|
||||
int olderr = errno;
|
||||
/* Hint for next allocation. Doesn't need to be thread-safe. */
|
||||
static uintptr_t alloc_hint = MMAP_REGION_START;
|
||||
int retry = 0;
|
||||
#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
|
||||
static int rlimit_modified = 0;
|
||||
if (LJ_UNLIKELY(rlimit_modified == 0)) {
|
||||
struct rlimit rlim;
|
||||
rlim.rlim_cur = rlim.rlim_max = MMAP_REGION_START;
|
||||
setrlimit(RLIMIT_DATA, &rlim); /* Ignore result. May fail below. */
|
||||
rlimit_modified = 1;
|
||||
}
|
||||
#endif
|
||||
for (;;) {
|
||||
void *p = mmap((void *)alloc_hint, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
|
||||
if ((uintptr_t)p >= MMAP_REGION_START &&
|
||||
(uintptr_t)p + size < MMAP_REGION_END) {
|
||||
alloc_hint = (uintptr_t)p + size;
|
||||
static uintptr_t hint_addr = 0;
|
||||
static uintptr_t hint_prng = 0;
|
||||
int olderr = errno;
|
||||
int retry;
|
||||
for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) {
|
||||
void *p = mmap((void *)hint_addr, size, MMAP_PROT, MMAP_FLAGS_PROBE, -1, 0);
|
||||
uintptr_t addr = (uintptr_t)p;
|
||||
if ((addr >> LJ_ALLOC_MBITS) == 0 && addr >= LJ_ALLOC_MMAP_PROBE_LOWER) {
|
||||
/* We got a suitable address. Bump the hint address. */
|
||||
hint_addr = addr + size;
|
||||
errno = olderr;
|
||||
return p;
|
||||
}
|
||||
if (p != CMFAIL) munmap(p, size);
|
||||
#if defined(__sun__) || defined(__DragonFly__)
|
||||
alloc_hint += 0x1000000; /* Need near-exhaustive linear scan. */
|
||||
if (alloc_hint + size < MMAP_REGION_END) continue;
|
||||
#endif
|
||||
if (retry) break;
|
||||
retry = 1;
|
||||
alloc_hint = MMAP_REGION_START;
|
||||
if (p != MFAIL) {
|
||||
munmap(p, size);
|
||||
} else if (errno == ENOMEM) {
|
||||
return MFAIL;
|
||||
}
|
||||
if (hint_addr) {
|
||||
/* First, try linear probing. */
|
||||
if (retry < LJ_ALLOC_MMAP_PROBE_LINEAR) {
|
||||
hint_addr += 0x1000000;
|
||||
if (((hint_addr + size) >> LJ_ALLOC_MBITS) != 0)
|
||||
hint_addr = 0;
|
||||
continue;
|
||||
} else if (retry == LJ_ALLOC_MMAP_PROBE_LINEAR) {
|
||||
/* Next, try a no-hint probe to get back an ASLR address. */
|
||||
hint_addr = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* Finally, try pseudo-random probing. */
|
||||
if (LJ_UNLIKELY(hint_prng == 0)) {
|
||||
hint_prng = mmap_probe_seed();
|
||||
}
|
||||
/* The unsuitable address we got has some ASLR PRNG bits. */
|
||||
hint_addr ^= addr & ~((uintptr_t)(LJ_PAGESIZE-1));
|
||||
do { /* The PRNG itself is very weak, but see above. */
|
||||
hint_prng = hint_prng * 1103515245 + 12345;
|
||||
hint_addr ^= hint_prng * (uintptr_t)LJ_PAGESIZE;
|
||||
hint_addr &= (((uintptr_t)1 << LJ_ALLOC_MBITS)-1);
|
||||
} while (hint_addr < LJ_ALLOC_MMAP_PROBE_LOWER);
|
||||
}
|
||||
errno = olderr;
|
||||
return CMFAIL;
|
||||
return MFAIL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error "NYI: need an equivalent of MAP_32BIT for this 64 bit OS"
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if LJ_ALLOC_MMAP32
|
||||
|
||||
/* 32 bit mode is easy. */
|
||||
static LJ_AINLINE void *CALL_MMAP(size_t size)
|
||||
#if defined(__sun__)
|
||||
#define LJ_ALLOC_MMAP32_START ((uintptr_t)0x1000)
|
||||
#else
|
||||
#define LJ_ALLOC_MMAP32_START ((uintptr_t)0)
|
||||
#endif
|
||||
|
||||
static void *mmap_map32(size_t size)
|
||||
{
|
||||
#if LJ_ALLOC_MMAP_PROBE
|
||||
static int fallback = 0;
|
||||
if (fallback)
|
||||
return mmap_probe(size);
|
||||
#endif
|
||||
{
|
||||
int olderr = errno;
|
||||
void *ptr = mmap((void *)LJ_ALLOC_MMAP32_START, size, MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0);
|
||||
errno = olderr;
|
||||
/* This only allows 1GB on Linux. So fallback to probing to get 2GB. */
|
||||
#if LJ_ALLOC_MMAP_PROBE
|
||||
if (ptr == MFAIL) {
|
||||
fallback = 1;
|
||||
return mmap_probe(size);
|
||||
}
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if LJ_ALLOC_MMAP32
|
||||
#define CALL_MMAP(size) mmap_map32(size)
|
||||
#elif LJ_ALLOC_MMAP_PROBE
|
||||
#define CALL_MMAP(size) mmap_probe(size)
|
||||
#else
|
||||
static void *CALL_MMAP(size_t size)
|
||||
{
|
||||
int olderr = errno;
|
||||
void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
|
||||
errno = olderr;
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
|
||||
|
||||
#include <sys/resource.h>
|
||||
|
||||
static void init_mmap(void)
|
||||
{
|
||||
struct rlimit rlim;
|
||||
rlim.rlim_cur = rlim.rlim_max = 0x10000;
|
||||
setrlimit(RLIMIT_DATA, &rlim); /* Ignore result. May fail later. */
|
||||
}
|
||||
#define INIT_MMAP() init_mmap()
|
||||
|
||||
#endif
|
||||
|
||||
#define INIT_MMAP() ((void)0)
|
||||
#define DIRECT_MMAP(s) CALL_MMAP(s)
|
||||
|
||||
static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
|
||||
static int CALL_MUNMAP(void *ptr, size_t size)
|
||||
{
|
||||
int olderr = errno;
|
||||
int ret = munmap(ptr, size);
|
||||
|
@ -280,10 +365,9 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#if LJ_TARGET_LINUX
|
||||
#if LJ_ALLOC_MREMAP
|
||||
/* Need to define _GNU_SOURCE to get the mremap prototype. */
|
||||
static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz,
|
||||
int flags)
|
||||
static void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, int flags)
|
||||
{
|
||||
int olderr = errno;
|
||||
ptr = mremap(ptr, osz, nsz, flags);
|
||||
|
@ -294,7 +378,7 @@ static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz,
|
|||
#define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv))
|
||||
#define CALL_MREMAP_NOMOVE 0
|
||||
#define CALL_MREMAP_MAYMOVE 1
|
||||
#if LJ_64
|
||||
#if LJ_64 && !LJ_GC64
|
||||
#define CALL_MREMAP_MV CALL_MREMAP_NOMOVE
|
||||
#else
|
||||
#define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE
|
||||
|
@ -303,6 +387,15 @@ static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz,
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef INIT_MMAP
|
||||
#define INIT_MMAP() ((void)0)
|
||||
#endif
|
||||
|
||||
#ifndef DIRECT_MMAP
|
||||
#define DIRECT_MMAP(s) CALL_MMAP(s)
|
||||
#endif
|
||||
|
||||
#ifndef CALL_MREMAP
|
||||
#define CALL_MREMAP(addr, osz, nsz, mv) ((void)osz, MFAIL)
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Public Lua/C API.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
**
|
||||
** Major portions taken verbatim or adapted from the Lua interpreter.
|
||||
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
|
||||
|
@ -24,6 +24,7 @@
|
|||
#include "lj_trace.h"
|
||||
#include "lj_vm.h"
|
||||
#include "lj_strscan.h"
|
||||
#include "lj_strfmt.h"
|
||||
|
||||
/* -- Common helper functions --------------------------------------------- */
|
||||
|
||||
|
@ -111,6 +112,13 @@ LUA_API void lua_xmove(lua_State *from, lua_State *to, int n)
|
|||
from->top = f;
|
||||
}
|
||||
|
||||
LUA_API const lua_Number *lua_version(lua_State *L)
|
||||
{
|
||||
static const lua_Number version = LUA_VERSION_NUM;
|
||||
UNUSED(L);
|
||||
return &version;
|
||||
}
|
||||
|
||||
/* -- Stack manipulation -------------------------------------------------- */
|
||||
|
||||
LUA_API int lua_gettop(lua_State *L)
|
||||
|
@ -151,30 +159,40 @@ LUA_API void lua_insert(lua_State *L, int idx)
|
|||
copyTV(L, p, L->top);
|
||||
}
|
||||
|
||||
LUA_API void lua_replace(lua_State *L, int idx)
|
||||
static void copy_slot(lua_State *L, TValue *f, int idx)
|
||||
{
|
||||
api_checknelems(L, 1);
|
||||
if (idx == LUA_GLOBALSINDEX) {
|
||||
api_check(L, tvistab(L->top-1));
|
||||
api_check(L, tvistab(f));
|
||||
/* NOBARRIER: A thread (i.e. L) is never black. */
|
||||
setgcref(L->env, obj2gco(tabV(L->top-1)));
|
||||
setgcref(L->env, obj2gco(tabV(f)));
|
||||
} else if (idx == LUA_ENVIRONINDEX) {
|
||||
GCfunc *fn = curr_func(L);
|
||||
if (fn->c.gct != ~LJ_TFUNC)
|
||||
lj_err_msg(L, LJ_ERR_NOENV);
|
||||
api_check(L, tvistab(L->top-1));
|
||||
setgcref(fn->c.env, obj2gco(tabV(L->top-1)));
|
||||
lj_gc_barrier(L, fn, L->top-1);
|
||||
api_check(L, tvistab(f));
|
||||
setgcref(fn->c.env, obj2gco(tabV(f)));
|
||||
lj_gc_barrier(L, fn, f);
|
||||
} else {
|
||||
TValue *o = index2adr(L, idx);
|
||||
api_checkvalidindex(L, o);
|
||||
copyTV(L, o, L->top-1);
|
||||
copyTV(L, o, f);
|
||||
if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */
|
||||
lj_gc_barrier(L, curr_func(L), L->top-1);
|
||||
lj_gc_barrier(L, curr_func(L), f);
|
||||
}
|
||||
}
|
||||
|
||||
LUA_API void lua_replace(lua_State *L, int idx)
|
||||
{
|
||||
api_checknelems(L, 1);
|
||||
copy_slot(L, L->top - 1, idx);
|
||||
L->top--;
|
||||
}
|
||||
|
||||
LUA_API void lua_copy(lua_State *L, int fromidx, int toidx)
|
||||
{
|
||||
copy_slot(L, index2adr(L, fromidx), toidx);
|
||||
}
|
||||
|
||||
LUA_API void lua_pushvalue(lua_State *L, int idx)
|
||||
{
|
||||
copyTV(L, L->top, index2adr(L, idx));
|
||||
|
@ -188,7 +206,7 @@ LUA_API int lua_type(lua_State *L, int idx)
|
|||
cTValue *o = index2adr(L, idx);
|
||||
if (tvisnumber(o)) {
|
||||
return LUA_TNUMBER;
|
||||
#if LJ_64
|
||||
#if LJ_64 && !LJ_GC64
|
||||
} else if (tvislightud(o)) {
|
||||
return LUA_TLIGHTUSERDATA;
|
||||
#endif
|
||||
|
@ -268,7 +286,7 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2)
|
|||
return 0;
|
||||
} else if (tvispri(o1)) {
|
||||
return o1 != niltv(L) && o2 != niltv(L);
|
||||
#if LJ_64
|
||||
#if LJ_64 && !LJ_GC64
|
||||
} else if (tvislightud(o1)) {
|
||||
return o1->u64 == o2->u64;
|
||||
#endif
|
||||
|
@ -283,8 +301,8 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2)
|
|||
} else {
|
||||
L->top = base+2;
|
||||
lj_vm_call(L, base, 1+1);
|
||||
L->top -= 2;
|
||||
return tvistruecond(L->top+1);
|
||||
L->top -= 2+LJ_FR2;
|
||||
return tvistruecond(L->top+1+LJ_FR2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -306,8 +324,8 @@ LUA_API int lua_lessthan(lua_State *L, int idx1, int idx2)
|
|||
} else {
|
||||
L->top = base+2;
|
||||
lj_vm_call(L, base, 1+1);
|
||||
L->top -= 2;
|
||||
return tvistruecond(L->top+1);
|
||||
L->top -= 2+LJ_FR2;
|
||||
return tvistruecond(L->top+1+LJ_FR2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -324,6 +342,22 @@ LUA_API lua_Number lua_tonumber(lua_State *L, int idx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
LUA_API lua_Number lua_tonumberx(lua_State *L, int idx, int *ok)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
TValue tmp;
|
||||
if (LJ_LIKELY(tvisnumber(o))) {
|
||||
if (ok) *ok = 1;
|
||||
return numberVnum(o);
|
||||
} else if (tvisstr(o) && lj_strscan_num(strV(o), &tmp)) {
|
||||
if (ok) *ok = 1;
|
||||
return numV(&tmp);
|
||||
} else {
|
||||
if (ok) *ok = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
|
@ -361,7 +395,7 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
|
|||
if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp)))
|
||||
return 0;
|
||||
if (tvisint(&tmp))
|
||||
return (lua_Integer)intV(&tmp);
|
||||
return intV(&tmp);
|
||||
n = numV(&tmp);
|
||||
}
|
||||
#if LJ_64
|
||||
|
@ -371,6 +405,35 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
|
|||
#endif
|
||||
}
|
||||
|
||||
LUA_API lua_Integer lua_tointegerx(lua_State *L, int idx, int *ok)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
TValue tmp;
|
||||
lua_Number n;
|
||||
if (LJ_LIKELY(tvisint(o))) {
|
||||
if (ok) *ok = 1;
|
||||
return intV(o);
|
||||
} else if (LJ_LIKELY(tvisnum(o))) {
|
||||
n = numV(o);
|
||||
} else {
|
||||
if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) {
|
||||
if (ok) *ok = 0;
|
||||
return 0;
|
||||
}
|
||||
if (tvisint(&tmp)) {
|
||||
if (ok) *ok = 1;
|
||||
return intV(&tmp);
|
||||
}
|
||||
n = numV(&tmp);
|
||||
}
|
||||
if (ok) *ok = 1;
|
||||
#if LJ_64
|
||||
return (lua_Integer)n;
|
||||
#else
|
||||
return lj_num2int(n);
|
||||
#endif
|
||||
}
|
||||
|
||||
LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
|
@ -434,7 +497,7 @@ LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len)
|
|||
} else if (tvisnumber(o)) {
|
||||
lj_gc_check(L);
|
||||
o = index2adr(L, idx); /* GC may move the stack. */
|
||||
s = lj_str_fromnumber(L, o);
|
||||
s = lj_strfmt_number(L, o);
|
||||
setstrV(L, o, s);
|
||||
} else {
|
||||
if (len != NULL) *len = 0;
|
||||
|
@ -453,7 +516,7 @@ LUALIB_API const char *luaL_checklstring(lua_State *L, int idx, size_t *len)
|
|||
} else if (tvisnumber(o)) {
|
||||
lj_gc_check(L);
|
||||
o = index2adr(L, idx); /* GC may move the stack. */
|
||||
s = lj_str_fromnumber(L, o);
|
||||
s = lj_strfmt_number(L, o);
|
||||
setstrV(L, o, s);
|
||||
} else {
|
||||
lj_err_argt(L, idx, LUA_TSTRING);
|
||||
|
@ -475,7 +538,7 @@ LUALIB_API const char *luaL_optlstring(lua_State *L, int idx,
|
|||
} else if (tvisnumber(o)) {
|
||||
lj_gc_check(L);
|
||||
o = index2adr(L, idx); /* GC may move the stack. */
|
||||
s = lj_str_fromnumber(L, o);
|
||||
s = lj_strfmt_number(L, o);
|
||||
setstrV(L, o, s);
|
||||
} else {
|
||||
lj_err_argt(L, idx, LUA_TSTRING);
|
||||
|
@ -507,7 +570,7 @@ LUA_API size_t lua_objlen(lua_State *L, int idx)
|
|||
} else if (tvisudata(o)) {
|
||||
return udataV(o)->len;
|
||||
} else if (tvisnumber(o)) {
|
||||
GCstr *s = lj_str_fromnumber(L, o);
|
||||
GCstr *s = lj_strfmt_number(L, o);
|
||||
setstrV(L, o, s);
|
||||
return s->len;
|
||||
} else {
|
||||
|
@ -545,17 +608,7 @@ LUA_API lua_State *lua_tothread(lua_State *L, int idx)
|
|||
|
||||
LUA_API const void *lua_topointer(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
if (tvisudata(o))
|
||||
return uddata(udataV(o));
|
||||
else if (tvislightud(o))
|
||||
return lightudV(o);
|
||||
else if (tviscdata(o))
|
||||
return cdataptr(cdataV(o));
|
||||
else if (tvisgcv(o))
|
||||
return gcV(o);
|
||||
else
|
||||
return NULL;
|
||||
return lj_obj_ptr(index2adr(L, idx));
|
||||
}
|
||||
|
||||
/* -- Stack setters (object creation) ------------------------------------- */
|
||||
|
@ -606,7 +659,7 @@ LUA_API const char *lua_pushvfstring(lua_State *L, const char *fmt,
|
|||
va_list argp)
|
||||
{
|
||||
lj_gc_check(L);
|
||||
return lj_str_pushvf(L, fmt, argp);
|
||||
return lj_strfmt_pushvf(L, fmt, argp);
|
||||
}
|
||||
|
||||
LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...)
|
||||
|
@ -615,7 +668,7 @@ LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...)
|
|||
va_list argp;
|
||||
lj_gc_check(L);
|
||||
va_start(argp, fmt);
|
||||
ret = lj_str_pushvf(L, fmt, argp);
|
||||
ret = lj_strfmt_pushvf(L, fmt, argp);
|
||||
va_end(argp);
|
||||
return ret;
|
||||
}
|
||||
|
@ -649,10 +702,8 @@ LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
|
|||
|
||||
LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
|
||||
{
|
||||
GCtab *t;
|
||||
lj_gc_check(L);
|
||||
t = lj_tab_new(L, (uint32_t)(narray > 0 ? narray+1 : 0), hsize2hbits(nrec));
|
||||
settabV(L, L->top, t);
|
||||
settabV(L, L->top, lj_tab_new_ah(L, narray, nrec));
|
||||
incr_top(L);
|
||||
}
|
||||
|
||||
|
@ -715,8 +766,8 @@ LUA_API void lua_concat(lua_State *L, int n)
|
|||
n -= (int)(L->top - top);
|
||||
L->top = top+2;
|
||||
lj_vm_call(L, top, 1+1);
|
||||
L->top--;
|
||||
copyTV(L, L->top-1, L->top);
|
||||
L->top -= 1+LJ_FR2;
|
||||
copyTV(L, L->top-1, L->top+LJ_FR2);
|
||||
} while (--n > 0);
|
||||
} else if (n == 0) { /* Push empty string. */
|
||||
setstrV(L, L->top, &G(L)->strempty);
|
||||
|
@ -735,8 +786,8 @@ LUA_API void lua_gettable(lua_State *L, int idx)
|
|||
if (v == NULL) {
|
||||
L->top += 2;
|
||||
lj_vm_call(L, L->top-2, 1+1);
|
||||
L->top -= 2;
|
||||
v = L->top+1;
|
||||
L->top -= 2+LJ_FR2;
|
||||
v = L->top+1+LJ_FR2;
|
||||
}
|
||||
copyTV(L, L->top-1, v);
|
||||
}
|
||||
|
@ -751,8 +802,8 @@ LUA_API void lua_getfield(lua_State *L, int idx, const char *k)
|
|||
if (v == NULL) {
|
||||
L->top += 2;
|
||||
lj_vm_call(L, L->top-2, 1+1);
|
||||
L->top -= 2;
|
||||
v = L->top+1;
|
||||
L->top -= 2+LJ_FR2;
|
||||
v = L->top+1+LJ_FR2;
|
||||
}
|
||||
copyTV(L, L->top, v);
|
||||
incr_top(L);
|
||||
|
@ -869,7 +920,7 @@ LUA_API void lua_upvaluejoin(lua_State *L, int idx1, int n1, int idx2, int n2)
|
|||
lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1]));
|
||||
}
|
||||
|
||||
LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
|
||||
LUALIB_API void *luaL_testudata(lua_State *L, int idx, const char *tname)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
if (tvisudata(o)) {
|
||||
|
@ -878,8 +929,14 @@ LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
|
|||
if (tv && tvistab(tv) && tabV(tv) == tabref(ud->metatable))
|
||||
return uddata(ud);
|
||||
}
|
||||
lj_err_argtype(L, idx, tname);
|
||||
return NULL; /* unreachable */
|
||||
return NULL; /* value is not a userdata with a metatable */
|
||||
}
|
||||
|
||||
LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname)
|
||||
{
|
||||
void *p = luaL_testudata(L, idx, tname);
|
||||
if (!p) lj_err_argtype(L, idx, tname);
|
||||
return p;
|
||||
}
|
||||
|
||||
/* -- Object setters ------------------------------------------------------ */
|
||||
|
@ -893,13 +950,14 @@ LUA_API void lua_settable(lua_State *L, int idx)
|
|||
o = lj_meta_tset(L, t, L->top-2);
|
||||
if (o) {
|
||||
/* NOBARRIER: lj_meta_tset ensures the table is not black. */
|
||||
copyTV(L, o, L->top-1);
|
||||
L->top -= 2;
|
||||
copyTV(L, o, L->top+1);
|
||||
} else {
|
||||
L->top += 3;
|
||||
copyTV(L, L->top-1, L->top-6);
|
||||
lj_vm_call(L, L->top-3, 0+1);
|
||||
L->top -= 3;
|
||||
TValue *base = L->top;
|
||||
copyTV(L, base+2, base-3-2*LJ_FR2);
|
||||
L->top = base+3;
|
||||
lj_vm_call(L, base, 0+1);
|
||||
L->top -= 3+LJ_FR2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -913,14 +971,14 @@ LUA_API void lua_setfield(lua_State *L, int idx, const char *k)
|
|||
setstrV(L, &key, lj_str_newz(L, k));
|
||||
o = lj_meta_tset(L, t, &key);
|
||||
if (o) {
|
||||
L->top--;
|
||||
/* NOBARRIER: lj_meta_tset ensures the table is not black. */
|
||||
copyTV(L, o, L->top);
|
||||
copyTV(L, o, --L->top);
|
||||
} else {
|
||||
L->top += 3;
|
||||
copyTV(L, L->top-1, L->top-6);
|
||||
lj_vm_call(L, L->top-3, 0+1);
|
||||
L->top -= 2;
|
||||
TValue *base = L->top;
|
||||
copyTV(L, base+2, base-3-2*LJ_FR2);
|
||||
L->top = base+3;
|
||||
lj_vm_call(L, base, 0+1);
|
||||
L->top -= 2+LJ_FR2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -987,6 +1045,12 @@ LUA_API int lua_setmetatable(lua_State *L, int idx)
|
|||
return 1;
|
||||
}
|
||||
|
||||
LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname)
|
||||
{
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, tname);
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
LUA_API int lua_setfenv(lua_State *L, int idx)
|
||||
{
|
||||
cTValue *o = index2adr(L, idx);
|
||||
|
@ -1027,11 +1091,24 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n)
|
|||
|
||||
/* -- Calls --------------------------------------------------------------- */
|
||||
|
||||
#if LJ_FR2
|
||||
static TValue *api_call_base(lua_State *L, int nargs)
|
||||
{
|
||||
TValue *o = L->top, *base = o - nargs;
|
||||
L->top = o+1;
|
||||
for (; o > base; o--) copyTV(L, o, o-1);
|
||||
setnilV(o);
|
||||
return o+1;
|
||||
}
|
||||
#else
|
||||
#define api_call_base(L, nargs) (L->top - (nargs))
|
||||
#endif
|
||||
|
||||
LUA_API void lua_call(lua_State *L, int nargs, int nresults)
|
||||
{
|
||||
api_check(L, L->status == 0 || L->status == LUA_ERRERR);
|
||||
api_check(L, L->status == LUA_OK || L->status == LUA_ERRERR);
|
||||
api_checknelems(L, nargs+1);
|
||||
lj_vm_call(L, L->top - nargs, nresults+1);
|
||||
lj_vm_call(L, api_call_base(L, nargs), nresults+1);
|
||||
}
|
||||
|
||||
LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
|
||||
|
@ -1040,7 +1117,7 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
|
|||
uint8_t oldh = hook_save(g);
|
||||
ptrdiff_t ef;
|
||||
int status;
|
||||
api_check(L, L->status == 0 || L->status == LUA_ERRERR);
|
||||
api_check(L, L->status == LUA_OK || L->status == LUA_ERRERR);
|
||||
api_checknelems(L, nargs+1);
|
||||
if (errfunc == 0) {
|
||||
ef = 0;
|
||||
|
@ -1049,7 +1126,7 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
|
|||
api_checkvalidindex(L, o);
|
||||
ef = savestack(L, o);
|
||||
}
|
||||
status = lj_vm_pcall(L, L->top - nargs, nresults+1, ef);
|
||||
status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef);
|
||||
if (status) hook_restore(g, oldh);
|
||||
return status;
|
||||
}
|
||||
|
@ -1057,12 +1134,14 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc)
|
|||
static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
|
||||
{
|
||||
GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L));
|
||||
TValue *top = L->top;
|
||||
fn->c.f = func;
|
||||
setfuncV(L, L->top, fn);
|
||||
setlightudV(L->top+1, checklightudptr(L, ud));
|
||||
setfuncV(L, top++, fn);
|
||||
if (LJ_FR2) setnilV(top++);
|
||||
setlightudV(top++, checklightudptr(L, ud));
|
||||
cframe_nres(L->cframe) = 1+0; /* Zero results. */
|
||||
L->top += 2;
|
||||
return L->top-1; /* Now call the newly allocated C function. */
|
||||
L->top = top;
|
||||
return top-1; /* Now call the newly allocated C function. */
|
||||
}
|
||||
|
||||
LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
|
||||
|
@ -1070,7 +1149,7 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
|
|||
global_State *g = G(L);
|
||||
uint8_t oldh = hook_save(g);
|
||||
int status;
|
||||
api_check(L, L->status == 0 || L->status == LUA_ERRERR);
|
||||
api_check(L, L->status == LUA_OK || L->status == LUA_ERRERR);
|
||||
status = lj_vm_cpcall(L, func, ud, cpcall);
|
||||
if (status) hook_restore(g, oldh);
|
||||
return status;
|
||||
|
@ -1079,10 +1158,11 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud)
|
|||
LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field)
|
||||
{
|
||||
if (luaL_getmetafield(L, idx, field)) {
|
||||
TValue *base = L->top--;
|
||||
copyTV(L, base, index2adr(L, idx));
|
||||
L->top = base+1;
|
||||
lj_vm_call(L, base, 1+1);
|
||||
TValue *top = L->top--;
|
||||
if (LJ_FR2) setnilV(top++);
|
||||
copyTV(L, top++, index2adr(L, idx));
|
||||
L->top = top;
|
||||
lj_vm_call(L, top-1, 1+1);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1090,6 +1170,11 @@ LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field)
|
|||
|
||||
/* -- Coroutine yield and resume ------------------------------------------ */
|
||||
|
||||
LUA_API int lua_isyieldable(lua_State *L)
|
||||
{
|
||||
return cframe_canyield(L->cframe);
|
||||
}
|
||||
|
||||
LUA_API int lua_yield(lua_State *L, int nresults)
|
||||
{
|
||||
void *cf = L->cframe;
|
||||
|
@ -1109,12 +1194,14 @@ LUA_API int lua_yield(lua_State *L, int nresults)
|
|||
} else { /* Yield from hook: add a pseudo-frame. */
|
||||
TValue *top = L->top;
|
||||
hook_leave(g);
|
||||
top->u64 = cframe_multres(cf);
|
||||
setcont(top+1, lj_cont_hook);
|
||||
setframe_pc(top+1, cframe_pc(cf)-1);
|
||||
setframe_gc(top+2, obj2gco(L));
|
||||
setframe_ftsz(top+2, (int)((char *)(top+3)-(char *)L->base)+FRAME_CONT);
|
||||
L->top = L->base = top+3;
|
||||
(top++)->u64 = cframe_multres(cf);
|
||||
setcont(top, lj_cont_hook);
|
||||
if (LJ_FR2) top++;
|
||||
setframe_pc(top, cframe_pc(cf)-1);
|
||||
if (LJ_FR2) top++;
|
||||
setframe_gc(top, obj2gco(L), LJ_TTHREAD);
|
||||
setframe_ftsz(top, ((char *)(top+1)-(char *)L->base)+FRAME_CONT);
|
||||
L->top = L->base = top+1;
|
||||
#if LJ_TARGET_X64
|
||||
lj_err_throw(L, LUA_YIELD);
|
||||
#else
|
||||
|
@ -1131,7 +1218,9 @@ LUA_API int lua_yield(lua_State *L, int nresults)
|
|||
LUA_API int lua_resume(lua_State *L, int nargs)
|
||||
{
|
||||
if (L->cframe == NULL && L->status <= LUA_YIELD)
|
||||
return lj_vm_resume(L, L->top - nargs, 0, 0);
|
||||
return lj_vm_resume(L,
|
||||
L->status == LUA_OK ? api_call_base(L, nargs) : L->top - nargs,
|
||||
0, 0);
|
||||
L->top = L->base;
|
||||
setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP));
|
||||
incr_top(L);
|
||||
|
@ -1161,7 +1250,7 @@ LUA_API int lua_gc(lua_State *L, int what, int data)
|
|||
res = (int)(g->gc.total & 0x3ff);
|
||||
break;
|
||||
case LUA_GCSTEP: {
|
||||
MSize a = (MSize)data << 10;
|
||||
GCSize a = (GCSize)data << 10;
|
||||
g->gc.threshold = (a <= g->gc.total) ? (g->gc.total - a) : 0;
|
||||
while (g->gc.total >= g->gc.threshold)
|
||||
if (lj_gc_step(L) > 0) {
|
||||
|
@ -1178,6 +1267,9 @@ LUA_API int lua_gc(lua_State *L, int what, int data)
|
|||
res = (int)(g->gc.stepmul);
|
||||
g->gc.stepmul = (MSize)data;
|
||||
break;
|
||||
case LUA_GCISRUNNING:
|
||||
res = (g->gc.threshold != LJ_MAX_MEM);
|
||||
break;
|
||||
default:
|
||||
res = -1; /* Invalid option. */
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Target architecture selection.
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_ARCH_H
|
||||
|
@ -19,12 +19,16 @@
|
|||
#define LUAJIT_ARCH_x64 2
|
||||
#define LUAJIT_ARCH_ARM 3
|
||||
#define LUAJIT_ARCH_arm 3
|
||||
#define LUAJIT_ARCH_PPC 4
|
||||
#define LUAJIT_ARCH_ppc 4
|
||||
#define LUAJIT_ARCH_PPCSPE 5
|
||||
#define LUAJIT_ARCH_ppcspe 5
|
||||
#define LUAJIT_ARCH_ARM64 4
|
||||
#define LUAJIT_ARCH_arm64 4
|
||||
#define LUAJIT_ARCH_PPC 5
|
||||
#define LUAJIT_ARCH_ppc 5
|
||||
#define LUAJIT_ARCH_MIPS 6
|
||||
#define LUAJIT_ARCH_mips 6
|
||||
#define LUAJIT_ARCH_MIPS32 6
|
||||
#define LUAJIT_ARCH_mips32 6
|
||||
#define LUAJIT_ARCH_MIPS64 7
|
||||
#define LUAJIT_ARCH_mips64 7
|
||||
|
||||
/* Target OS. */
|
||||
#define LUAJIT_OS_OTHER 0
|
||||
|
@ -43,14 +47,14 @@
|
|||
#define LUAJIT_TARGET LUAJIT_ARCH_X64
|
||||
#elif defined(__arm__) || defined(__arm) || defined(__ARM__) || defined(__ARM)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_ARM
|
||||
#elif defined(__aarch64__)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_ARM64
|
||||
#elif defined(__ppc__) || defined(__ppc) || defined(__PPC__) || defined(__PPC) || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) || defined(__POWERPC) || defined(_M_PPC)
|
||||
#ifdef __NO_FPRS__
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_PPCSPE
|
||||
#else
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_PPC
|
||||
#endif
|
||||
#elif defined(__mips64__) || defined(__mips64) || defined(__MIPS64__) || defined(__MIPS64)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_MIPS64
|
||||
#elif defined(__mips__) || defined(__mips) || defined(__MIPS__) || defined(__MIPS)
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_MIPS
|
||||
#define LUAJIT_TARGET LUAJIT_ARCH_MIPS32
|
||||
#else
|
||||
#error "No support for this architecture (yet)"
|
||||
#endif
|
||||
|
@ -70,7 +74,10 @@
|
|||
defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__DragonFly__)) && !defined(__ORBIS__)
|
||||
#define LUAJIT_OS LUAJIT_OS_BSD
|
||||
#elif (defined(__sun__) && defined(__svr4__)) || defined(__CYGWIN__)
|
||||
#elif (defined(__sun__) && defined(__svr4__)) || defined(__HAIKU__)
|
||||
#define LUAJIT_OS LUAJIT_OS_POSIX
|
||||
#elif defined(__CYGWIN__)
|
||||
#define LJ_TARGET_CYGWIN 1
|
||||
#define LUAJIT_OS LUAJIT_OS_POSIX
|
||||
#else
|
||||
#define LUAJIT_OS LUAJIT_OS_OTHER
|
||||
|
@ -96,7 +103,7 @@
|
|||
#define LJ_TARGET_WINDOWS (LUAJIT_OS == LUAJIT_OS_WINDOWS)
|
||||
#define LJ_TARGET_LINUX (LUAJIT_OS == LUAJIT_OS_LINUX)
|
||||
#define LJ_TARGET_OSX (LUAJIT_OS == LUAJIT_OS_OSX)
|
||||
#define LJ_TARGET_IOS (LJ_TARGET_OSX && LUAJIT_TARGET == LUAJIT_ARCH_ARM)
|
||||
#define LJ_TARGET_IOS (LJ_TARGET_OSX && (LUAJIT_TARGET == LUAJIT_ARCH_ARM || LUAJIT_TARGET == LUAJIT_ARCH_ARM64))
|
||||
#define LJ_TARGET_POSIX (LUAJIT_OS > LUAJIT_OS_WINDOWS)
|
||||
#define LJ_TARGET_DLOPEN LJ_TARGET_POSIX
|
||||
|
||||
|
@ -122,6 +129,12 @@
|
|||
#define LJ_TARGET_CONSOLE 1
|
||||
#endif
|
||||
|
||||
#ifdef _DURANGO
|
||||
#define LJ_TARGET_XBOXONE 1
|
||||
#define LJ_TARGET_CONSOLE 1
|
||||
#define LJ_TARGET_GC64 1
|
||||
#endif
|
||||
|
||||
#define LJ_NUMMODE_SINGLE 0 /* Single-number mode only. */
|
||||
#define LJ_NUMMODE_SINGLE_DUAL 1 /* Default to single-number mode. */
|
||||
#define LJ_NUMMODE_DUAL 2 /* Dual-number mode only. */
|
||||
|
@ -133,7 +146,7 @@
|
|||
#define LJ_ARCH_NAME "x86"
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#if LJ_TARGET_WINDOWS || __CYGWIN__
|
||||
#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
|
||||
#define LJ_ABI_WIN 1
|
||||
#else
|
||||
#define LJ_ABI_WIN 0
|
||||
|
@ -151,7 +164,11 @@
|
|||
#define LJ_ARCH_NAME "x64"
|
||||
#define LJ_ARCH_BITS 64
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#define LJ_ABI_WIN LJ_TARGET_WINDOWS
|
||||
#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_X86ORX64 1
|
||||
#define LJ_TARGET_EHRETREG 0
|
||||
|
@ -160,6 +177,9 @@
|
|||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNALIGNED 1
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE_DUAL
|
||||
#ifdef LUAJIT_ENABLE_GC64
|
||||
#define LJ_TARGET_GC64 1
|
||||
#endif
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM
|
||||
|
||||
|
@ -193,15 +213,49 @@
|
|||
#define LJ_ARCH_VERSION 50
|
||||
#endif
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM64
|
||||
|
||||
#define LJ_ARCH_BITS 64
|
||||
#if defined(__AARCH64EB__)
|
||||
#define LJ_ARCH_NAME "arm64be"
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||
#else
|
||||
#define LJ_ARCH_NAME "arm64"
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#endif
|
||||
#define LJ_TARGET_ARM64 1
|
||||
#define LJ_TARGET_EHRETREG 0
|
||||
#define LJ_TARGET_JUMPRANGE 27 /* +-2^27 = +-128MB */
|
||||
#define LJ_TARGET_MASKSHIFT 1
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
||||
#define LJ_TARGET_GC64 1
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||
|
||||
#define LJ_ARCH_VERSION 80
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_PPC
|
||||
|
||||
#define LJ_ARCH_NAME "ppc"
|
||||
#ifndef LJ_ARCH_ENDIAN
|
||||
#if __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#else
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if _LP64
|
||||
#define LJ_ARCH_BITS 64
|
||||
#if LJ_ARCH_ENDIAN == LUAJIT_LE
|
||||
#define LJ_ARCH_NAME "ppc64le"
|
||||
#else
|
||||
#define LJ_ARCH_NAME "ppc64"
|
||||
#endif
|
||||
#else
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_ARCH_NAME "ppc"
|
||||
#endif
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||
|
||||
#define LJ_TARGET_PPC 1
|
||||
#define LJ_TARGET_EHRETREG 3
|
||||
#define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */
|
||||
|
@ -210,6 +264,15 @@
|
|||
#define LJ_TARGET_UNIFYROT 1 /* Want only IR_BROL. */
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL_SINGLE
|
||||
|
||||
#if LJ_TARGET_CONSOLE
|
||||
#define LJ_ARCH_PPC32ON64 1
|
||||
#define LJ_ARCH_NOFFI 1
|
||||
#elif LJ_ARCH_BITS == 64
|
||||
#define LJ_ARCH_PPC64 1
|
||||
#define LJ_TARGET_GC64 1
|
||||
#define LJ_ARCH_NOJIT 1 /* NYI */
|
||||
#endif
|
||||
|
||||
#if _ARCH_PWR7
|
||||
#define LJ_ARCH_VERSION 70
|
||||
#elif _ARCH_PWR6
|
||||
|
@ -223,10 +286,6 @@
|
|||
#else
|
||||
#define LJ_ARCH_VERSION 0
|
||||
#endif
|
||||
#if __PPC64__ || __powerpc64__ || LJ_TARGET_CONSOLE
|
||||
#define LJ_ARCH_PPC64 1
|
||||
#define LJ_ARCH_NOFFI 1
|
||||
#endif
|
||||
#if _ARCH_PPCSQ
|
||||
#define LJ_ARCH_SQRT 1
|
||||
#endif
|
||||
|
@ -240,44 +299,60 @@
|
|||
#define LJ_ARCH_XENON 1
|
||||
#endif
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_PPCSPE
|
||||
|
||||
#define LJ_ARCH_NAME "ppcspe"
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||
#ifndef LJ_ABI_SOFTFP
|
||||
#define LJ_ABI_SOFTFP 1
|
||||
#endif
|
||||
#define LJ_ABI_EABI 1
|
||||
#define LJ_TARGET_PPCSPE 1
|
||||
#define LJ_TARGET_EHRETREG 3
|
||||
#define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */
|
||||
#define LJ_TARGET_MASKSHIFT 0
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNIFYROT 1 /* Want only IR_BROL. */
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE
|
||||
#define LJ_ARCH_NOFFI 1 /* NYI: comparisons, calls. */
|
||||
#define LJ_ARCH_NOJIT 1
|
||||
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_MIPS
|
||||
#elif LUAJIT_TARGET == LUAJIT_ARCH_MIPS32 || LUAJIT_TARGET == LUAJIT_ARCH_MIPS64
|
||||
|
||||
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL)
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||
#define LJ_ARCH_NAME "mipsel"
|
||||
#else
|
||||
#define LJ_ARCH_NAME "mips64el"
|
||||
#endif
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_LE
|
||||
#else
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||
#define LJ_ARCH_NAME "mips"
|
||||
#else
|
||||
#define LJ_ARCH_NAME "mips64"
|
||||
#endif
|
||||
#define LJ_ARCH_ENDIAN LUAJIT_BE
|
||||
#endif
|
||||
|
||||
#if !defined(LJ_ARCH_HASFPU)
|
||||
#ifdef __mips_soft_float
|
||||
#define LJ_ARCH_HASFPU 0
|
||||
#else
|
||||
#define LJ_ARCH_HASFPU 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(LJ_ABI_SOFTFP)
|
||||
#ifdef __mips_soft_float
|
||||
#define LJ_ABI_SOFTFP 1
|
||||
#else
|
||||
#define LJ_ABI_SOFTFP 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LUAJIT_TARGET == LUAJIT_ARCH_MIPS32
|
||||
#define LJ_ARCH_BITS 32
|
||||
#define LJ_TARGET_MIPS32 1
|
||||
#else
|
||||
#if LJ_ABI_SOFTFP || !LJ_ARCH_HASFPU
|
||||
#define LJ_ARCH_NOJIT 1 /* NYI */
|
||||
#endif
|
||||
#define LJ_ARCH_BITS 64
|
||||
#define LJ_TARGET_MIPS64 1
|
||||
#define LJ_TARGET_GC64 1
|
||||
#endif
|
||||
#define LJ_TARGET_MIPS 1
|
||||
#define LJ_TARGET_EHRETREG 4
|
||||
#define LJ_TARGET_JUMPRANGE 27 /* 2*2^27 = 256MB-aligned region */
|
||||
#define LJ_TARGET_MASKSHIFT 1
|
||||
#define LJ_TARGET_MASKROT 1
|
||||
#define LJ_TARGET_UNIFYROT 2 /* Want only IR_BROR. */
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE
|
||||
#define LJ_ARCH_NUMMODE LJ_NUMMODE_DUAL
|
||||
|
||||
#if _MIPS_ARCH_MIPS32R2
|
||||
#if _MIPS_ARCH_MIPS32R2 || _MIPS_ARCH_MIPS64R2
|
||||
#define LJ_ARCH_VERSION 20
|
||||
#else
|
||||
#define LJ_ARCH_VERSION 10
|
||||
|
@ -305,6 +380,16 @@
|
|||
#if (__GNUC__ < 4) || ((__GNUC__ == 4) && __GNUC_MINOR__ < 2)
|
||||
#error "Need at least GCC 4.2 or newer"
|
||||
#endif
|
||||
#elif LJ_TARGET_ARM64
|
||||
#if __clang__
|
||||
#if ((__clang_major__ < 3) || ((__clang_major__ == 3) && __clang_minor__ < 5)) && !defined(__NX_TOOLCHAIN_MAJOR__)
|
||||
#error "Need at least Clang 3.5 or newer"
|
||||
#endif
|
||||
#else
|
||||
#if (__GNUC__ < 4) || ((__GNUC__ == 4) && __GNUC_MINOR__ < 8)
|
||||
#error "Need at least GCC 4.8 or newer"
|
||||
#endif
|
||||
#endif
|
||||
#elif !LJ_TARGET_PS3
|
||||
#if (__GNUC__ < 4) || ((__GNUC__ == 4) && __GNUC_MINOR__ < 3)
|
||||
#error "Need at least GCC 4.3 or newer"
|
||||
|
@ -328,22 +413,30 @@
|
|||
#if !(__ARM_EABI__ || LJ_TARGET_IOS)
|
||||
#error "Only ARM EABI or iOS 3.0+ ABI is supported"
|
||||
#endif
|
||||
#elif LJ_TARGET_PPC || LJ_TARGET_PPCSPE
|
||||
#elif LJ_TARGET_ARM64
|
||||
#if defined(_ILP32)
|
||||
#error "No support for ILP32 model on ARM64"
|
||||
#endif
|
||||
#elif LJ_TARGET_PPC
|
||||
#if defined(_SOFT_FLOAT) || defined(_SOFT_DOUBLE)
|
||||
#error "No support for PowerPC CPUs without double-precision FPU"
|
||||
#endif
|
||||
#if defined(_LITTLE_ENDIAN)
|
||||
#error "No support for little-endian PowerPC"
|
||||
#if !LJ_ARCH_PPC64 && LJ_ARCH_ENDIAN == LUAJIT_LE
|
||||
#error "No support for little-endian PPC32"
|
||||
#endif
|
||||
#if defined(_LP64)
|
||||
#error "No support for PowerPC 64 bit mode"
|
||||
#if LJ_ARCH_PPC64
|
||||
#error "No support for PowerPC 64 bit mode (yet)"
|
||||
#endif
|
||||
#elif LJ_TARGET_MIPS
|
||||
#if defined(__mips_soft_float)
|
||||
#error "No support for MIPS CPUs without FPU"
|
||||
#ifdef __NO_FPRS__
|
||||
#error "No support for PPC/e500 anymore (use LuaJIT 2.0)"
|
||||
#endif
|
||||
#if defined(_LP64)
|
||||
#error "No support for MIPS64"
|
||||
#elif LJ_TARGET_MIPS32
|
||||
#if !((defined(_MIPS_SIM_ABI32) && _MIPS_SIM == _MIPS_SIM_ABI32) || (defined(_ABIO32) && _MIPS_SIM == _ABIO32))
|
||||
#error "Only o32 ABI supported for MIPS32"
|
||||
#endif
|
||||
#elif LJ_TARGET_MIPS64
|
||||
#if !((defined(_MIPS_SIM_ABI64) && _MIPS_SIM == _MIPS_SIM_ABI64) || (defined(_ABI64) && _MIPS_SIM == _ABI64))
|
||||
#error "Only n64 ABI supported for MIPS64"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
@ -369,6 +462,20 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/* 64 bit GC references. */
|
||||
#if LJ_TARGET_GC64
|
||||
#define LJ_GC64 1
|
||||
#else
|
||||
#define LJ_GC64 0
|
||||
#endif
|
||||
|
||||
/* 2-slot frame info. */
|
||||
#if LJ_GC64
|
||||
#define LJ_FR2 1
|
||||
#else
|
||||
#define LJ_FR2 0
|
||||
#endif
|
||||
|
||||
/* Disable or enable the JIT compiler. */
|
||||
#if defined(LUAJIT_DISABLE_JIT) || defined(LJ_ARCH_NOJIT) || defined(LJ_OS_NOJIT)
|
||||
#define LJ_HASJIT 0
|
||||
|
@ -383,6 +490,21 @@
|
|||
#define LJ_HASFFI 1
|
||||
#endif
|
||||
|
||||
#if defined(LUAJIT_DISABLE_PROFILE)
|
||||
#define LJ_HASPROFILE 0
|
||||
#elif LJ_TARGET_POSIX
|
||||
#define LJ_HASPROFILE 1
|
||||
#define LJ_PROFILE_SIGPROF 1
|
||||
#elif LJ_TARGET_PS3
|
||||
#define LJ_HASPROFILE 1
|
||||
#define LJ_PROFILE_PTHREAD 1
|
||||
#elif LJ_TARGET_WINDOWS || LJ_TARGET_XBOX360
|
||||
#define LJ_HASPROFILE 1
|
||||
#define LJ_PROFILE_WTHREAD 1
|
||||
#else
|
||||
#define LJ_HASPROFILE 0
|
||||
#endif
|
||||
|
||||
#ifndef LJ_ARCH_HASFPU
|
||||
#define LJ_ARCH_HASFPU 1
|
||||
#endif
|
||||
|
@ -415,15 +537,23 @@
|
|||
#define LJ_TARGET_UNALIGNED 0
|
||||
#endif
|
||||
|
||||
/* Various workarounds for embedded operating systems. */
|
||||
#if (defined(__ANDROID__) && !defined(LJ_TARGET_X86ORX64)) || defined(__symbian__) || LJ_TARGET_XBOX360
|
||||
/* Various workarounds for embedded operating systems or weak C runtimes. */
|
||||
#if defined(__ANDROID__) || defined(__symbian__) || LJ_TARGET_XBOX360 || LJ_TARGET_WINDOWS
|
||||
#define LUAJIT_NO_LOG2
|
||||
#endif
|
||||
#if defined(__symbian__)
|
||||
#if defined(__symbian__) || LJ_TARGET_WINDOWS
|
||||
#define LUAJIT_NO_EXP2
|
||||
#endif
|
||||
#if LJ_TARGET_CONSOLE || (LJ_TARGET_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0)
|
||||
#define LJ_NO_SYSTEM 1
|
||||
#endif
|
||||
|
||||
#if defined(LUAJIT_NO_UNWIND) || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3
|
||||
#if !defined(LUAJIT_NO_UNWIND) && __GNU_COMPACT_EH__
|
||||
/* NYI: no support for compact unwind specification, yet. */
|
||||
#define LUAJIT_NO_UNWIND 1
|
||||
#endif
|
||||
|
||||
#if defined(LUAJIT_NO_UNWIND) || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4
|
||||
#define LJ_NO_UNWIND 1
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** IR assembler (SSA IR -> machine code).
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#define lj_asm_c
|
||||
|
@ -91,7 +91,7 @@ typedef struct ASMState {
|
|||
MCode *realign; /* Realign loop if not NULL. */
|
||||
|
||||
#ifdef RID_NUM_KREF
|
||||
int32_t krefk[RID_NUM_KREF];
|
||||
intptr_t krefk[RID_NUM_KREF];
|
||||
#endif
|
||||
IRRef1 phireg[RID_MAX]; /* PHI register references. */
|
||||
uint16_t parentmap[LJ_MAX_JSLOTS]; /* Parent instruction to RegSP map. */
|
||||
|
@ -144,7 +144,7 @@ static LJ_AINLINE void checkmclim(ASMState *as)
|
|||
#define ra_krefreg(ref) ((Reg)(RID_MIN_KREF + (Reg)(ref)))
|
||||
#define ra_krefk(as, ref) (as->krefk[(ref)])
|
||||
|
||||
static LJ_AINLINE void ra_setkref(ASMState *as, Reg r, int32_t k)
|
||||
static LJ_AINLINE void ra_setkref(ASMState *as, Reg r, intptr_t k)
|
||||
{
|
||||
IRRef ref = (IRRef)(r - RID_MIN_KREF);
|
||||
as->krefk[ref] = k;
|
||||
|
@ -171,6 +171,8 @@ IRFLDEF(FLOFS)
|
|||
#include "lj_emit_x86.h"
|
||||
#elif LJ_TARGET_ARM
|
||||
#include "lj_emit_arm.h"
|
||||
#elif LJ_TARGET_ARM64
|
||||
#include "lj_emit_arm64.h"
|
||||
#elif LJ_TARGET_PPC
|
||||
#include "lj_emit_ppc.h"
|
||||
#elif LJ_TARGET_MIPS
|
||||
|
@ -179,6 +181,12 @@ IRFLDEF(FLOFS)
|
|||
#error "Missing instruction emitter for target CPU"
|
||||
#endif
|
||||
|
||||
/* Generic load/store of register from/to stack slot. */
|
||||
#define emit_spload(as, ir, r, ofs) \
|
||||
emit_loadofs(as, ir, (r), RID_SP, (ofs))
|
||||
#define emit_spstore(as, ir, r, ofs) \
|
||||
emit_storeofs(as, ir, (r), RID_SP, (ofs))
|
||||
|
||||
/* -- Register allocator debugging ---------------------------------------- */
|
||||
|
||||
/* #define LUAJIT_DEBUG_RA */
|
||||
|
@ -316,7 +324,11 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
|||
lua_assert(!rset_test(as->freeset, r));
|
||||
ra_free(as, r);
|
||||
ra_modified(as, r);
|
||||
#if LJ_64
|
||||
emit_loadu64(as, r, ra_krefk(as, ref));
|
||||
#else
|
||||
emit_loadi(as, r, ra_krefk(as, ref));
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
ir = IR(ref);
|
||||
|
@ -328,7 +340,7 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
|||
RA_DBGX((as, "remat $i $r", ir, r));
|
||||
#if !LJ_SOFTFP
|
||||
if (ir->o == IR_KNUM) {
|
||||
emit_loadn(as, r, ir_knum(ir));
|
||||
emit_loadk64(as, r, ir);
|
||||
} else
|
||||
#endif
|
||||
if (emit_canremat(REF_BASE) && ir->o == IR_BASE) {
|
||||
|
@ -336,10 +348,16 @@ static Reg ra_rematk(ASMState *as, IRRef ref)
|
|||
emit_getgl(as, r, jit_base);
|
||||
} else if (emit_canremat(ASMREF_L) && ir->o == IR_KPRI) {
|
||||
lua_assert(irt_isnil(ir->t)); /* REF_NIL stores ASMREF_L register. */
|
||||
emit_getgl(as, r, jit_L);
|
||||
emit_getgl(as, r, cur_L);
|
||||
#if LJ_64
|
||||
} else if (ir->o == IR_KINT64) {
|
||||
emit_loadu64(as, r, ir_kint64(ir)->u64);
|
||||
#if LJ_GC64
|
||||
} else if (ir->o == IR_KGC) {
|
||||
emit_loadu64(as, r, (uintptr_t)ir_kgc(ir));
|
||||
} else if (ir->o == IR_KPTR || ir->o == IR_KKPTR) {
|
||||
emit_loadu64(as, r, (uintptr_t)ir_kptr(ir));
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
lua_assert(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||
|
@ -512,7 +530,7 @@ static void ra_evictk(ASMState *as)
|
|||
|
||||
#ifdef RID_NUM_KREF
|
||||
/* Allocate a register for a constant. */
|
||||
static Reg ra_allock(ASMState *as, int32_t k, RegSet allow)
|
||||
static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow)
|
||||
{
|
||||
/* First try to find a register which already holds the same constant. */
|
||||
RegSet pick, work = ~as->freeset & RSET_GPR;
|
||||
|
@ -521,9 +539,31 @@ static Reg ra_allock(ASMState *as, int32_t k, RegSet allow)
|
|||
IRRef ref;
|
||||
r = rset_pickbot(work);
|
||||
ref = regcost_ref(as->cost[r]);
|
||||
#if LJ_64
|
||||
if (ref < ASMREF_L) {
|
||||
if (ra_iskref(ref)) {
|
||||
if (k == ra_krefk(as, ref))
|
||||
return r;
|
||||
} else {
|
||||
IRIns *ir = IR(ref);
|
||||
if ((ir->o == IR_KINT64 && k == (int64_t)ir_kint64(ir)->u64) ||
|
||||
#if LJ_GC64
|
||||
(ir->o == IR_KINT && k == ir->i) ||
|
||||
(ir->o == IR_KGC && k == (intptr_t)ir_kgc(ir)) ||
|
||||
((ir->o == IR_KPTR || ir->o == IR_KKPTR) &&
|
||||
k == (intptr_t)ir_kptr(ir))
|
||||
#else
|
||||
(ir->o != IR_KINT64 && k == ir->i)
|
||||
#endif
|
||||
)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (ref < ASMREF_L &&
|
||||
k == (ra_iskref(ref) ? ra_krefk(as, ref) : IR(ref)->i))
|
||||
return r;
|
||||
#endif
|
||||
rset_clear(work, r);
|
||||
}
|
||||
pick = as->freeset & allow;
|
||||
|
@ -543,7 +583,7 @@ static Reg ra_allock(ASMState *as, int32_t k, RegSet allow)
|
|||
}
|
||||
|
||||
/* Allocate a specific register for a constant. */
|
||||
static void ra_allockreg(ASMState *as, int32_t k, Reg r)
|
||||
static void ra_allockreg(ASMState *as, intptr_t k, Reg r)
|
||||
{
|
||||
Reg kr = ra_allock(as, k, RID2RSET(r));
|
||||
if (kr != r) {
|
||||
|
@ -613,10 +653,20 @@ static Reg ra_alloc1(ASMState *as, IRRef ref, RegSet allow)
|
|||
return r;
|
||||
}
|
||||
|
||||
/* Add a register rename to the IR. */
|
||||
static void ra_addrename(ASMState *as, Reg down, IRRef ref, SnapNo snapno)
|
||||
{
|
||||
IRRef ren;
|
||||
lj_ir_set(as->J, IRT(IR_RENAME, IRT_NIL), ref, snapno);
|
||||
ren = tref_ref(lj_ir_emit(as->J));
|
||||
as->J->cur.ir[ren].r = (uint8_t)down;
|
||||
as->J->cur.ir[ren].s = SPS_NONE;
|
||||
}
|
||||
|
||||
/* Rename register allocation and emit move. */
|
||||
static void ra_rename(ASMState *as, Reg down, Reg up)
|
||||
{
|
||||
IRRef ren, ref = regcost_ref(as->cost[up] = as->cost[down]);
|
||||
IRRef ref = regcost_ref(as->cost[up] = as->cost[down]);
|
||||
IRIns *ir = IR(ref);
|
||||
ir->r = (uint8_t)up;
|
||||
as->cost[down] = 0;
|
||||
|
@ -629,11 +679,7 @@ static void ra_rename(ASMState *as, Reg down, Reg 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. */
|
||||
if (!ra_hasspill(IR(ref)->s)) { /* Add the rename to the IR. */
|
||||
lj_ir_set(as->J, IRT(IR_RENAME, IRT_NIL), ref, as->snapno);
|
||||
ren = tref_ref(lj_ir_emit(as->J));
|
||||
as->ir = as->T->ir; /* The IR may have been reallocated. */
|
||||
IR(ren)->r = (uint8_t)down;
|
||||
IR(ren)->s = SPS_NONE;
|
||||
ra_addrename(as, down, ref, as->snapno);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -683,18 +729,22 @@ static void ra_left(ASMState *as, Reg dest, IRRef lref)
|
|||
if (ra_noreg(left)) {
|
||||
if (irref_isk(lref)) {
|
||||
if (ir->o == IR_KNUM) {
|
||||
cTValue *tv = ir_knum(ir);
|
||||
/* FP remat needs a load except for +0. Still better than eviction. */
|
||||
if (tvispzero(tv) || !(as->freeset & RSET_FPR)) {
|
||||
emit_loadn(as, dest, tv);
|
||||
if (tvispzero(ir_knum(ir)) || !(as->freeset & RSET_FPR)) {
|
||||
emit_loadk64(as, dest, ir);
|
||||
return;
|
||||
}
|
||||
#if LJ_64
|
||||
} else if (ir->o == IR_KINT64) {
|
||||
emit_loadu64(as, dest, ir_kint64(ir)->u64);
|
||||
emit_loadk64(as, dest, ir);
|
||||
return;
|
||||
#if LJ_GC64
|
||||
} else if (ir->o == IR_KGC || ir->o == IR_KPTR || ir->o == IR_KKPTR) {
|
||||
emit_loadk64(as, dest, ir);
|
||||
return;
|
||||
#endif
|
||||
} else {
|
||||
#endif
|
||||
} else if (ir->o != IR_KPRI) {
|
||||
lua_assert(ir->o == IR_KINT || ir->o == IR_KGC ||
|
||||
ir->o == IR_KPTR || ir->o == IR_KKPTR || ir->o == IR_KNULL);
|
||||
emit_loadi(as, dest, ir->i);
|
||||
|
@ -935,7 +985,7 @@ static void asm_snap_prep(ASMState *as)
|
|||
} else {
|
||||
/* Process any renames above the highwater mark. */
|
||||
for (; as->snaprename < as->T->nins; as->snaprename++) {
|
||||
IRIns *ir = IR(as->snaprename);
|
||||
IRIns *ir = &as->T->ir[as->snaprename];
|
||||
if (asm_snap_checkrename(as, ir->op1))
|
||||
ir->op2 = REF_BIAS-1; /* Kill rename. */
|
||||
}
|
||||
|
@ -944,44 +994,6 @@ static void asm_snap_prep(ASMState *as)
|
|||
|
||||
/* -- Miscellaneous helpers ----------------------------------------------- */
|
||||
|
||||
/* Collect arguments from CALL* and CARG instructions. */
|
||||
static void asm_collectargs(ASMState *as, IRIns *ir,
|
||||
const CCallInfo *ci, IRRef *args)
|
||||
{
|
||||
uint32_t n = CCI_NARGS(ci);
|
||||
lua_assert(n <= CCI_NARGS_MAX*2); /* Account for split args. */
|
||||
if ((ci->flags & CCI_L)) { *args++ = ASMREF_L; n--; }
|
||||
while (n-- > 1) {
|
||||
ir = IR(ir->op1);
|
||||
lua_assert(ir->o == IR_CARG);
|
||||
args[n] = ir->op2 == REF_NIL ? 0 : ir->op2;
|
||||
}
|
||||
args[0] = ir->op1 == REF_NIL ? 0 : ir->op1;
|
||||
lua_assert(IR(ir->op1)->o != IR_CARG);
|
||||
}
|
||||
|
||||
/* Reconstruct CCallInfo flags for CALLX*. */
|
||||
static uint32_t asm_callx_flags(ASMState *as, IRIns *ir)
|
||||
{
|
||||
uint32_t nargs = 0;
|
||||
if (ir->op1 != REF_NIL) { /* Count number of arguments first. */
|
||||
IRIns *ira = IR(ir->op1);
|
||||
nargs++;
|
||||
while (ira->o == IR_CARG) { nargs++; ira = IR(ira->op1); }
|
||||
}
|
||||
#if LJ_HASFFI
|
||||
if (IR(ir->op2)->o == IR_CARG) { /* Copy calling convention info. */
|
||||
CTypeID id = (CTypeID)IR(IR(ir->op2)->op2)->i;
|
||||
CType *ct = ctype_get(ctype_ctsG(J2G(as->J)), id);
|
||||
nargs |= ((ct->info & CTF_VARARG) ? CCI_VARARG : 0);
|
||||
#if LJ_TARGET_X86
|
||||
nargs |= (ctype_cconv(ct->info) << CCI_CC_SHIFT);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return (nargs | (ir->t.irt << CCI_OTSHIFT));
|
||||
}
|
||||
|
||||
/* Calculate stack adjustment. */
|
||||
static int32_t asm_stack_adjust(ASMState *as)
|
||||
{
|
||||
|
@ -1066,6 +1078,259 @@ static void asm_gcstep(ASMState *as, IRIns *ir)
|
|||
as->gcsteps = 0x80000000; /* Prevent implicit GC check further up. */
|
||||
}
|
||||
|
||||
/* -- Buffer operations --------------------------------------------------- */
|
||||
|
||||
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref);
|
||||
|
||||
static void asm_bufhdr(ASMState *as, IRIns *ir)
|
||||
{
|
||||
Reg sb = ra_dest(as, ir, RSET_GPR);
|
||||
if ((ir->op2 & IRBUFHDR_APPEND)) {
|
||||
/* Rematerialize const buffer pointer instead of likely spill. */
|
||||
IRIns *irp = IR(ir->op1);
|
||||
if (!(ra_hasreg(irp->r) || irp == ir-1 ||
|
||||
(irp == ir-2 && !ra_used(ir-1)))) {
|
||||
while (!(irp->o == IR_BUFHDR && !(irp->op2 & IRBUFHDR_APPEND)))
|
||||
irp = IR(irp->op1);
|
||||
if (irref_isk(irp->op1)) {
|
||||
ra_weak(as, ra_allocref(as, ir->op1, RSET_GPR));
|
||||
ir = irp;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
|
||||
/* Passing ir isn't strictly correct, but it's an IRT_PGC, too. */
|
||||
emit_storeofs(as, ir, tmp, sb, offsetof(SBuf, p));
|
||||
emit_loadofs(as, ir, tmp, sb, offsetof(SBuf, b));
|
||||
}
|
||||
#if LJ_TARGET_X86ORX64
|
||||
ra_left(as, sb, ir->op1);
|
||||
#else
|
||||
ra_leftov(as, sb, ir->op1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void asm_bufput(ASMState *as, IRIns *ir)
|
||||
{
|
||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_buf_putstr];
|
||||
IRRef args[3];
|
||||
IRIns *irs;
|
||||
int kchar = -1;
|
||||
args[0] = ir->op1; /* SBuf * */
|
||||
args[1] = ir->op2; /* GCstr * */
|
||||
irs = IR(ir->op2);
|
||||
lua_assert(irt_isstr(irs->t));
|
||||
if (irs->o == IR_KGC) {
|
||||
GCstr *s = ir_kstr(irs);
|
||||
if (s->len == 1) { /* Optimize put of single-char string constant. */
|
||||
kchar = strdata(s)[0];
|
||||
args[1] = ASMREF_TMP1; /* int, truncated to char */
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_buf_putchar];
|
||||
}
|
||||
} else if (mayfuse(as, ir->op2) && ra_noreg(irs->r)) {
|
||||
if (irs->o == IR_TOSTR) { /* Fuse number to string conversions. */
|
||||
if (irs->op2 == IRTOSTR_NUM) {
|
||||
args[1] = ASMREF_TMP1; /* TValue * */
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_putnum];
|
||||
} else {
|
||||
lua_assert(irt_isinteger(IR(irs->op1)->t));
|
||||
args[1] = irs->op1; /* int */
|
||||
if (irs->op2 == IRTOSTR_INT)
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_putint];
|
||||
else
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_buf_putchar];
|
||||
}
|
||||
} else if (irs->o == IR_SNEW) { /* Fuse string allocation. */
|
||||
args[1] = irs->op1; /* const void * */
|
||||
args[2] = irs->op2; /* MSize */
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_buf_putmem];
|
||||
}
|
||||
}
|
||||
asm_setupresult(as, ir, ci); /* SBuf * */
|
||||
asm_gencall(as, ci, args);
|
||||
if (args[1] == ASMREF_TMP1) {
|
||||
Reg tmp = ra_releasetmp(as, ASMREF_TMP1);
|
||||
if (kchar == -1)
|
||||
asm_tvptr(as, tmp, irs->op1);
|
||||
else
|
||||
ra_allockreg(as, kchar, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void asm_bufstr(ASMState *as, IRIns *ir)
|
||||
{
|
||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_buf_tostr];
|
||||
IRRef args[1];
|
||||
args[0] = ir->op1; /* SBuf *sb */
|
||||
as->gcsteps++;
|
||||
asm_setupresult(as, ir, ci); /* GCstr * */
|
||||
asm_gencall(as, ci, args);
|
||||
}
|
||||
|
||||
/* -- Type conversions ---------------------------------------------------- */
|
||||
|
||||
static void asm_tostr(ASMState *as, IRIns *ir)
|
||||
{
|
||||
const CCallInfo *ci;
|
||||
IRRef args[2];
|
||||
args[0] = ASMREF_L;
|
||||
as->gcsteps++;
|
||||
if (ir->op2 == IRTOSTR_NUM) {
|
||||
args[1] = ASMREF_TMP1; /* cTValue * */
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_num];
|
||||
} else {
|
||||
args[1] = ir->op1; /* int32_t k */
|
||||
if (ir->op2 == IRTOSTR_INT)
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_int];
|
||||
else
|
||||
ci = &lj_ir_callinfo[IRCALL_lj_strfmt_char];
|
||||
}
|
||||
asm_setupresult(as, ir, ci); /* GCstr * */
|
||||
asm_gencall(as, ci, args);
|
||||
if (ir->op2 == IRTOSTR_NUM)
|
||||
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1);
|
||||
}
|
||||
|
||||
#if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86
|
||||
static void asm_conv64(ASMState *as, IRIns *ir)
|
||||
{
|
||||
IRType st = (IRType)((ir-1)->op2 & IRCONV_SRCMASK);
|
||||
IRType dt = (((ir-1)->op2 & IRCONV_DSTMASK) >> IRCONV_DSH);
|
||||
IRCallID id;
|
||||
IRRef args[2];
|
||||
lua_assert((ir-1)->o == IR_CONV && ir->o == IR_HIOP);
|
||||
args[LJ_BE] = (ir-1)->op1;
|
||||
args[LJ_LE] = ir->op1;
|
||||
if (st == IRT_NUM || st == IRT_FLOAT) {
|
||||
id = IRCALL_fp64_d2l + ((st == IRT_FLOAT) ? 2 : 0) + (dt - IRT_I64);
|
||||
ir--;
|
||||
} else {
|
||||
id = IRCALL_fp64_l2d + ((dt == IRT_FLOAT) ? 2 : 0) + (st - IRT_I64);
|
||||
}
|
||||
{
|
||||
#if LJ_TARGET_ARM && !LJ_ABI_SOFTFP
|
||||
CCallInfo cim = lj_ir_callinfo[id], *ci = &cim;
|
||||
cim.flags |= CCI_VARARG; /* These calls don't use the hard-float ABI! */
|
||||
#else
|
||||
const CCallInfo *ci = &lj_ir_callinfo[id];
|
||||
#endif
|
||||
asm_setupresult(as, ir, ci);
|
||||
asm_gencall(as, ci, args);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- Memory references --------------------------------------------------- */
|
||||
|
||||
static void asm_newref(ASMState *as, IRIns *ir)
|
||||
{
|
||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_newkey];
|
||||
IRRef args[3];
|
||||
if (ir->r == RID_SINK)
|
||||
return;
|
||||
args[0] = ASMREF_L; /* lua_State *L */
|
||||
args[1] = ir->op1; /* GCtab *t */
|
||||
args[2] = ASMREF_TMP1; /* cTValue *key */
|
||||
asm_setupresult(as, ir, ci); /* TValue * */
|
||||
asm_gencall(as, ci, args);
|
||||
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2);
|
||||
}
|
||||
|
||||
static void asm_lref(ASMState *as, IRIns *ir)
|
||||
{
|
||||
Reg r = ra_dest(as, ir, RSET_GPR);
|
||||
#if LJ_TARGET_X86ORX64
|
||||
ra_left(as, r, ASMREF_L);
|
||||
#else
|
||||
ra_leftov(as, r, ASMREF_L);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* -- Calls --------------------------------------------------------------- */
|
||||
|
||||
/* Collect arguments from CALL* and CARG instructions. */
|
||||
static void asm_collectargs(ASMState *as, IRIns *ir,
|
||||
const CCallInfo *ci, IRRef *args)
|
||||
{
|
||||
uint32_t n = CCI_XNARGS(ci);
|
||||
lua_assert(n <= CCI_NARGS_MAX*2); /* Account for split args. */
|
||||
if ((ci->flags & CCI_L)) { *args++ = ASMREF_L; n--; }
|
||||
while (n-- > 1) {
|
||||
ir = IR(ir->op1);
|
||||
lua_assert(ir->o == IR_CARG);
|
||||
args[n] = ir->op2 == REF_NIL ? 0 : ir->op2;
|
||||
}
|
||||
args[0] = ir->op1 == REF_NIL ? 0 : ir->op1;
|
||||
lua_assert(IR(ir->op1)->o != IR_CARG);
|
||||
}
|
||||
|
||||
/* Reconstruct CCallInfo flags for CALLX*. */
|
||||
static uint32_t asm_callx_flags(ASMState *as, IRIns *ir)
|
||||
{
|
||||
uint32_t nargs = 0;
|
||||
if (ir->op1 != REF_NIL) { /* Count number of arguments first. */
|
||||
IRIns *ira = IR(ir->op1);
|
||||
nargs++;
|
||||
while (ira->o == IR_CARG) { nargs++; ira = IR(ira->op1); }
|
||||
}
|
||||
#if LJ_HASFFI
|
||||
if (IR(ir->op2)->o == IR_CARG) { /* Copy calling convention info. */
|
||||
CTypeID id = (CTypeID)IR(IR(ir->op2)->op2)->i;
|
||||
CType *ct = ctype_get(ctype_ctsG(J2G(as->J)), id);
|
||||
nargs |= ((ct->info & CTF_VARARG) ? CCI_VARARG : 0);
|
||||
#if LJ_TARGET_X86
|
||||
nargs |= (ctype_cconv(ct->info) << CCI_CC_SHIFT);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return (nargs | (ir->t.irt << CCI_OTSHIFT));
|
||||
}
|
||||
|
||||
static void asm_callid(ASMState *as, IRIns *ir, IRCallID id)
|
||||
{
|
||||
const CCallInfo *ci = &lj_ir_callinfo[id];
|
||||
IRRef args[2];
|
||||
args[0] = ir->op1;
|
||||
args[1] = ir->op2;
|
||||
asm_setupresult(as, ir, ci);
|
||||
asm_gencall(as, ci, args);
|
||||
}
|
||||
|
||||
static void asm_call(ASMState *as, IRIns *ir)
|
||||
{
|
||||
IRRef args[CCI_NARGS_MAX];
|
||||
const CCallInfo *ci = &lj_ir_callinfo[ir->op2];
|
||||
asm_collectargs(as, ir, ci, args);
|
||||
asm_setupresult(as, ir, ci);
|
||||
asm_gencall(as, ci, args);
|
||||
}
|
||||
|
||||
#if !LJ_SOFTFP
|
||||
static void asm_fppow(ASMState *as, IRIns *ir, IRRef lref, IRRef rref)
|
||||
{
|
||||
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_pow];
|
||||
IRRef args[2];
|
||||
args[0] = lref;
|
||||
args[1] = rref;
|
||||
asm_setupresult(as, ir, ci);
|
||||
asm_gencall(as, ci, args);
|
||||
}
|
||||
|
||||
static int asm_fpjoin_pow(ASMState *as, IRIns *ir)
|
||||
{
|
||||
IRIns *irp = IR(ir->op1);
|
||||
if (irp == ir-1 && irp->o == IR_MUL && !ra_used(irp)) {
|
||||
IRIns *irpp = IR(irp->op1);
|
||||
if (irpp == ir-2 && irpp->o == IR_FPMATH &&
|
||||
irpp->op2 == IRFPM_LOG2 && !ra_used(irpp)) {
|
||||
asm_fppow(as, ir, irpp->op1, irp->op2);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* -- PHI and loop handling ----------------------------------------------- */
|
||||
|
||||
/* Break a PHI cycle by renaming to a free register (evict if needed). */
|
||||
|
@ -1251,12 +1516,7 @@ static void asm_phi_fixup(ASMState *as)
|
|||
irt_clearmark(ir->t);
|
||||
/* Left PHI gained a spill slot before the loop? */
|
||||
if (ra_hasspill(ir->s)) {
|
||||
IRRef ren;
|
||||
lj_ir_set(as->J, IRT(IR_RENAME, IRT_NIL), lref, as->loopsnapno);
|
||||
ren = tref_ref(lj_ir_emit(as->J));
|
||||
as->ir = as->T->ir; /* The IR may have been reallocated. */
|
||||
IR(ren)->r = (uint8_t)r;
|
||||
IR(ren)->s = SPS_NONE;
|
||||
ra_addrename(as, r, lref, as->loopsnapno);
|
||||
}
|
||||
}
|
||||
rset_clear(work, r);
|
||||
|
@ -1331,6 +1591,8 @@ static void asm_loop(ASMState *as)
|
|||
#include "lj_asm_x86.h"
|
||||
#elif LJ_TARGET_ARM
|
||||
#include "lj_asm_arm.h"
|
||||
#elif LJ_TARGET_ARM64
|
||||
#include "lj_asm_arm64.h"
|
||||
#elif LJ_TARGET_PPC
|
||||
#include "lj_asm_ppc.h"
|
||||
#elif LJ_TARGET_MIPS
|
||||
|
@ -1339,6 +1601,136 @@ static void asm_loop(ASMState *as)
|
|||
#error "Missing assembler for target CPU"
|
||||
#endif
|
||||
|
||||
/* -- Instruction dispatch ------------------------------------------------ */
|
||||
|
||||
/* Assemble a single instruction. */
|
||||
static void asm_ir(ASMState *as, IRIns *ir)
|
||||
{
|
||||
switch ((IROp)ir->o) {
|
||||
/* Miscellaneous ops. */
|
||||
case IR_LOOP: asm_loop(as); break;
|
||||
case IR_NOP: case IR_XBAR: lua_assert(!ra_used(ir)); break;
|
||||
case IR_USE:
|
||||
ra_alloc1(as, ir->op1, irt_isfp(ir->t) ? RSET_FPR : RSET_GPR); break;
|
||||
case IR_PHI: asm_phi(as, ir); break;
|
||||
case IR_HIOP: asm_hiop(as, ir); break;
|
||||
case IR_GCSTEP: asm_gcstep(as, ir); break;
|
||||
case IR_PROF: asm_prof(as, ir); break;
|
||||
|
||||
/* Guarded assertions. */
|
||||
case IR_LT: case IR_GE: case IR_LE: case IR_GT:
|
||||
case IR_ULT: case IR_UGE: case IR_ULE: case IR_UGT:
|
||||
case IR_ABC:
|
||||
asm_comp(as, ir);
|
||||
break;
|
||||
case IR_EQ: case IR_NE:
|
||||
if ((ir-1)->o == IR_HREF && ir->op1 == as->curins-1) {
|
||||
as->curins--;
|
||||
asm_href(as, ir-1, (IROp)ir->o);
|
||||
} else {
|
||||
asm_equal(as, ir);
|
||||
}
|
||||
break;
|
||||
|
||||
case IR_RETF: asm_retf(as, ir); break;
|
||||
|
||||
/* Bit ops. */
|
||||
case IR_BNOT: asm_bnot(as, ir); break;
|
||||
case IR_BSWAP: asm_bswap(as, ir); break;
|
||||
case IR_BAND: asm_band(as, ir); break;
|
||||
case IR_BOR: asm_bor(as, ir); break;
|
||||
case IR_BXOR: asm_bxor(as, ir); break;
|
||||
case IR_BSHL: asm_bshl(as, ir); break;
|
||||
case IR_BSHR: asm_bshr(as, ir); break;
|
||||
case IR_BSAR: asm_bsar(as, ir); break;
|
||||
case IR_BROL: asm_brol(as, ir); break;
|
||||
case IR_BROR: asm_bror(as, ir); break;
|
||||
|
||||
/* Arithmetic ops. */
|
||||
case IR_ADD: asm_add(as, ir); break;
|
||||
case IR_SUB: asm_sub(as, ir); break;
|
||||
case IR_MUL: asm_mul(as, ir); break;
|
||||
case IR_MOD: asm_mod(as, ir); break;
|
||||
case IR_NEG: asm_neg(as, ir); break;
|
||||
#if LJ_SOFTFP
|
||||
case IR_DIV: case IR_POW: case IR_ABS:
|
||||
case IR_ATAN2: case IR_LDEXP: case IR_FPMATH: case IR_TOBIT:
|
||||
lua_assert(0); /* Unused for LJ_SOFTFP. */
|
||||
break;
|
||||
#else
|
||||
case IR_DIV: asm_div(as, ir); break;
|
||||
case IR_POW: asm_pow(as, ir); break;
|
||||
case IR_ABS: asm_abs(as, ir); break;
|
||||
case IR_ATAN2: asm_atan2(as, ir); break;
|
||||
case IR_LDEXP: asm_ldexp(as, ir); break;
|
||||
case IR_FPMATH: asm_fpmath(as, ir); break;
|
||||
case IR_TOBIT: asm_tobit(as, ir); break;
|
||||
#endif
|
||||
case IR_MIN: asm_min(as, ir); break;
|
||||
case IR_MAX: asm_max(as, ir); break;
|
||||
|
||||
/* Overflow-checking arithmetic ops. */
|
||||
case IR_ADDOV: asm_addov(as, ir); break;
|
||||
case IR_SUBOV: asm_subov(as, ir); break;
|
||||
case IR_MULOV: asm_mulov(as, ir); break;
|
||||
|
||||
/* Memory references. */
|
||||
case IR_AREF: asm_aref(as, ir); break;
|
||||
case IR_HREF: asm_href(as, ir, 0); break;
|
||||
case IR_HREFK: asm_hrefk(as, ir); break;
|
||||
case IR_NEWREF: asm_newref(as, ir); break;
|
||||
case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;
|
||||
case IR_FREF: asm_fref(as, ir); break;
|
||||
case IR_STRREF: asm_strref(as, ir); break;
|
||||
case IR_LREF: asm_lref(as, ir); break;
|
||||
|
||||
/* Loads and stores. */
|
||||
case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
|
||||
asm_ahuvload(as, ir);
|
||||
break;
|
||||
case IR_FLOAD: asm_fload(as, ir); break;
|
||||
case IR_XLOAD: asm_xload(as, ir); break;
|
||||
case IR_SLOAD: asm_sload(as, ir); break;
|
||||
|
||||
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: asm_ahustore(as, ir); break;
|
||||
case IR_FSTORE: asm_fstore(as, ir); break;
|
||||
case IR_XSTORE: asm_xstore(as, ir); break;
|
||||
|
||||
/* Allocations. */
|
||||
case IR_SNEW: case IR_XSNEW: asm_snew(as, ir); break;
|
||||
case IR_TNEW: asm_tnew(as, ir); break;
|
||||
case IR_TDUP: asm_tdup(as, ir); break;
|
||||
case IR_CNEW: case IR_CNEWI: asm_cnew(as, ir); break;
|
||||
|
||||
/* Buffer operations. */
|
||||
case IR_BUFHDR: asm_bufhdr(as, ir); break;
|
||||
case IR_BUFPUT: asm_bufput(as, ir); break;
|
||||
case IR_BUFSTR: asm_bufstr(as, ir); break;
|
||||
|
||||
/* Write barriers. */
|
||||
case IR_TBAR: asm_tbar(as, ir); break;
|
||||
case IR_OBAR: asm_obar(as, ir); break;
|
||||
|
||||
/* Type conversions. */
|
||||
case IR_CONV: asm_conv(as, ir); break;
|
||||
case IR_TOSTR: asm_tostr(as, ir); break;
|
||||
case IR_STRTO: asm_strto(as, ir); break;
|
||||
|
||||
/* Calls. */
|
||||
case IR_CALLA:
|
||||
as->gcsteps++;
|
||||
/* fallthrough */
|
||||
case IR_CALLN: case IR_CALLL: case IR_CALLS: asm_call(as, ir); break;
|
||||
case IR_CALLXS: asm_callx(as, ir); break;
|
||||
case IR_CARG: break;
|
||||
|
||||
default:
|
||||
setintV(&as->J->errinfo, ir->o);
|
||||
lj_trace_err_info(as->J, LJ_TRERR_NYIIR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Head of trace ------------------------------------------------------- */
|
||||
|
||||
/* Head of a root trace. */
|
||||
|
@ -1537,7 +1929,7 @@ static BCReg asm_baseslot(ASMState *as, SnapShot *snap, int *gotframe)
|
|||
SnapEntry sn = map[n-1];
|
||||
if ((sn & SNAP_FRAME)) {
|
||||
*gotframe = 1;
|
||||
return snap_slot(sn);
|
||||
return snap_slot(sn) - LJ_FR2;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -1557,19 +1949,23 @@ static void asm_tail_link(ASMState *as)
|
|||
|
||||
if (as->T->link == 0) {
|
||||
/* Setup fixed registers for exit to interpreter. */
|
||||
const BCIns *pc = snap_pc(as->T->snapmap[snap->mapofs + snap->nent]);
|
||||
const BCIns *pc = snap_pc(&as->T->snapmap[snap->mapofs + snap->nent]);
|
||||
int32_t mres;
|
||||
if (bc_op(*pc) == BC_JLOOP) { /* NYI: find a better way to do this. */
|
||||
BCIns *retpc = &traceref(as->J, bc_d(*pc))->startins;
|
||||
if (bc_isret(bc_op(*retpc)))
|
||||
pc = retpc;
|
||||
}
|
||||
#if LJ_GC64
|
||||
emit_loadu64(as, RID_LPC, u64ptr(pc));
|
||||
#else
|
||||
ra_allockreg(as, i32ptr(J2GG(as->J)->dispatch), RID_DISPATCH);
|
||||
ra_allockreg(as, i32ptr(pc), RID_LPC);
|
||||
mres = (int32_t)(snap->nslots - baseslot);
|
||||
#endif
|
||||
mres = (int32_t)(snap->nslots - baseslot - LJ_FR2);
|
||||
switch (bc_op(*pc)) {
|
||||
case BC_CALLM: case BC_CALLMT:
|
||||
mres -= (int32_t)(1 + bc_a(*pc) + bc_c(*pc)); break;
|
||||
mres -= (int32_t)(1 + LJ_FR2 + bc_a(*pc) + bc_c(*pc)); break;
|
||||
case BC_RETM: mres -= (int32_t)(bc_a(*pc) + bc_d(*pc)); break;
|
||||
case BC_TSETM: mres -= (int32_t)bc_a(*pc); break;
|
||||
default: if (bc_op(*pc) < BC_FUNCF) mres = 0; break;
|
||||
|
@ -1581,6 +1977,11 @@ static void asm_tail_link(ASMState *as)
|
|||
}
|
||||
emit_addptr(as, RID_BASE, 8*(int32_t)baseslot);
|
||||
|
||||
if (as->J->ktrace) { /* Patch ktrace slot with the final GCtrace pointer. */
|
||||
setgcref(IR(as->J->ktrace)[LJ_GC64].gcr, obj2gco(as->J->curfinal));
|
||||
IR(as->J->ktrace)->o = IR_KGC;
|
||||
}
|
||||
|
||||
/* Sync the interpreter state with the on-trace state. */
|
||||
asm_stack_restore(as, snap);
|
||||
|
||||
|
@ -1606,17 +2007,22 @@ static void asm_setup_regsp(ASMState *as)
|
|||
ra_setup(as);
|
||||
|
||||
/* 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++) {
|
||||
ir->prev = REGSP_INIT;
|
||||
if (irt_is64(ir->t) && ir->o != IR_KNULL) {
|
||||
#if LJ_GC64
|
||||
ir->i = 0; /* Will become non-zero only for RIP-relative addresses. */
|
||||
#else
|
||||
/* Make life easier for backends by putting address of constant in i. */
|
||||
ir->i = (int32_t)(intptr_t)(ir+1);
|
||||
#endif
|
||||
ir++;
|
||||
}
|
||||
}
|
||||
|
||||
/* REF_BASE is used for implicit references to the BASE register. */
|
||||
lastir->prev = REGSP_HINT(RID_BASE);
|
||||
|
||||
ir = IR(nins-1);
|
||||
if (ir->o == IR_RENAME) {
|
||||
do { ir--; nins--; } while (ir->o == IR_RENAME);
|
||||
T->nins = nins; /* Remove any renames left over from ASM restart. */
|
||||
}
|
||||
as->snaprename = nins;
|
||||
as->snapref = nins;
|
||||
as->snapno = T->nsnap;
|
||||
|
@ -1677,7 +2083,7 @@ static void asm_setup_regsp(ASMState *as)
|
|||
as->modset |= RSET_SCRATCH;
|
||||
continue;
|
||||
}
|
||||
case IR_CALLN: case IR_CALLL: case IR_CALLS: {
|
||||
case IR_CALLN: case IR_CALLA: case IR_CALLL: case IR_CALLS: {
|
||||
const CCallInfo *ci = &lj_ir_callinfo[ir->op2];
|
||||
ir->prev = asm_setup_call_slots(as, ir, ci);
|
||||
if (inloop)
|
||||
|
@ -1722,10 +2128,20 @@ static void asm_setup_regsp(ASMState *as)
|
|||
/* fallthrough */
|
||||
#endif
|
||||
/* C calls evict all scratch regs and return results in RID_RET. */
|
||||
case IR_SNEW: case IR_XSNEW: case IR_NEWREF:
|
||||
case IR_SNEW: case IR_XSNEW: case IR_NEWREF: case IR_BUFPUT:
|
||||
if (REGARG_NUMGPR < 3 && as->evenspill < 3)
|
||||
as->evenspill = 3; /* lj_str_new and lj_tab_newkey need 3 args. */
|
||||
case IR_TNEW: case IR_TDUP: case IR_CNEW: case IR_CNEWI: case IR_TOSTR:
|
||||
#if LJ_TARGET_X86 && LJ_HASFFI
|
||||
if (0) {
|
||||
case IR_CNEW:
|
||||
if (ir->op2 != REF_NIL && as->evenspill < 4)
|
||||
as->evenspill = 4; /* lj_cdata_newv needs 4 args. */
|
||||
}
|
||||
#else
|
||||
case IR_CNEW:
|
||||
#endif
|
||||
case IR_TNEW: case IR_TDUP: case IR_CNEWI: case IR_TOSTR:
|
||||
case IR_BUFSTR:
|
||||
ir->prev = REGSP_HINT(RID_RET);
|
||||
if (inloop)
|
||||
as->modset = RSET_SCRATCH;
|
||||
|
@ -1734,21 +2150,26 @@ static void asm_setup_regsp(ASMState *as)
|
|||
if (inloop)
|
||||
as->modset = RSET_SCRATCH;
|
||||
break;
|
||||
#if !LJ_TARGET_X86ORX64 && !LJ_SOFTFP
|
||||
case IR_ATAN2: case IR_LDEXP:
|
||||
#if !LJ_SOFTFP
|
||||
case IR_ATAN2:
|
||||
#if LJ_TARGET_X86
|
||||
if (as->evenspill < 4) /* Leave room to call atan2(). */
|
||||
as->evenspill = 4;
|
||||
#endif
|
||||
#if !LJ_TARGET_X86ORX64
|
||||
case IR_LDEXP:
|
||||
#endif
|
||||
#endif
|
||||
case IR_POW:
|
||||
if (!LJ_SOFTFP && irt_isnum(ir->t)) {
|
||||
#if LJ_TARGET_X86ORX64
|
||||
ir->prev = REGSP_HINT(RID_XMM0);
|
||||
if (inloop)
|
||||
as->modset |= RSET_RANGE(RID_XMM0, RID_XMM1+1)|RID2RSET(RID_EAX);
|
||||
#else
|
||||
ir->prev = REGSP_HINT(RID_FPRET);
|
||||
if (inloop)
|
||||
as->modset |= RSET_SCRATCH;
|
||||
#endif
|
||||
#if LJ_TARGET_X86
|
||||
break;
|
||||
#else
|
||||
ir->prev = REGSP_HINT(RID_FPRET);
|
||||
continue;
|
||||
#endif
|
||||
}
|
||||
/* fallthrough for integer POW */
|
||||
case IR_DIV: case IR_MOD:
|
||||
|
@ -1761,31 +2182,33 @@ static void asm_setup_regsp(ASMState *as)
|
|||
break;
|
||||
case IR_FPMATH:
|
||||
#if LJ_TARGET_X86ORX64
|
||||
if (ir->op2 == IRFPM_EXP2) { /* May be joined to lj_vm_pow_sse. */
|
||||
ir->prev = REGSP_HINT(RID_XMM0);
|
||||
#if !LJ_64
|
||||
if (as->evenspill < 4) /* Leave room for 16 byte scratch area. */
|
||||
if (ir->op2 <= IRFPM_TRUNC) {
|
||||
if (!(as->flags & JIT_F_SSE4_1)) {
|
||||
ir->prev = REGSP_HINT(RID_XMM0);
|
||||
if (inloop)
|
||||
as->modset |= RSET_RANGE(RID_XMM0, RID_XMM3+1)|RID2RSET(RID_EAX);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} else if (ir->op2 == IRFPM_EXP2 && !LJ_64) {
|
||||
if (as->evenspill < 4) /* Leave room to call pow(). */
|
||||
as->evenspill = 4;
|
||||
#endif
|
||||
if (inloop)
|
||||
as->modset |= RSET_RANGE(RID_XMM0, RID_XMM2+1)|RID2RSET(RID_EAX);
|
||||
continue;
|
||||
} else if (ir->op2 <= IRFPM_TRUNC && !(as->flags & JIT_F_SSE4_1)) {
|
||||
ir->prev = REGSP_HINT(RID_XMM0);
|
||||
if (inloop)
|
||||
as->modset |= RSET_RANGE(RID_XMM0, RID_XMM3+1)|RID2RSET(RID_EAX);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (inloop)
|
||||
as->modset |= RSET_SCRATCH;
|
||||
#if LJ_TARGET_X86
|
||||
break;
|
||||
#else
|
||||
ir->prev = REGSP_HINT(RID_FPRET);
|
||||
if (inloop)
|
||||
as->modset |= RSET_SCRATCH;
|
||||
continue;
|
||||
#endif
|
||||
#if LJ_TARGET_X86ORX64
|
||||
/* Non-constant shift counts need to be in RID_ECX on x86/x64. */
|
||||
case IR_BSHL: case IR_BSHR: case IR_BSAR: case IR_BROL: case IR_BROR:
|
||||
case IR_BSHL: case IR_BSHR: case IR_BSAR:
|
||||
if ((as->flags & JIT_F_BMI2)) /* Except if BMI2 is available. */
|
||||
break;
|
||||
case IR_BROL: case IR_BROR:
|
||||
if (!irref_isk(ir->op2) && !ra_hashint(IR(ir->op2)->r)) {
|
||||
IR(ir->op2)->r = REGSP_HINT(RID_ECX);
|
||||
if (inloop)
|
||||
|
@ -1831,14 +2254,25 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||
ASMState *as = &as_;
|
||||
MCode *origtop;
|
||||
|
||||
/* Remove nops/renames left over from ASM restart due to LJ_TRERR_MCODELM. */
|
||||
{
|
||||
IRRef nins = T->nins;
|
||||
IRIns *ir = &T->ir[nins-1];
|
||||
if (ir->o == IR_NOP || ir->o == IR_RENAME) {
|
||||
do { ir--; nins--; } while (ir->o == IR_NOP || ir->o == IR_RENAME);
|
||||
T->nins = nins;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure an initialized instruction beyond the last one for HIOP checks. */
|
||||
J->cur.nins = lj_ir_nextins(J);
|
||||
J->cur.ir[J->cur.nins].o = IR_NOP;
|
||||
/* This also allows one RENAME to be added without reallocating curfinal. */
|
||||
as->orignins = lj_ir_nextins(J);
|
||||
J->cur.ir[as->orignins].o = IR_NOP;
|
||||
|
||||
/* Setup initial state. Copy some fields to reduce indirections. */
|
||||
as->J = J;
|
||||
as->T = T;
|
||||
as->ir = T->ir;
|
||||
J->curfinal = lj_trace_alloc(J->L, T); /* This copies the IR, too. */
|
||||
as->flags = J->flags;
|
||||
as->loopref = J->loopref;
|
||||
as->realign = NULL;
|
||||
|
@ -1851,12 +2285,41 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||
as->mclim = as->mcbot + MCLIM_REDZONE;
|
||||
asm_setup_target(as);
|
||||
|
||||
do {
|
||||
/*
|
||||
** This is a loop, because the MCode may have to be (re-)assembled
|
||||
** multiple times:
|
||||
**
|
||||
** 1. as->realign is set (and the assembly aborted), if the arch-specific
|
||||
** backend wants the MCode to be aligned differently.
|
||||
**
|
||||
** This is currently only the case on x86/x64, where small loops get
|
||||
** an aligned loop body plus a short branch. Not much effort is wasted,
|
||||
** because the abort happens very quickly and only once.
|
||||
**
|
||||
** 2. The IR is immovable, since the MCode embeds pointers to various
|
||||
** constants inside the IR. But RENAMEs may need to be added to the IR
|
||||
** during assembly, which might grow and reallocate the IR. We check
|
||||
** at the end if the IR (in J->cur.ir) has actually grown, resize the
|
||||
** copy (in J->curfinal.ir) and try again.
|
||||
**
|
||||
** 95% of all traces have zero RENAMEs, 3% have one RENAME, 1.5% have
|
||||
** 2 RENAMEs and only 0.5% have more than that. That's why we opt to
|
||||
** always have one spare slot in the IR (see above), which means we
|
||||
** have to redo the assembly for only ~2% of all traces.
|
||||
**
|
||||
** Very, very rarely, this needs to be done repeatedly, since the
|
||||
** location of constants inside the IR (actually, reachability from
|
||||
** a global pointer) may affect register allocation and thus the
|
||||
** number of RENAMEs.
|
||||
*/
|
||||
for (;;) {
|
||||
as->mcp = as->mctop;
|
||||
#ifdef LUA_USE_ASSERT
|
||||
as->mcp_prev = as->mcp;
|
||||
#endif
|
||||
as->curins = T->nins;
|
||||
as->ir = J->curfinal->ir; /* Use the copied IR. */
|
||||
as->curins = J->cur.nins = as->orignins;
|
||||
|
||||
RA_DBG_START();
|
||||
RA_DBGX((as, "===== STOP ====="));
|
||||
|
||||
|
@ -1884,22 +2347,40 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||
checkmclim(as);
|
||||
asm_ir(as, ir);
|
||||
}
|
||||
} while (as->realign); /* Retry in case the MCode needs to be realigned. */
|
||||
|
||||
/* Emit head of trace. */
|
||||
RA_DBG_REF();
|
||||
checkmclim(as);
|
||||
if (as->gcsteps > 0) {
|
||||
as->curins = as->T->snap[0].ref;
|
||||
asm_snap_prep(as); /* The GC check is a guard. */
|
||||
asm_gc_check(as);
|
||||
if (as->realign && J->curfinal->nins >= T->nins)
|
||||
continue; /* Retry in case only the MCode needs to be realigned. */
|
||||
|
||||
/* Emit head of trace. */
|
||||
RA_DBG_REF();
|
||||
checkmclim(as);
|
||||
if (as->gcsteps > 0) {
|
||||
as->curins = as->T->snap[0].ref;
|
||||
asm_snap_prep(as); /* The GC check is a guard. */
|
||||
asm_gc_check(as);
|
||||
as->curins = as->stopins;
|
||||
}
|
||||
ra_evictk(as);
|
||||
if (as->parent)
|
||||
asm_head_side(as);
|
||||
else
|
||||
asm_head_root(as);
|
||||
asm_phi_fixup(as);
|
||||
|
||||
if (J->curfinal->nins >= T->nins) { /* IR didn't grow? */
|
||||
lua_assert(J->curfinal->nk == T->nk);
|
||||
memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins,
|
||||
(T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */
|
||||
T->nins = J->curfinal->nins;
|
||||
break; /* Done. */
|
||||
}
|
||||
|
||||
/* Otherwise try again with a bigger IR. */
|
||||
lj_trace_free(J2G(J), J->curfinal);
|
||||
J->curfinal = NULL; /* In case lj_trace_alloc() OOMs. */
|
||||
J->curfinal = lj_trace_alloc(J->L, T);
|
||||
as->realign = NULL;
|
||||
}
|
||||
ra_evictk(as);
|
||||
if (as->parent)
|
||||
asm_head_side(as);
|
||||
else
|
||||
asm_head_root(as);
|
||||
asm_phi_fixup(as);
|
||||
|
||||
RA_DBGX((as, "===== START ===="));
|
||||
RA_DBG_FLUSH();
|
||||
|
@ -1912,6 +2393,9 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
|
|||
if (!as->loopref)
|
||||
asm_tail_fixup(as, T->link); /* Note: this may change as->mctop! */
|
||||
T->szmcode = (MSize)((char *)as->mctop - (char *)as->mcp);
|
||||
#if LJ_TARGET_MCODE_FIXUP
|
||||
asm_mcode_fixup(T->mcode, T->szmcode);
|
||||
#endif
|
||||
lj_mcode_sync(T->mcode, origtop);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** IR assembler (SSA IR -> machine code).
|
||||
** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef _LJ_ASM_H
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue