issue #98 merge changes in master
commit
24ac6f29f3
@ -1,7 +1,6 @@
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
CTestTestfile.cmake
|
||||
|
@ -0,0 +1,3 @@
|
||||
[submodule "dmr_c"]
|
||||
path = dmr_c
|
||||
url = https://github.com/dibyendumajumdar/dmr_c.git
|
@ -0,0 +1,116 @@
|
||||
# The preferred build method for Ravi is to use CMake
|
||||
# However if you want a quick build without JIT or other options then this
|
||||
# Makefile might be adequate. It is based off the standard Lua Makefile
|
||||
#
|
||||
|
||||
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
|
||||
|
||||
# Your platform. See PLATS for possible values.
|
||||
PLAT= none
|
||||
|
||||
# Where to install. The installation starts in the src and doc directories,
|
||||
# so take care if INSTALL_TOP is not an absolute path. See the local target.
|
||||
# You may want to make INSTALL_LMOD and INSTALL_CMOD consistent with
|
||||
# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h.
|
||||
INSTALL_TOP= /usr/local
|
||||
INSTALL_BIN= $(INSTALL_TOP)/bin
|
||||
INSTALL_INC= $(INSTALL_TOP)/include/ravi
|
||||
INSTALL_LIB= $(INSTALL_TOP)/lib
|
||||
#INSTALL_MAN= $(INSTALL_TOP)/man/man1
|
||||
INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
|
||||
INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V
|
||||
|
||||
# How to install. If your install program does not support "-p", then
|
||||
# you may have to run ranlib on the installed liblua.a.
|
||||
INSTALL= install -p
|
||||
INSTALL_EXEC= $(INSTALL) -m 0755
|
||||
INSTALL_DATA= $(INSTALL) -m 0644
|
||||
#
|
||||
# If you don't have "install" you can use "cp" instead.
|
||||
# INSTALL= cp -p
|
||||
# INSTALL_EXEC= $(INSTALL)
|
||||
# INSTALL_DATA= $(INSTALL)
|
||||
|
||||
# Other utilities.
|
||||
MKDIR= mkdir -p
|
||||
RM= rm -f
|
||||
|
||||
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
|
||||
|
||||
# Convenience platforms targets.
|
||||
PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
|
||||
|
||||
# What to install.
|
||||
TO_BIN= ravi
|
||||
TO_INC= lua.h luaconf.h lualib.h lauxlib.h lua.hpp
|
||||
TO_LIB= libravinojit.a
|
||||
#TO_MAN= lua.1 luac.1
|
||||
|
||||
# Lua version and release.
|
||||
V= 5.3
|
||||
R= $V.4
|
||||
|
||||
# Targets start here.
|
||||
all: $(PLAT)
|
||||
|
||||
$(PLATS) clean:
|
||||
cd src && $(MAKE) $@
|
||||
|
||||
test: dummy
|
||||
src/ravi -v
|
||||
|
||||
install: dummy
|
||||
cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)
|
||||
cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
|
||||
cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
|
||||
cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
|
||||
# cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
|
||||
|
||||
uninstall:
|
||||
cd src && cd $(INSTALL_BIN) && $(RM) $(TO_BIN)
|
||||
cd src && cd $(INSTALL_INC) && $(RM) $(TO_INC)
|
||||
cd src && cd $(INSTALL_LIB) && $(RM) $(TO_LIB)
|
||||
# cd doc && cd $(INSTALL_MAN) && $(RM) $(TO_MAN)
|
||||
|
||||
local:
|
||||
$(MAKE) install INSTALL_TOP=../install
|
||||
|
||||
none:
|
||||
@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
|
||||
@echo " $(PLATS)"
|
||||
@echo "See doc/readme.html for complete instructions."
|
||||
|
||||
# make may get confused with test/ and install/
|
||||
dummy:
|
||||
|
||||
# echo config parameters
|
||||
echo:
|
||||
@cd src && $(MAKE) -s echo
|
||||
@echo "PLAT= $(PLAT)"
|
||||
@echo "V= $V"
|
||||
@echo "R= $R"
|
||||
@echo "TO_BIN= $(TO_BIN)"
|
||||
@echo "TO_INC= $(TO_INC)"
|
||||
@echo "TO_LIB= $(TO_LIB)"
|
||||
# @echo "TO_MAN= $(TO_MAN)"
|
||||
@echo "INSTALL_TOP= $(INSTALL_TOP)"
|
||||
@echo "INSTALL_BIN= $(INSTALL_BIN)"
|
||||
@echo "INSTALL_INC= $(INSTALL_INC)"
|
||||
@echo "INSTALL_LIB= $(INSTALL_LIB)"
|
||||
# @echo "INSTALL_MAN= $(INSTALL_MAN)"
|
||||
@echo "INSTALL_LMOD= $(INSTALL_LMOD)"
|
||||
@echo "INSTALL_CMOD= $(INSTALL_CMOD)"
|
||||
@echo "INSTALL_EXEC= $(INSTALL_EXEC)"
|
||||
@echo "INSTALL_DATA= $(INSTALL_DATA)"
|
||||
|
||||
# echo pkg-config data
|
||||
pc:
|
||||
@echo "version=$R"
|
||||
@echo "prefix=$(INSTALL_TOP)"
|
||||
@echo "libdir=$(INSTALL_LIB)"
|
||||
@echo "includedir=$(INSTALL_INC)"
|
||||
|
||||
# list targets that do not create files (but not all makes understand .PHONY)
|
||||
.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho
|
||||
|
||||
# (end of Makefile)
|
@ -1,5 +1,6 @@
|
||||
mkdir llvm64d
|
||||
cd llvm64d
|
||||
rem cmake -DCMAKE_INSTALL_PREFIX=c:\ravi64llvmd -G "Visual Studio 14 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\LLVM37debug\share\llvm\cmake ..
|
||||
cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=c:\d\ravi64llvmd -G "Visual Studio 14 Win64" -DLLVM_JIT=ON -DLLVM_DIR=c:\d\LLVM39D64\lib\cmake\llvm ..
|
||||
rem cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=c:\d\ravi64llvmd -G "Visual Studio 15 2017 Win64" -DLLVM_JIT=ON -DEMBEDDED_DMRC=ON -DLLVM_DIR=c:\d\LLVM39D64\lib\cmake\llvm ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -G "Visual Studio 15 2017 Win64" -DLTESTS=ON -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DLLVM_DIR=c:\Software\llvm501d\lib\cmake\llvm ..
|
||||
cd ..
|
@ -0,0 +1,4 @@
|
||||
mkdir asmvm
|
||||
cd asmvm
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi-asmvm -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Debug -DASM_VM=ON -G "Visual Studio 15 2017 Win64" ..
|
||||
cd ..
|
@ -1,4 +1,4 @@
|
||||
mkdir nojit64a
|
||||
cd nojit64a
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\ravi -DCMAKE_BUILD_TYPE=Debug -G "Visual Studio 15 2017 Win64" ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -DCMAKE_BUILD_TYPE=Debug -DLTESTS=ON -G "Visual Studio 15 2017 Win64" ..
|
||||
cd ..
|
@ -1,4 +1,4 @@
|
||||
mkdir nojit64
|
||||
cd nojit64
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\ravi -DCMAKE_BUILD_TYPE=Release -DSTATIC_BUILD=ON -G "Visual Studio 14 Win64" ..
|
||||
cmake -DCMAKE_INSTALL_PREFIX=c:\Software\ravi -DCMAKE_BUILD_TYPE=Debug -DSTATIC_BUILD=OFF -G "Visual Studio 15 2017 Win64" ..
|
||||
cd ..
|
@ -1,3 +1,4 @@
|
||||
mkdir xcodellvm
|
||||
cd xcodellvm
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -G Xcode -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
|
||||
#cmake -DCMAKE_BUILD_TYPE=Debug -G Xcode -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -G Xcode -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..
|
||||
|
@ -1,3 +0,0 @@
|
||||
mkdir buildgcc
|
||||
cd buildgcc
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DGCC_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi ..
|
@ -1,3 +1,5 @@
|
||||
mkdir buildllvmd
|
||||
cd buildllvmd
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
|
||||
#cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
|
||||
#cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DLTESTS=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_JIT=ON -DLTESTS=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravillvm -DLLVM_DIR=$HOME/Software/llvm600/lib/cmake/llvm ..
|
||||
|
@ -1,4 +1,4 @@
|
||||
mkdir buildllvm
|
||||
cd buildllvm
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
|
||||
#cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM39/lib/cmake/llvm ..
|
||||
#cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..
|
||||
|
@ -0,0 +1,3 @@
|
||||
mkdir buildasmvm
|
||||
cd buildasmvm
|
||||
cmake -DSTATIC_BUILD=ON -DASM_VM=ON -DCMAKE_BUILD_TYPE=Debug -DCOMPUTED_GOTO=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi ..
|
@ -0,0 +1,3 @@
|
||||
mkdir buildnojit
|
||||
cd buildnojit
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$HOME/ravi ..
|
@ -1,3 +1,4 @@
|
||||
mkdir buildnojit
|
||||
cd buildnojit
|
||||
cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$HOME/ravi ..
|
||||
#cmake -DSTATIC_BUILD=ON -DCMAKE_BUILD_TYPE=Release -DCOMPUTED_GOTO=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi ..
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCOMPUTED_GOTO=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi ..
|
||||
|
@ -1,15 +0,0 @@
|
||||
find_path(GCCJIT_INC libgccjit.h
|
||||
PATHS
|
||||
~/local/include
|
||||
/usr/local/include
|
||||
)
|
||||
|
||||
find_library(GCCJIT_LIB
|
||||
NAMES gccjit libgccjit
|
||||
PATHS
|
||||
~/local/lib
|
||||
/usr/local/lib/gcc/5
|
||||
)
|
||||
|
||||
set( GCCJIT_INCLUDE_DIRS "${GCCJIT_INC}" )
|
||||
set( GCCJIT_LIBRARIES "${GCCJIT_LIB}" )
|
@ -0,0 +1 @@
|
||||
Subproject commit 5b42a99121627677952d4cf3445d795be85582de
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
** Target architecture selection.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef RAVI_ARCH_H
|
||||
#define RAVI_ARCH_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
/* Target endianess. */
|
||||
#define RAVI__ARCH_LE 0
|
||||
#define RAVI__ARCH_BE 1
|
||||
|
||||
/* Target architectures. */
|
||||
#define RAVI__ARCH_X86 1
|
||||
#define RAVI__ARCH_x86 1
|
||||
#define RAVI__ARCH_X64 2
|
||||
#define RAVI__ARCH_x64 2
|
||||
#define RAVI__ARCH_ARM 3
|
||||
#define RAVI__ARCH_arm 3
|
||||
#define RAVI__ARCH_ARM64 4
|
||||
#define RAVI__ARCH_arm64 4
|
||||
#define RAVI__ARCH_PPC 5
|
||||
#define RAVI__ARCH_ppc 5
|
||||
#define RAVI__ARCH_MIPS 6
|
||||
#define RAVI__ARCH_mips 6
|
||||
#define RAVI__ARCH_MIPS32 6
|
||||
#define RAVI__ARCH_mips32 6
|
||||
#define RAVI__ARCH_MIPS64 7
|
||||
#define RAVI__ARCH_mips64 7
|
||||
|
||||
/* Target OS. */
|
||||
#define RAVI__OS_OTHER 0
|
||||
#define RAVI__OS_WINDOWS 1
|
||||
#define RAVI__OS_LINUX 2
|
||||
#define RAVI__OS_OSX 3
|
||||
#define RAVI__OS_BSD 4
|
||||
#define RAVI__OS_POSIX 5
|
||||
|
||||
/* Select native target if no target defined. */
|
||||
#ifndef RAVI__TARGET
|
||||
#if defined(__i386) || defined(__i386__) || defined(_M_IX86)
|
||||
#error "No support for this architecture (yet)"
|
||||
#define RAVI__TARGET RAVI__ARCH_X86
|
||||
#elif defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
|
||||
#define RAVI__TARGET RAVI__ARCH_X64
|
||||
#elif defined(__arm__) || defined(__arm) || defined(__ARM__) || defined(__ARM)
|
||||
#error "No support for this architecture (yet)"
|
||||
#define RAVI__TARGET RAVI__ARCH_ARM
|
||||
#elif defined(__aarch64__)
|
||||
#error "No support for this architecture (yet)"
|
||||
#define RAVI__TARGET RAVI__ARCH_ARM64
|
||||
#elif defined(__ppc__) || defined(__ppc) || defined(__PPC__) || defined(__PPC) || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) || defined(__POWERPC) || defined(_M_PPC)
|
||||
#error "No support for this architecture (yet)"
|
||||
#define RAVI__TARGET RAVI__ARCH_PPC
|
||||
#elif defined(__mips64__) || defined(__mips64) || defined(__MIPS64__) || defined(__MIPS64)
|
||||
#error "No support for this architecture (yet)"
|
||||
#define RAVI__TARGET RAVI__ARCH_MIPS64
|
||||
#elif defined(__mips__) || defined(__mips) || defined(__MIPS__) || defined(__MIPS)
|
||||
#error "No support for this architecture (yet)"
|
||||
#define RAVI__TARGET RAVI__ARCH_MIPS32
|
||||
#else
|
||||
#error "No support for this architecture (yet)"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Select native OS if no target OS defined. */
|
||||
#ifndef RAVI__OS
|
||||
#if defined(_WIN32) && !defined(_XBOX_VER)
|
||||
#define RAVI__OS RAVI__OS_WINDOWS
|
||||
#elif defined(__linux__)
|
||||
#define RAVI__OS RAVI__OS_LINUX
|
||||
#elif defined(__MACH__) && defined(__APPLE__)
|
||||
#define RAVI__OS RAVI__OS_OSX
|
||||
#elif (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
|
||||
defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__DragonFly__)) && !defined(__ORBIS__)
|
||||
#define RAVI__OS RAVI__OS_BSD
|
||||
#elif (defined(__sun__) && defined(__svr4__)) || defined(__HAIKU__)
|
||||
#define RAVI__OS RAVI__OS_POSIX
|
||||
#elif defined(__CYGWIN__)
|
||||
#define RAVI_TARGET_CYGWIN 1
|
||||
#define RAVI__OS RAVI__OS_POSIX
|
||||
#else
|
||||
#define RAVI__OS RAVI__OS_OTHER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Set target OS properties. */
|
||||
#if RAVI__OS == RAVI__OS_WINDOWS
|
||||
#define RAVI_OS_NAME "Windows"
|
||||
#elif RAVI__OS == RAVI__OS_LINUX
|
||||
#define RAVI_OS_NAME "Linux"
|
||||
#elif RAVI__OS == RAVI__OS_OSX
|
||||
#define RAVI_OS_NAME "OSX"
|
||||
#elif RAVI__OS == RAVI__OS_BSD
|
||||
#define RAVI_OS_NAME "BSD"
|
||||
#elif RAVI__OS == RAVI__OS_POSIX
|
||||
#define RAVI_OS_NAME "POSIX"
|
||||
#else
|
||||
#define RAVI_OS_NAME "Other"
|
||||
#endif
|
||||
|
||||
#define RAVI_TARGET_WINDOWS (RAVI__OS == RAVI__OS_WINDOWS)
|
||||
#define RAVI_TARGET_LINUX (RAVI__OS == RAVI__OS_LINUX)
|
||||
#define RAVI_TARGET_OSX (RAVI__OS == RAVI__OS_OSX)
|
||||
#define RAVI_TARGET_IOS (RAVI_TARGET_OSX && (RAVI__TARGET == RAVI__ARCH_ARM || RAVI__TARGET == RAVI__ARCH_ARM64))
|
||||
#define RAVI_TARGET_POSIX (RAVI__OS > RAVI__OS_WINDOWS)
|
||||
#define RAVI_TARGET_DLOPEN RAVI_TARGET_POSIX
|
||||
|
||||
/* Set target architecture properties. */
|
||||
#if RAVI__TARGET == RAVI__ARCH_X86
|
||||
|
||||
#define RAVI_ARCH_NAME "x86"
|
||||
#define RAVI_ARCH_BITS 32
|
||||
#define RAVI_ARCH_ENDIAN RAVI__ARCH_LE
|
||||
#if RAVI_TARGET_WINDOWS || RAVI_TARGET_CYGWIN
|
||||
#define RAVI_ABI_WIN 1
|
||||
#else
|
||||
#define RAVI_ABI_WIN 0
|
||||
#endif
|
||||
#define RAVI_TARGET_X86 1
|
||||
#define RAVI_TARGET_X86ORX64 1
|
||||
#define RAVI_TARGET_EHRETREG 0
|
||||
#define RAVI_TARGET_MASKSHIFT 1
|
||||
#define RAVI_TARGET_MASKROT 1
|
||||
#define RAVI_TARGET_UNALIGNED 1
|
||||
|
||||
#elif RAVI__TARGET == RAVI__ARCH_X64
|
||||
|
||||
#define RAVI_ARCH_NAME "x64"
|
||||
#define RAVI_ARCH_BITS 64
|
||||
#define RAVI_ARCH_ENDIAN RAVI__ARCH_LE
|
||||
#if RAVI_TARGET_WINDOWS || RAVI_TARGET_CYGWIN
|
||||
#define RAVI_ABI_WIN 1
|
||||
#else
|
||||
#define RAVI_ABI_WIN 0
|
||||
#endif
|
||||
#define RAVI_TARGET_X64 1
|
||||
#define RAVI_TARGET_X86ORX64 1
|
||||
#define RAVI_TARGET_EHRETREG 0
|
||||
#define RAVI_TARGET_JUMPRANGE 31 /* +-2^31 = +-2GB */
|
||||
#define RAVI_TARGET_MASKSHIFT 1
|
||||
#define RAVI_TARGET_MASKROT 1
|
||||
#define RAVI_TARGET_UNALIGNED 1
|
||||
|
||||
#else
|
||||
#error "No target architecture defined"
|
||||
#endif
|
||||
|
||||
#ifndef RAVI_PAGESIZE
|
||||
#define RAVI_PAGESIZE 4096
|
||||
#endif
|
||||
|
||||
#if RAVI_ARCH_ENDIAN == RAVI__ARCH_BE
|
||||
#define RAVI_LE 0
|
||||
#define RAVI_BE 1
|
||||
#define RAVI_ENDIAN_SELECT(le, be) be
|
||||
#define RAVI_ENDIAN_LOHI(lo, hi) hi lo
|
||||
#else
|
||||
#define RAVI_LE 1
|
||||
#define RAVI_BE 0
|
||||
#define RAVI_ENDIAN_SELECT(le, be) le
|
||||
#define RAVI_ENDIAN_LOHI(lo, hi) lo hi
|
||||
#endif
|
||||
|
||||
#if RAVI_ARCH_BITS == 32
|
||||
#define RAVI_32 1
|
||||
#define RAVI_64 0
|
||||
#else
|
||||
#define RAVI_32 0
|
||||
#define RAVI_64 1
|
||||
#endif
|
||||
|
||||
#ifndef RAVI_TARGET_UNALIGNED
|
||||
#define RAVI_TARGET_UNALIGNED 0
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
** LuaJIT common internal definitions.
|
||||
** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
|
||||
*/
|
||||
|
||||
#ifndef RAVI_DEF_H
|
||||
#define RAVI_DEF_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Needed everywhere. */
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Various macros. */
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) ((void)(x)) /* to avoid warnings */
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,776 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef RAVI_RAVI_GCCJIT_H
|
||||
#define RAVI_RAVI_GCCJIT_H
|
||||
|
||||
#ifdef USE_GCCJIT
|
||||
#include <libgccjit.h>
|
||||
#include "ravijit.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// TODO we probably do not need all the headers
|
||||
// below
|
||||
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lfunc.h"
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
#include "lstate.h"
|
||||
#include "lstring.h"
|
||||
#include "ltable.h"
|
||||
#include "lvm.h"
|
||||
|
||||
typedef enum {
|
||||
LUA__TNIL = LUA_TNIL,
|
||||
LUA__TBOOLEAN = LUA_TBOOLEAN,
|
||||
LUA__TLIGHTUSERDATA = LUA_TLIGHTUSERDATA,
|
||||
LUA__TNUMBER = LUA_TNUMBER,
|
||||
LUA__TSTRING = ctb(LUA_TSTRING),
|
||||
LUA__TTABLE = ctb(LUA_TTABLE),
|
||||
RAVI__TLTABLE = ctb(LUA_TTABLE),
|
||||
RAVI__TIARRAY = ctb(RAVI_TIARRAY),
|
||||
RAVI__TFARRAY = ctb(RAVI_TFARRAY),
|
||||
LUA__TFUNCTION = ctb(LUA_TFUNCTION),
|
||||
LUA__TUSERDATA = ctb(LUA_TUSERDATA),
|
||||
LUA__TTHREAD = ctb(LUA_TTHREAD),
|
||||
LUA__TLCL = ctb(LUA_TLCL),
|
||||
LUA__TLCF = LUA_TLCF,
|
||||
LUA__TCCL = ctb(LUA_TCCL),
|
||||
LUA__TSHRSTR = ctb(LUA_TSHRSTR),
|
||||
LUA__TLNGSTR = ctb(LUA_TLNGSTR),
|
||||
LUA__TNUMFLT = LUA_TNUMFLT,
|
||||
LUA__TNUMINT = LUA_TNUMINT
|
||||
} lua_typecode_t;
|
||||
|
||||
typedef struct ravi_gcc_context_t ravi_gcc_context_t;
|
||||
typedef struct ravi_gcc_types_t ravi_gcc_types_t;
|
||||
typedef struct ravi_gcc_codegen_t ravi_gcc_codegen_t;
|
||||
|
||||
struct ravi_State {
|
||||
ravi_gcc_context_t *jit;
|
||||
ravi_gcc_codegen_t *code_generator;
|
||||
};
|
||||
|
||||
struct ravi_gcc_types_t {
|
||||
|
||||
gcc_jit_type *C_boolT;
|
||||
gcc_jit_type *C_doubleT;
|
||||
gcc_jit_type *C_intptr_t;
|
||||
gcc_jit_type *C_size_t;
|
||||
gcc_jit_type *C_ptrdiff_t;
|
||||
gcc_jit_type *C_int64_t;
|
||||
gcc_jit_type *C_shortT;
|
||||
gcc_jit_type *C_unsigned_shortT;
|
||||
gcc_jit_type *C_voidT;
|
||||
gcc_jit_type *C_pvoidT;
|
||||
|
||||
gcc_jit_type *lua_NumberT;
|
||||
gcc_jit_type *plua_NumberT;
|
||||
gcc_jit_type *pplua_NumberT;
|
||||
|
||||
gcc_jit_type *lua_IntegerT;
|
||||
gcc_jit_type *plua_IntegerT;
|
||||
gcc_jit_type *pplua_IntegerT;
|
||||
// gcc_jit_type *clua_IntegerT;
|
||||
|
||||
gcc_jit_type *lua_UnsignedT;
|
||||
gcc_jit_type *lua_KContextT;
|
||||
|
||||
// gcc_jit_function *lua_CFunctionT;
|
||||
gcc_jit_type *plua_CFunctionT;
|
||||
|
||||
// gcc_jit_function *lua_KFunctionT;
|
||||
gcc_jit_type *plua_KFunctionT;
|
||||
|
||||
// gcc_jit_function *lua_HookT;
|
||||
gcc_jit_type *plua_HookT;
|
||||
|
||||
// gcc_jit_function *lua_AllocT;
|
||||
gcc_jit_type *plua_AllocT;
|
||||
|
||||
gcc_jit_type *l_memT;
|
||||
gcc_jit_type *lu_memT;
|
||||
|
||||
gcc_jit_type *tmsT;
|
||||
|
||||
gcc_jit_type *lu_byteT;
|
||||
gcc_jit_type *L_UmaxalignT;
|
||||
gcc_jit_type *C_charT;
|
||||
gcc_jit_type *C_pcharT;
|
||||
gcc_jit_type *C_pconstcharT;
|
||||
|
||||
gcc_jit_type *C_intT;
|
||||
gcc_jit_type *C_pintT;
|
||||
gcc_jit_type *C_unsigned_intT;
|
||||
|
||||
gcc_jit_struct *lua_StateT;
|
||||
gcc_jit_type *plua_StateT;
|
||||
|
||||
gcc_jit_field *lua_State_ci;
|
||||
gcc_jit_field *lua_State_top;
|
||||
|
||||
gcc_jit_struct *global_StateT;
|
||||
gcc_jit_type *pglobal_StateT;
|
||||
|
||||
gcc_jit_struct *ravi_StateT;
|
||||
gcc_jit_type *pravi_StateT;
|
||||
|
||||
gcc_jit_struct *GCObjectT;
|
||||
gcc_jit_type *pGCObjectT;
|
||||
|
||||
gcc_jit_type *ValueT;
|
||||
gcc_jit_struct *TValueT;
|
||||
gcc_jit_type *cTValueT;
|
||||
gcc_jit_type *pTValueT;
|
||||
gcc_jit_type *pcTValueT;
|
||||
|
||||
gcc_jit_field *Value_value;
|
||||
gcc_jit_field *Value_value_gc;
|
||||
gcc_jit_field *Value_value_n;
|
||||
gcc_jit_field *Value_value_i;
|
||||
gcc_jit_field *Value_value_b;
|
||||
gcc_jit_field *Value_tt;
|
||||
|
||||
gcc_jit_struct *TStringT;
|
||||
gcc_jit_type *pTStringT;
|
||||
gcc_jit_type *ppTStringT;
|
||||
|
||||
gcc_jit_struct *UdataT;
|
||||
gcc_jit_struct *RaviArrayT;
|
||||
gcc_jit_field *RaviArray_len;
|
||||
gcc_jit_field *RaviArray_data;
|
||||
gcc_jit_field *RaviArray_array_type;
|
||||
|
||||
gcc_jit_struct *TableT;
|
||||
gcc_jit_type *pTableT;
|
||||
gcc_jit_type *ppTableT;
|
||||
gcc_jit_field *Table_ravi_array;
|
||||
|
||||
gcc_jit_struct *UpvaldescT;
|
||||
gcc_jit_type *pUpvaldescT;
|
||||
|
||||
gcc_jit_type *ravitype_tT;
|
||||
gcc_jit_struct *LocVarT;
|
||||
gcc_jit_type *pLocVarT;
|
||||
|
||||
gcc_jit_type *InstructionT;
|
||||
gcc_jit_type *pInstructionT;
|
||||
gcc_jit_struct *LClosureT;
|
||||
gcc_jit_type *pLClosureT;
|
||||
gcc_jit_type *ppLClosureT;
|
||||
gcc_jit_type *pppLClosureT;
|
||||
gcc_jit_type *ClosureT;
|
||||
gcc_jit_type *pClosureT;
|
||||
|
||||
gcc_jit_field *LClosure_p;
|
||||
gcc_jit_field *LClosure_p_k;
|
||||
gcc_jit_field *LClosure_upvals;
|
||||
|
||||
gcc_jit_struct *RaviJITProtoT;
|
||||
|
||||
gcc_jit_struct *ProtoT;
|
||||
gcc_jit_type *pProtoT;
|
||||
gcc_jit_type *ppProtoT;
|
||||
|
||||
gcc_jit_field *Proto_sizep;
|
||||
|
||||
gcc_jit_struct *UpValT;
|
||||
gcc_jit_type *pUpValT;
|
||||
gcc_jit_struct *UpVal_u_openT;
|
||||
gcc_jit_type *UpVal_uT;
|
||||
|
||||
gcc_jit_field *UpVal_v;
|
||||
gcc_jit_field *UpVal_u;
|
||||
gcc_jit_field *UpVal_u_value;
|
||||
|
||||
gcc_jit_struct *CClosureT;
|
||||
gcc_jit_type *pCClosureT;
|
||||
|
||||
gcc_jit_type *TKeyT;
|
||||
gcc_jit_type *pTKeyT;
|
||||
|
||||
gcc_jit_struct *NodeT;
|
||||
gcc_jit_type *pNodeT;
|
||||
|
||||
gcc_jit_struct *lua_DebugT;
|
||||
gcc_jit_type *plua_DebugT;
|
||||
|
||||
gcc_jit_struct *lua_longjumpT;
|
||||
gcc_jit_type *plua_longjumpT;
|
||||
|
||||
gcc_jit_struct *MbufferT;
|
||||
gcc_jit_struct *stringtableT;
|
||||
|
||||
gcc_jit_type *StkIdT;
|
||||
|
||||
gcc_jit_struct *CallInfoT;
|
||||
gcc_jit_struct *CallInfo_cT;
|
||||
gcc_jit_struct *CallInfo_lT;
|
||||
gcc_jit_type *CallInfo_uT;
|
||||
gcc_jit_type *pCallInfoT;
|
||||
|
||||
gcc_jit_field *CallInfo_func;
|
||||
gcc_jit_field *CallInfo_top;
|
||||
gcc_jit_field *CallInfo_u;
|
||||
gcc_jit_field *CallInfo_u_l;
|
||||
gcc_jit_field *CallInfo_u_l_base;
|
||||
|
||||
gcc_jit_function *jitFunctionT;
|
||||
|
||||
gcc_jit_function *luaD_poscallT;
|
||||
gcc_jit_function *luaD_precallT;
|
||||
gcc_jit_function *luaD_callT;
|
||||
gcc_jit_function *luaF_closeT;
|
||||
gcc_jit_function *luaT_trybinTMT;
|
||||
gcc_jit_function *luaG_runerrorT;
|
||||
gcc_jit_function *luaV_equalobjT;
|
||||
gcc_jit_function *luaV_lessthanT;
|
||||
gcc_jit_function *luaV_lessequalT;
|
||||
gcc_jit_function *luaV_forlimitT;
|
||||
gcc_jit_function *luaV_tonumberT;
|
||||
gcc_jit_function *luaV_tointegerT;
|
||||
gcc_jit_function *luaV_modT;
|
||||
gcc_jit_function *luaV_objlenT;
|
||||
gcc_jit_function *luaV_divT;
|
||||
gcc_jit_function *luaC_upvalbarrierT;
|
||||
|
||||
gcc_jit_function *luaV_executeT;
|
||||
gcc_jit_function *luaV_gettableT;
|
||||
gcc_jit_function *luaV_settableT;
|
||||
|
||||
// Following are functions that handle specific bytecodes
|
||||
// We cheat for these bytecodes by calling the function that
|
||||
// implements it
|
||||
gcc_jit_function *raviV_op_newarrayintT;
|
||||
gcc_jit_function *raviV_op_newarrayfloatT;
|
||||
gcc_jit_function *raviV_op_setlistT;
|
||||
gcc_jit_function *raviV_op_newtableT;
|
||||
gcc_jit_function *raviV_op_loadnilT;
|
||||
gcc_jit_function *raviV_op_concatT;
|
||||
gcc_jit_function *raviV_op_closureT;
|
||||
gcc_jit_function *raviV_op_varargT;
|
||||
gcc_jit_function *raviV_op_setupvalT;
|
||||
|
||||
gcc_jit_function *raviH_set_intT;
|
||||
gcc_jit_function *raviH_set_floatT;
|
||||
|
||||
gcc_jit_function *printfT;
|
||||
};
|
||||
|
||||
struct ravi_gcc_context_t {
|
||||
|
||||
/* parent JIT context - all functions are child contexts
|
||||
* of this.
|
||||
*/
|
||||
gcc_jit_context *context;
|
||||
|
||||
gcc_jit_result *parent_result_;
|
||||
|
||||
/* Lua type definitions */
|
||||
ravi_gcc_types_t *types;
|
||||
|
||||
/* Should we auto compile what we can? */
|
||||
bool auto_;
|
||||
|
||||
/* Is JIT enabled */
|
||||
bool enabled_;
|
||||
|
||||
/* Optimizer level */
|
||||
int opt_level_;
|
||||
|
||||
/* Size level */
|
||||
int size_level_;
|
||||
|
||||
/* min code size for compilation */
|
||||
int min_code_size_;
|
||||
|
||||
/* min execution count for compilation */
|
||||
int min_exec_count_;
|
||||
};
|
||||
|
||||
struct ravi_gcc_codegen_t {
|
||||
|
||||
ravi_gcc_context_t *ravi;
|
||||
|
||||
char temp[31];
|
||||
|
||||
int id;
|
||||
};
|
||||
|
||||
// struct ravi_gcc_function_t {
|
||||
//
|
||||
// gcc_jit_result *jit_result;
|
||||
//
|
||||
//};
|
||||
|
||||
typedef struct ravi_branch_def_t {
|
||||
// this field is used for all branches
|
||||
gcc_jit_block *jmp;
|
||||
|
||||
// These are local variables for a fornum
|
||||
// loop
|
||||
gcc_jit_lvalue *ilimit;
|
||||
gcc_jit_lvalue *istep;
|
||||
gcc_jit_lvalue *iidx;
|
||||
gcc_jit_lvalue *flimit;
|
||||
gcc_jit_lvalue *fstep;
|
||||
gcc_jit_lvalue *fidx;
|
||||
|
||||
} ravi_branch_def_t;
|
||||
|
||||
typedef struct ravi_function_def_t {
|
||||
|
||||
ravi_gcc_context_t *ravi;
|
||||
|
||||
Proto *p;
|
||||
|
||||
char name[31];
|
||||
|
||||
/* Child context for the function being compiled */
|
||||
gcc_jit_context *function_context;
|
||||
|
||||
gcc_jit_param *L;
|
||||
|
||||
gcc_jit_function *jit_function;
|
||||
|
||||
gcc_jit_block *entry_block;
|
||||
|
||||
struct ravi_branch_def_t **jmp_targets;
|
||||
|
||||
/* Currently compiled function's stack frame L->ci */
|
||||
gcc_jit_lvalue *ci_val;
|
||||
|
||||
/* Currently compiled function's stack value L->ci->func
|
||||
* type is LClosure *
|
||||
*/
|
||||
gcc_jit_rvalue *lua_closure;
|
||||
gcc_jit_lvalue *lua_closure_val;
|
||||
|
||||
gcc_jit_lvalue *kOne_luaInteger;
|
||||
|
||||
gcc_jit_block *current_block;
|
||||
|
||||
bool current_block_terminated;
|
||||
|
||||
/* The Lua stack base - this can change during execution so needs to be lvalue
|
||||
*/
|
||||
gcc_jit_rvalue *base_ref;
|
||||
// gcc_jit_lvalue *base;
|
||||
|
||||
/* Reference to lua_closure->p - never changes */
|
||||
gcc_jit_rvalue *proto;
|
||||
|
||||
/* The Lua constants list for the function - this never changes */
|
||||
gcc_jit_rvalue *k;
|
||||
|
||||
/* temporary buffer for creating unique names */
|
||||
char buf[80];
|
||||
|
||||
/* counter used for creating unique names */
|
||||
unsigned int counter;
|
||||
|
||||
int dump_ir;
|
||||
int dump_asm;
|
||||
int opt_level;
|
||||
|
||||
} ravi_function_def_t;
|
||||
|
||||
/* Create a new context */
|
||||
extern ravi_gcc_context_t *ravi_jit_new_context(void);
|
||||
|
||||
/* Destroy a context */
|
||||
extern void ravi_jit_context_free(ravi_gcc_context_t *);
|
||||
|
||||
/* Setup Lua types */
|
||||
extern bool ravi_setup_lua_types(ravi_gcc_context_t *);
|
||||
|
||||
extern ravi_gcc_codegen_t *
|
||||
ravi_jit_new_codegen(ravi_gcc_context_t *global_context);
|
||||
|
||||
extern void ravi_jit_codegen_free(ravi_gcc_codegen_t *);
|
||||
|
||||
extern bool ravi_jit_has_errored(ravi_gcc_context_t *);
|
||||
|
||||
extern void ravi_emit_load_base(ravi_function_def_t *def);
|
||||
|
||||
extern gcc_jit_lvalue *ravi_emit_get_register(ravi_function_def_t *def, int A);
|
||||
|
||||
extern gcc_jit_lvalue *ravi_emit_get_constant(ravi_function_def_t *def, int Bx);
|
||||
|
||||
extern gcc_jit_lvalue *
|
||||
ravi_emit_get_register_or_constant(ravi_function_def_t *def, int B);
|
||||
|
||||
extern void ravi_emit_set_L_top_toreg(ravi_function_def_t *def, int B);
|
||||
|
||||
extern void ravi_emit_refresh_L_top(ravi_function_def_t *def);
|
||||
|
||||
extern gcc_jit_lvalue *ravi_emit_get_Proto_sizep(ravi_function_def_t *def);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_emit_get_upvals(ravi_function_def_t *def,
|
||||
int offset);
|
||||
// Get upval->v
|
||||
extern gcc_jit_lvalue *ravi_emit_load_upval_v(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *pupval);
|
||||
|
||||
// Get upval->u.value
|
||||
extern gcc_jit_lvalue *ravi_emit_load_upval_value(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *pupval);
|
||||
|
||||
extern void ravi_set_current_block(ravi_function_def_t *def,
|
||||
gcc_jit_block *block);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_function_call1_rvalue(ravi_function_def_t *def,
|
||||
gcc_jit_function *f,
|
||||
gcc_jit_rvalue *arg1);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_function_call2_rvalue(ravi_function_def_t *def,
|
||||
gcc_jit_function *f,
|
||||
gcc_jit_rvalue *arg1,
|
||||
gcc_jit_rvalue *arg2);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_function_call3_rvalue(ravi_function_def_t *def,
|
||||
gcc_jit_function *f,
|
||||
gcc_jit_rvalue *arg1,
|
||||
gcc_jit_rvalue *arg2,
|
||||
gcc_jit_rvalue *arg3);
|
||||
|
||||
extern gcc_jit_rvalue *
|
||||
ravi_function_call4_rvalue(ravi_function_def_t *def, gcc_jit_function *f,
|
||||
gcc_jit_rvalue *arg1, gcc_jit_rvalue *arg2,
|
||||
gcc_jit_rvalue *arg3, gcc_jit_rvalue *arg4);
|
||||
|
||||
extern gcc_jit_rvalue *
|
||||
ravi_function_call5_rvalue(ravi_function_def_t *def, gcc_jit_function *f,
|
||||
gcc_jit_rvalue *arg1, gcc_jit_rvalue *arg2,
|
||||
gcc_jit_rvalue *arg3, gcc_jit_rvalue *arg4,
|
||||
gcc_jit_rvalue *arg5);
|
||||
|
||||
extern const char *unique_name(ravi_function_def_t *def, const char *prefix,
|
||||
int pc);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_emit_num_stack_elements(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *ra);
|
||||
|
||||
extern void ravi_emit_struct_assign(ravi_function_def_t *def,
|
||||
gcc_jit_lvalue *reg_dest,
|
||||
gcc_jit_lvalue *reg_src);
|
||||
|
||||
/* Store an integer value and set type to TNUMINT */
|
||||
extern gcc_jit_lvalue *ravi_emit_load_reg_i(ravi_function_def_t *def,
|
||||
gcc_jit_lvalue *reg);
|
||||
|
||||
/* Store a number value and set type to TNUMFLT */
|
||||
extern gcc_jit_lvalue *ravi_emit_load_reg_n(ravi_function_def_t *def,
|
||||
gcc_jit_lvalue *reg);
|
||||
|
||||
/* Get TValue->value_.b */
|
||||
extern gcc_jit_lvalue *ravi_emit_load_reg_b(ravi_function_def_t *def,
|
||||
gcc_jit_lvalue *reg);
|
||||
|
||||
extern gcc_jit_lvalue *ravi_emit_load_type(ravi_function_def_t *def,
|
||||
gcc_jit_lvalue *reg);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_emit_is_value_of_type(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *value_type,
|
||||
int lua_type);
|
||||
|
||||
extern gcc_jit_rvalue *
|
||||
ravi_emit_is_not_value_of_type(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *value_type, int lua_type);
|
||||
|
||||
extern gcc_jit_rvalue *
|
||||
ravi_emit_is_not_value_of_type_class(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *value_type, int lua_type);
|
||||
|
||||
extern void ravi_emit_store_reg_i_withtype(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *ivalue,
|
||||
gcc_jit_lvalue *reg);
|
||||
|
||||
extern void ravi_emit_store_reg_n_withtype(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *nvalue,
|
||||
gcc_jit_lvalue *reg);
|
||||
|
||||
extern void ravi_emit_store_reg_b_withtype(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *bvalue,
|
||||
gcc_jit_lvalue *reg);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_emit_load_reg_h(ravi_function_def_t *def,
|
||||
gcc_jit_lvalue *reg);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_emit_load_reg_h_floatarray(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *h);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_emit_load_reg_h_intarray(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *h);
|
||||
|
||||
extern gcc_jit_lvalue *ravi_emit_load_ravi_arraylength(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *h);
|
||||
|
||||
extern gcc_jit_lvalue *ravi_emit_load_ravi_arraytype(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *h);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_emit_array_get(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *ptr,
|
||||
gcc_jit_rvalue *index);
|
||||
|
||||
extern gcc_jit_lvalue *ravi_emit_array_get_ptr(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *ptr,
|
||||
gcc_jit_rvalue *index);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_emit_comparison(ravi_function_def_t *def,
|
||||
enum gcc_jit_comparison op,
|
||||
gcc_jit_rvalue *a,
|
||||
gcc_jit_rvalue *b);
|
||||
|
||||
extern gcc_jit_lvalue *ravi_emit_tonumtype(ravi_function_def_t *def,
|
||||
gcc_jit_lvalue *reg,
|
||||
lua_typecode_t tt, int pc);
|
||||
|
||||
extern void ravi_emit_conditional_branch(ravi_function_def_t *def,
|
||||
gcc_jit_rvalue *cond,
|
||||
gcc_jit_block *true_block,
|
||||
gcc_jit_block *false_block);
|
||||
|
||||
extern void ravi_emit_branch(ravi_function_def_t *def,
|
||||
gcc_jit_block *target_block);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_emit_boolean_testfalse(ravi_function_def_t *def,
|
||||
gcc_jit_lvalue *reg,
|
||||
bool negate);
|
||||
|
||||
extern void ravi_emit_raise_lua_error(ravi_function_def_t *def,
|
||||
const char *msg);
|
||||
|
||||
extern void ravi_emit_RETURN(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_LOADK(ravi_function_def_t *def, int A, int Bx, int pc);
|
||||
|
||||
extern void ravi_emit_iFORPREP(ravi_function_def_t *def, int A, int pc,
|
||||
int step_one);
|
||||
|
||||
extern void ravi_emit_iFORLOOP(ravi_function_def_t *def, int A, int pc,
|
||||
ravi_branch_def_t *b, int step_one);
|
||||
|
||||
extern void ravi_emit_MOVE(ravi_function_def_t *def, int A, int B);
|
||||
|
||||
extern void ravi_emit_MOVEI(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_MOVEF(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_LOADNIL(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_LOADFZ(ravi_function_def_t *def, int A, int pc);
|
||||
|
||||
extern void ravi_emit_LOADIZ(ravi_function_def_t *def, int A, int pc);
|
||||
|
||||
extern void ravi_emit_LOADBOOL(ravi_function_def_t *def, int A, int B, int C,
|
||||
int j, int pc);
|
||||
|
||||
// implements EQ, LE and LT - by using the supplied lua function to call.
|
||||
extern void ravi_emit_EQ_LE_LT(ravi_function_def_t *def, int A, int B, int C,
|
||||
int j, int jA, gcc_jit_function *callee,
|
||||
const char *opname, OpCode op, int pc);
|
||||
|
||||
extern void ravi_emit_JMP(ravi_function_def_t *def, int A, int j, int pc);
|
||||
|
||||
// Handle OP_CALL
|
||||
extern void ravi_emit_CALL(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_GETTABUP(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_SETTABUP(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_SETUPVAL(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_GETUPVAL(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_TEST(ravi_function_def_t *def, int A, int B, int C, int j,
|
||||
int jA, int pc);
|
||||
|
||||
extern void ravi_emit_TESTSET(ravi_function_def_t *def, int A, int B, int C,
|
||||
int j, int jA, int pc);
|
||||
|
||||
extern void ravi_emit_NOT(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_TOFLT(ravi_function_def_t *def, int A, int pc);
|
||||
|
||||
extern void ravi_emit_TOINT(ravi_function_def_t *def, int A, int pc);
|
||||
|
||||
extern void ravi_emit_CONCAT(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_CLOSURE(ravi_function_def_t *def, int A, int Bx, int pc);
|
||||
|
||||
extern void ravi_emit_VARARG(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_UNMF(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_UNMI(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_ADDFF(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_ADDFI(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_ADDII(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_SUBFF(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_SUBFI(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_SUBIF(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_SUBII(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_DIVFF(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_DIVFI(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_DIVIF(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_DIVII(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_MULFF(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_MULFI(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_MULII(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_SELF(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_LEN(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_SETTABLE(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_GETTABLE(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_NEWTABLE(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_SETLIST(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_TFORCALL(ravi_function_def_t *def, int A, int B, int C,
|
||||
int j, int jA, int pc);
|
||||
|
||||
extern void ravi_emit_TFORLOOP(ravi_function_def_t *def, int A, int j, int pc);
|
||||
|
||||
extern void ravi_emit_GETTABLE_AI(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc, bool omitArrayGetRangeCheck);
|
||||
|
||||
extern void ravi_emit_GETTABLE_AF(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc, bool omitArrayGetRangeCheck);
|
||||
|
||||
extern void ravi_emit_NEWARRAYFLOAT(ravi_function_def_t *def, int A, int pc);
|
||||
|
||||
extern void ravi_emit_NEWARRAYINT(ravi_function_def_t *def, int A, int pc);
|
||||
|
||||
extern void ravi_emit_TOARRAY(ravi_function_def_t *def, int A,
|
||||
int array_type_expected, const char *errmsg,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_MOVEAI(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_MOVEAF(ravi_function_def_t *def, int A, int B, int pc);
|
||||
|
||||
extern void ravi_emit_SETTABLE_AI_AF(ravi_function_def_t *def, int A, int B,
|
||||
int C, bool known_tt, lua_typecode_t tt,
|
||||
int pc);
|
||||
|
||||
extern void ravi_emit_ARITH(ravi_function_def_t *def, int A, int B, int C,
|
||||
OpCode op, TMS tms, int pc);
|
||||
|
||||
extern void ravi_dump_rvalue(gcc_jit_rvalue *rv);
|
||||
|
||||
extern void ravi_dump_lvalue(gcc_jit_lvalue *lv);
|
||||
|
||||
extern void ravi_debug_printf(ravi_function_def_t *def, const char *str);
|
||||
|
||||
extern void ravi_debug_printf1(ravi_function_def_t *def, const char *str,
|
||||
gcc_jit_rvalue *arg1);
|
||||
|
||||
extern void ravi_debug_printf2(ravi_function_def_t *def, const char *str,
|
||||
gcc_jit_rvalue *arg1, gcc_jit_rvalue *arg2);
|
||||
|
||||
extern void ravi_debug_printf3(ravi_function_def_t *def, const char *str,
|
||||
gcc_jit_rvalue *arg1, gcc_jit_rvalue *arg2,
|
||||
gcc_jit_rvalue *arg3);
|
||||
|
||||
extern void ravi_debug_printf4(ravi_function_def_t *def, const char *str,
|
||||
gcc_jit_rvalue *arg1, gcc_jit_rvalue *arg2,
|
||||
gcc_jit_rvalue *arg3, gcc_jit_rvalue *arg4);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_int_constant(ravi_function_def_t *def, int value);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_bool_constant(ravi_function_def_t *def, int value);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_lua_Integer_constant(ravi_function_def_t *def,
|
||||
int value);
|
||||
|
||||
extern gcc_jit_rvalue *ravi_lua_Number_constant(ravi_function_def_t *def,
|
||||
double value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* USE_GCCJIT */
|
||||
|
||||
#endif /* RAVI_RAVI_GCCJIT_H */
|
@ -0,0 +1,124 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015-2017 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef RAVI_JITSHARED_H
|
||||
#define RAVI_JITSHARED_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// TODO we probably do not need all the headers
|
||||
// below
|
||||
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lprefix.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lauxlib.h"
|
||||
#include "ldebug.h"
|
||||
#include "ldo.h"
|
||||
#include "lfunc.h"
|
||||
#include "lobject.h"
|
||||
#include "lopcodes.h"
|
||||
#include "lstate.h"
|
||||
#include "lstring.h"
|
||||
#include "ltable.h"
|
||||
#include "lua.h"
|
||||
#include "lvm.h"
|
||||
|
||||
#include <ravi_membuf.h>
|
||||
|
||||
#define RA(i) (base + GETARG_A(i))
|
||||
/* to be used after possible stack reallocation */
|
||||
#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base + GETARG_B(i))
|
||||
#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base + GETARG_C(i))
|
||||
#define RKB(i) \
|
||||
check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
|
||||
ISK(GETARG_B(i)) ? k + INDEXK(GETARG_B(i)) : base + GETARG_B(i))
|
||||
#define RKC(i) \
|
||||
check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
|
||||
ISK(GETARG_C(i)) ? k + INDEXK(GETARG_C(i)) : base + GETARG_C(i))
|
||||
#define KBx(i) \
|
||||
(k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++)))
|
||||
/* RAVI */
|
||||
#define KB(i) \
|
||||
check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k + INDEXK(GETARG_B(i)))
|
||||
#define KC(i) \
|
||||
check_exp(getCMode(GET_OPCODE(i)) == OpArgK, k + INDEXK(GETARG_C(i)))
|
||||
|
||||
enum errorcode {
|
||||
Error_integer_expected,
|
||||
Error_number_expected,
|
||||
Error_integer_array_expected,
|
||||
Error_number_array_expected,
|
||||
Error_table_expected,
|
||||
Error_upval_needs_integer,
|
||||
Error_upval_needs_number,
|
||||
Error_upval_needs_integer_array,
|
||||
Error_upval_needs_number_array,
|
||||
Error_upval_needs_table,
|
||||
Error_for_limit_must_be_number,
|
||||
Error_for_step_must_be_number,
|
||||
Error_for_initial_value_must_be_number,
|
||||
Error_array_out_of_bounds,
|
||||
};
|
||||
|
||||
enum ravi_codegen_type {
|
||||
RAVI_CODEGEN_NONE = 0,
|
||||
RAVI_CODEGEN_HEADER_ONLY = 1,
|
||||
RAVI_CODEGEN_FUNCTION_ONLY = 2,
|
||||
RAVI_CODEGEN_ALL = 3,
|
||||
};
|
||||
|
||||
struct ravi_compile_options_t {
|
||||
/* Is this a manual request? */
|
||||
int manual_request;
|
||||
|
||||
/* Should range check be omitted when compiling array access */
|
||||
int omit_array_get_range_check;
|
||||
|
||||
enum ravi_codegen_type codegen_type;
|
||||
};
|
||||
|
||||
LUAI_FUNC bool raviJ_cancompile(Proto *p);
|
||||
|
||||
// Convert a Lua function to C code
|
||||
// Returns true if compilation was successful
|
||||
// If successful then buf will be set
|
||||
LUAI_FUNC bool raviJ_codegen(struct lua_State *L, struct Proto *p,
|
||||
struct ravi_compile_options_t *options,
|
||||
const char *fname, membuff_t *buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,28 @@
|
||||
#ifndef RAVI_MEMBUF_H
|
||||
#define RAVI_MEMBUF_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
char *buf;
|
||||
size_t allocated_size;
|
||||
size_t pos;
|
||||
} membuff_t;
|
||||
|
||||
extern void membuff_init(membuff_t *mb, size_t initial_size);
|
||||
extern void membuff_rewindpos(membuff_t *mb);
|
||||
extern void membuff_resize(membuff_t *mb, size_t new_size);
|
||||
extern void membuff_free(membuff_t *mb);
|
||||
extern void membuff_add_string(membuff_t *mb, const char *str);
|
||||
extern void membuff_add_fstring(membuff_t *mb, const char *str, ...);
|
||||
extern void membuff_add_bool(membuff_t *mb, bool value);
|
||||
extern void membuff_add_int(membuff_t *mb, int value);
|
||||
extern void membuff_add_longlong(membuff_t *mb, int64_t value);
|
||||
|
||||
/* strncpy() with guaranteed 0 termination */
|
||||
extern void ravi_string_copy(char *buf, const char *src, size_t buflen);
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,69 @@
|
||||
-- Microbenchmark for bit operations library. Public domain.
|
||||
|
||||
local bit = require"bit"
|
||||
|
||||
if not bit.rol then -- Replacement function if rotates are missing.
|
||||
local bor, shl, shr = bit.bor, bit.lshift, bit.rshift
|
||||
function bit.rol(a, b) return bor(shl(a, b), shr(a, 32-b)) end
|
||||
end
|
||||
|
||||
if not bit.bswap then -- Replacement function if bswap is missing.
|
||||
local bor, band, shl, shr = bit.bor, bit.band, bit.lshift, bit.rshift
|
||||
function bit.bswap(a)
|
||||
return bor(shr(a, 24), band(shr(a, 8), 0xff00),
|
||||
shl(band(a, 0xff00), 8), shl(a, 24));
|
||||
end
|
||||
end
|
||||
|
||||
local base = 0
|
||||
|
||||
local function bench(name, t)
|
||||
local n = 2000000
|
||||
repeat
|
||||
local tm = os.clock()
|
||||
t(n)
|
||||
tm = os.clock() - tm
|
||||
if tm > 1 then
|
||||
local ns = tm*1000/(n/1000000)
|
||||
io.write(string.format("%-15s %6.1f ns\n", name, ns-base))
|
||||
return ns
|
||||
end
|
||||
n = n + n
|
||||
until false
|
||||
end
|
||||
|
||||
-- The overhead for the base loop is subtracted from the other measurements.
|
||||
base = bench("loop baseline", function(n)
|
||||
local x = 0; for i=1,n do x = x + i end
|
||||
end)
|
||||
|
||||
bench("tobit", function(n)
|
||||
local f = bit.tobit or bit.cast
|
||||
local x = 0; for i=1,n do x = x + f(i) end
|
||||
end)
|
||||
|
||||
bench("bnot", function(n)
|
||||
local f = bit.bnot
|
||||
local x = 0; for i=1,n do x = x + f(i) end
|
||||
end)
|
||||
|
||||
bench("bor/band/bxor", function(n)
|
||||
local f = bit.bor
|
||||
local x = 0; for i=1,n do x = x + f(i, 1) end
|
||||
end)
|
||||
|
||||
bench("shifts", function(n)
|
||||
local f = bit.lshift
|
||||
local x = 0; for i=1,n do x = x + f(i, 1) end
|
||||
end)
|
||||
|
||||
bench("rotates", function(n)
|
||||
local f = bit.rol
|
||||
local x = 0; for i=1,n do x = x + f(i, 1) end
|
||||
end)
|
||||
|
||||
bench("bswap", function(n)
|
||||
local f = bit.bswap
|
||||
local x = 0; for i=1,n do x = x + f(i) end
|
||||
end)
|
||||
|
@ -0,0 +1,85 @@
|
||||
-- Test cases for bit operations library. Public domain.
|
||||
|
||||
local bit = require"bit"
|
||||
|
||||
local vb = {
|
||||
0, 1, -1, 2, -2, 0x12345678, 0x87654321,
|
||||
0x33333333, 0x77777777, 0x55aa55aa, 0xaa55aa55,
|
||||
0x7fffffff, 0x80000000, 0xffffffff
|
||||
}
|
||||
|
||||
local function cksum(name, s, r)
|
||||
local z = 0
|
||||
for i=1,#s do z = (z + string.byte(s, i)*i) % 2147483629 end
|
||||
if z ~= r then
|
||||
error("bit."..name.." test failed (got "..z..", expected "..r..")", 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function check_unop(name, r)
|
||||
local f = bit[name]
|
||||
local s = ""
|
||||
if pcall(f) or pcall(f, "z") or pcall(f, true) then
|
||||
error("bit."..name.." fails to detect argument errors", 0)
|
||||
end
|
||||
for _,x in ipairs(vb) do s = s..","..tostring(f(x)) end
|
||||
cksum(name, s, r)
|
||||
end
|
||||
|
||||
local function check_binop(name, r)
|
||||
local f = bit[name]
|
||||
local s = ""
|
||||
if pcall(f) or pcall(f, "z") or pcall(f, true) then
|
||||
error("bit."..name.." fails to detect argument errors", 0)
|
||||
end
|
||||
for _,x in ipairs(vb) do
|
||||
for _,y in ipairs(vb) do s = s..","..tostring(f(x, y)) end
|
||||
end
|
||||
cksum(name, s, r)
|
||||
end
|
||||
|
||||
local function check_binop_range(name, r, yb, ye)
|
||||
local f = bit[name]
|
||||
local s = ""
|
||||
if pcall(f) or pcall(f, "z") or pcall(f, true) or pcall(f, 1, true) then
|
||||
error("bit."..name.." fails to detect argument errors", 0)
|
||||
end
|
||||
for _,x in ipairs(vb) do
|
||||
for y=yb,ye do s = s..","..tostring(f(x, y)) end
|
||||
end
|
||||
cksum(name, s, r)
|
||||
end
|
||||
|
||||
local function check_shift(name, r)
|
||||
check_binop_range(name, r, 0, 31)
|
||||
end
|
||||
|
||||
-- Minimal sanity checks.
|
||||
assert(0x7fffffff == 2147483647, "broken hex literals")
|
||||
assert(0xffffffff == -1 or 0xffffffff == 2^32-1, "broken hex literals")
|
||||
assert(tostring(-1) == "-1", "broken tostring()")
|
||||
assert(tostring(0xffffffff) == "-1" or tostring(0xffffffff) == "4294967295", "broken tostring()")
|
||||
|
||||
-- Basic argument processing.
|
||||
assert(bit.tobit(1) == 1)
|
||||
assert(bit.band(1) == 1)
|
||||
assert(bit.bxor(1,2) == 3)
|
||||
assert(bit.bor(1,2,4,8,16,32,64,128) == 255)
|
||||
|
||||
-- Apply operations to test vectors and compare checksums.
|
||||
check_unop("tobit", 277312)
|
||||
check_unop("bnot", 287870)
|
||||
check_unop("bswap", 307611)
|
||||
|
||||
check_binop("band", 41206764)
|
||||
check_binop("bor", 51253663)
|
||||
check_binop("bxor", 79322427)
|
||||
|
||||
check_shift("lshift", 325260344)
|
||||
check_shift("rshift", 139061800)
|
||||
check_shift("arshift", 111364720)
|
||||
check_shift("rol", 302401155)
|
||||
check_shift("ror", 302316761)
|
||||
|
||||
check_binop_range("tohex", 47880306, -8, 8)
|
||||
|
@ -0,0 +1,38 @@
|
||||
-- Print anything - including nested tables
|
||||
local function table_print (tt, indent, done)
|
||||
done = done or {}
|
||||
indent = indent or 0
|
||||
if type(tt) == "table" then
|
||||
for key, value in pairs (tt) do
|
||||
io.write(string.rep (" ", indent)) -- indent it
|
||||
if type (value) == "table" and not done [value] then
|
||||
done [value] = true
|
||||
io.write(string.format("[%s] => table\n", tostring (key)));
|
||||
io.write(string.rep (" ", indent+4)) -- indent it
|
||||
io.write("(\n");
|
||||
table_print (value, indent + 7, done)
|
||||
io.write(string.rep (" ", indent+4)) -- indent it
|
||||
io.write(")\n");
|
||||
else
|
||||
io.write(string.format("[%s] => %s\n",
|
||||
tostring (key), tostring(value)))
|
||||
end
|
||||
end
|
||||
else
|
||||
io.write(tostring(tt) .. "\n")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local somecode = [[
|
||||
extern int adder(int a, int b);
|
||||
|
||||
int adder(int a, int b)
|
||||
{
|
||||
return a+b;
|
||||
}
|
||||
]]
|
||||
|
||||
local symbols = dmrc.getsymbols(somecode)
|
||||
|
||||
table_print(symbols)
|
@ -0,0 +1,20 @@
|
||||
local testfunc = [[
|
||||
struct lua_State;
|
||||
extern int puts(const char *);
|
||||
extern int TestFunc(struct lua_State *L);
|
||||
|
||||
int TestFunc(struct lua_State *L)
|
||||
{
|
||||
puts("hello world!\n");
|
||||
return 0;
|
||||
}
|
||||
]]
|
||||
|
||||
|
||||
local ctx = llvm.context()
|
||||
local m = ctx:newmodule()
|
||||
m:compileC(testfunc)
|
||||
local f = m:getfunction("TestFunc")
|
||||
local callable = f:compile()
|
||||
|
||||
callable()
|
@ -0,0 +1,196 @@
|
||||
-- MD5 test and benchmark. Public domain.
|
||||
|
||||
local bit = require("bit")
|
||||
local tobit, tohex, bnot = bit.tobit or bit.cast, bit.tohex, bit.bnot
|
||||
local bor, band, bxor = bit.bor, bit.band, bit.bxor
|
||||
local lshift, rshift, rol, bswap = bit.lshift, bit.rshift, bit.rol, bit.bswap
|
||||
local byte, char, sub, rep = string.byte, string.char, string.sub, string.rep
|
||||
|
||||
if not rol then -- Replacement function if rotates are missing.
|
||||
local bor, shl, shr = bit.bor, bit.lshift, bit.rshift
|
||||
function rol(a, b) return bor(shl(a, b), shr(a, 32-b)) end
|
||||
end
|
||||
|
||||
if not bswap then -- Replacement function if bswap is missing.
|
||||
local bor, band, shl, shr = bit.bor, bit.band, bit.lshift, bit.rshift
|
||||
function bswap(a)
|
||||
return bor(shr(a, 24), band(shr(a, 8), 0xff00),
|
||||
shl(band(a, 0xff00), 8), shl(a, 24));
|
||||
end
|
||||
end
|
||||
|
||||
if not tohex then -- (Unreliable) replacement function if tohex is missing.
|
||||
function tohex(a)
|
||||
return string.sub(string.format("%08x", a), -8)
|
||||
end
|
||||
end
|
||||
|
||||
local function tr_f(a, b, c, d, x, s)
|
||||
return rol(bxor(d, band(b, bxor(c, d))) + a + x, s) + b
|
||||
end
|
||||
|
||||
local function tr_g(a, b, c, d, x, s)
|
||||
return rol(bxor(c, band(d, bxor(b, c))) + a + x, s) + b
|
||||
end
|
||||
|
||||
local function tr_h(a, b, c, d, x, s)
|
||||
return rol(bxor(b, c, d) + a + x, s) + b
|
||||
end
|
||||
|
||||
local function tr_i(a, b, c, d, x, s)
|
||||
return rol(bxor(c, bor(b, bnot(d))) + a + x, s) + b
|
||||
end
|
||||
|
||||
local function transform(x, a1, b1, c1, d1)
|
||||
local a, b, c, d = a1, b1, c1, d1
|
||||
|
||||
a = tr_f(a, b, c, d, x[ 1] + 0xd76aa478, 7)
|
||||
d = tr_f(d, a, b, c, x[ 2] + 0xe8c7b756, 12)
|
||||
c = tr_f(c, d, a, b, x[ 3] + 0x242070db, 17)
|
||||
b = tr_f(b, c, d, a, x[ 4] + 0xc1bdceee, 22)
|
||||
a = tr_f(a, b, c, d, x[ 5] + 0xf57c0faf, 7)
|
||||
d = tr_f(d, a, b, c, x[ 6] + 0x4787c62a, 12)
|
||||
c = tr_f(c, d, a, b, x[ 7] + 0xa8304613, 17)
|
||||
b = tr_f(b, c, d, a, x[ 8] + 0xfd469501, 22)
|
||||
a = tr_f(a, b, c, d, x[ 9] + 0x698098d8, 7)
|
||||
d = tr_f(d, a, b, c, x[10] + 0x8b44f7af, 12)
|
||||
c = tr_f(c, d, a, b, x[11] + 0xffff5bb1, 17)
|
||||
b = tr_f(b, c, d, a, x[12] + 0x895cd7be, 22)
|
||||
a = tr_f(a, b, c, d, x[13] + 0x6b901122, 7)
|
||||
d = tr_f(d, a, b, c, x[14] + 0xfd987193, 12)
|
||||
c = tr_f(c, d, a, b, x[15] + 0xa679438e, 17)
|
||||
b = tr_f(b, c, d, a, x[16] + 0x49b40821, 22)
|
||||
|
||||
a = tr_g(a, b, c, d, x[ 2] + 0xf61e2562, 5)
|
||||
d = tr_g(d, a, b, c, x[ 7] + 0xc040b340, 9)
|
||||
c = tr_g(c, d, a, b, x[12] + 0x265e5a51, 14)
|
||||
b = tr_g(b, c, d, a, x[ 1] + 0xe9b6c7aa, 20)
|
||||
a = tr_g(a, b, c, d, x[ 6] + 0xd62f105d, 5)
|
||||
d = tr_g(d, a, b, c, x[11] + 0x02441453, 9)
|
||||
c = tr_g(c, d, a, b, x[16] + 0xd8a1e681, 14)
|
||||
b = tr_g(b, c, d, a, x[ 5] + 0xe7d3fbc8, 20)
|
||||
a = tr_g(a, b, c, d, x[10] + 0x21e1cde6, 5)
|
||||
d = tr_g(d, a, b, c, x[15] + 0xc33707d6, 9)
|
||||
c = tr_g(c, d, a, b, x[ 4] + 0xf4d50d87, 14)
|
||||
b = tr_g(b, c, d, a, x[ 9] + 0x455a14ed, 20)
|
||||
a = tr_g(a, b, c, d, x[14] + 0xa9e3e905, 5)
|
||||
d = tr_g(d, a, b, c, x[ 3] + 0xfcefa3f8, 9)
|
||||
c = tr_g(c, d, a, b, x[ 8] + 0x676f02d9, 14)
|
||||
b = tr_g(b, c, d, a, x[13] + 0x8d2a4c8a, 20)
|
||||
|
||||
a = tr_h(a, b, c, d, x[ 6] + 0xfffa3942, 4)
|
||||
d = tr_h(d, a, b, c, x[ 9] + 0x8771f681, 11)
|
||||
c = tr_h(c, d, a, b, x[12] + 0x6d9d6122, 16)
|
||||
b = tr_h(b, c, d, a, x[15] + 0xfde5380c, 23)
|
||||
a = tr_h(a, b, c, d, x[ 2] + 0xa4beea44, 4)
|
||||
d = tr_h(d, a, b, c, x[ 5] + 0x4bdecfa9, 11)
|
||||
c = tr_h(c, d, a, b, x[ 8] + 0xf6bb4b60, 16)
|
||||
b = tr_h(b, c, d, a, x[11] + 0xbebfbc70, 23)
|
||||
a = tr_h(a, b, c, d, x[14] + 0x289b7ec6, 4)
|
||||
d = tr_h(d, a, b, c, x[ 1] + 0xeaa127fa, 11)
|
||||
c = tr_h(c, d, a, b, x[ 4] + 0xd4ef3085, 16)
|
||||
b = tr_h(b, c, d, a, x[ 7] + 0x04881d05, 23)
|
||||
a = tr_h(a, b, c, d, x[10] + 0xd9d4d039, 4)
|
||||
d = tr_h(d, a, b, c, x[13] + 0xe6db99e5, 11)
|
||||
c = tr_h(c, d, a, b, x[16] + 0x1fa27cf8, 16)
|
||||
b = tr_h(b, c, d, a, x[ 3] + 0xc4ac5665, 23)
|
||||
|
||||
a = tr_i(a, b, c, d, x[ 1] + 0xf4292244, 6)
|
||||
d = tr_i(d, a, b, c, x[ 8] + 0x432aff97, 10)
|
||||
c = tr_i(c, d, a, b, x[15] + 0xab9423a7, 15)
|
||||
b = tr_i(b, c, d, a, x[ 6] + 0xfc93a039, 21)
|
||||
a = tr_i(a, b, c, d, x[13] + 0x655b59c3, 6)
|
||||
d = tr_i(d, a, b, c, x[ 4] + 0x8f0ccc92, 10)
|
||||
c = tr_i(c, d, a, b, x[11] + 0xffeff47d, 15)
|
||||
b = tr_i(b, c, d, a, x[ 2] + 0x85845dd1, 21)
|
||||
a = tr_i(a, b, c, d, x[ 9] + 0x6fa87e4f, 6)
|
||||
d = tr_i(d, a, b, c, x[16] + 0xfe2ce6e0, 10)
|
||||
c = tr_i(c, d, a, b, x[ 7] + 0xa3014314, 15)
|
||||
b = tr_i(b, c, d, a, x[14] + 0x4e0811a1, 21)
|
||||
a = tr_i(a, b, c, d, x[ 5] + 0xf7537e82, 6)
|
||||
d = tr_i(d, a, b, c, x[12] + 0xbd3af235, 10)
|
||||
c = tr_i(c, d, a, b, x[ 3] + 0x2ad7d2bb, 15)
|
||||
b = tr_i(b, c, d, a, x[10] + 0xeb86d391, 21)
|
||||
|
||||
return tobit(a+a1), tobit(b+b1), tobit(c+c1), tobit(d+d1)
|
||||
end
|
||||
|
||||
-- Note: this is copying the original string and NOT particularly fast.
|
||||
-- A library for struct unpacking would make this task much easier.
|
||||
local function md5(msg)
|
||||
local len = #msg
|
||||
msg = msg.."\128"..rep("\0", 63 - band(len + 8, 63))
|
||||
..char(band(lshift(len, 3), 255), band(rshift(len, 5), 255),
|
||||
band(rshift(len, 13), 255), band(rshift(len, 21), 255))
|
||||
.."\0\0\0\0"
|
||||
local a, b, c, d = 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
|
||||
local x, k = {}, 1
|
||||
for i=1,#msg,4 do
|
||||
local m0, m1, m2, m3 = byte(msg, i, i+3)
|
||||
x[k] = bor(m0, lshift(m1, 8), lshift(m2, 16), lshift(m3, 24))
|
||||
if k == 16 then
|
||||
a, b, c, d = transform(x, a, b, c, d)
|
||||
k = 1
|
||||
else
|
||||
k = k + 1
|
||||
end
|
||||
end
|
||||
return tohex(bswap(a))..tohex(bswap(b))..tohex(bswap(c))..tohex(bswap(d))
|
||||
end
|
||||
|
||||
assert(md5('') == 'd41d8cd98f00b204e9800998ecf8427e')
|
||||
assert(md5('a') == '0cc175b9c0f1b6a831c399e269772661')
|
||||
assert(md5('abc') == '900150983cd24fb0d6963f7d28e17f72')
|
||||
assert(md5('message digest') == 'f96b697d7cb7938d525a2f31aaf161d0')
|
||||
assert(md5('abcdefghijklmnopqrstuvwxyz') == 'c3fcd3d76192e4007dfb496cca67e13b')
|
||||
assert(md5('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') ==
|
||||
'd174ab98d277d9f5a5611c2c9f419d9f')
|
||||
assert(md5('12345678901234567890123456789012345678901234567890123456789012345678901234567890') ==
|
||||
'57edf4a22be3c955ac49da2e2107b67a')
|
||||
|
||||
if arg and arg[1] == "bench" then
|
||||
-- Credits: William Shakespeare, Romeo and Juliet
|
||||
local txt = [[Rebellious subjects, enemies to peace,
|
||||
Profaners of this neighbour-stained steel,--
|
||||
Will they not hear? What, ho! you men, you beasts,
|
||||
That quench the fire of your pernicious rage
|
||||
With purple fountains issuing from your veins,
|
||||
On pain of torture, from those bloody hands
|
||||
Throw your mistemper'd weapons to the ground,
|
||||
And hear the sentence of your moved prince.
|
||||
Three civil brawls, bred of an airy word,
|
||||
By thee, old Capulet, and Montague,
|
||||
Have thrice disturb'd the quiet of our streets,
|
||||
And made Verona's ancient citizens
|
||||
Cast by their grave beseeming ornaments,
|
||||
To wield old partisans, in hands as old,
|
||||
Canker'd with peace, to part your canker'd hate:
|
||||
If ever you disturb our streets again,
|
||||
Your lives shall pay the forfeit of the peace.
|
||||
For this time, all the rest depart away:
|
||||
You Capulet; shall go along with me:
|
||||
And, Montague, come you this afternoon,
|
||||
To know our further pleasure in this case,
|
||||
To old Free-town, our common judgment-place.
|
||||
Once more, on pain of death, all men depart.]]
|
||||
txt = txt..txt..txt..txt
|
||||
txt = txt..txt..txt..txt
|
||||
|
||||
local function bench()
|
||||
local n = 80
|
||||
repeat
|
||||
local tm = os.clock()
|
||||
local res
|
||||
for i=1,n do
|
||||
res = md5(txt)
|
||||
end
|
||||
assert(res == 'a831e91e0f70eddcb70dc61c6f82f6cd')
|
||||
tm = os.clock() - tm
|
||||
if tm > 1 then return tm*(1000000000/(n*#txt)) end
|
||||
n = n + n
|
||||
until false
|
||||
end
|
||||
|
||||
io.write(string.format("MD5 %7.1f ns/char\n", bench()))
|
||||
end
|
||||
|
@ -0,0 +1,32 @@
|
||||
-- This is the (naive) Sieve of Eratosthenes. Public domain.
|
||||
|
||||
local bit = require("bit")
|
||||
local band, bxor, rshift, rol = bit.band, bit.bxor, bit.rshift, bit.rol
|
||||
|
||||
local function nsieve(p, m)
|
||||
local count = 0
|
||||
for i=0,rshift(m, 5) do p[i] = -1 end
|
||||
for i=2,m do
|
||||
if band(rshift(p[rshift(i, 5)], i), 1) ~= 0 then
|
||||
count = count + 1
|
||||
for j=i+i,m,i do
|
||||
local jx = rshift(j, 5)
|
||||
p[jx] = band(p[jx], rol(-2, j))
|
||||
end
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
if arg and arg[1] then
|
||||
local N = tonumber(arg[1]) or 1
|
||||
if N < 2 then N = 2 end
|
||||
local primes = {}
|
||||
|
||||
for i=0,2 do
|
||||
local m = (2^(N-i))*10000
|
||||
io.write(string.format("Primes up to %8d %8d\n", m, nsieve(primes, m)))
|
||||
end
|
||||
else
|
||||
assert(nsieve({}, 10000) == 1229)
|
||||
end
|
@ -0,0 +1,21 @@
|
||||
local tests = {}
|
||||
|
||||
tests.RETURN = function()
|
||||
return
|
||||
end
|
||||
|
||||
tests.LOADK = function()
|
||||
return 1, 4.2, 'hello'
|
||||
end
|
||||
|
||||
tests.MOVE = function(a, b)
|
||||
local c,d = a,b
|
||||
return c,d
|
||||
end
|
||||
|
||||
|
||||
for k,v in pairs(tests) do
|
||||
print(k)
|
||||
ravi.dumplua(v)
|
||||
--v()
|
||||
end
|
@ -0,0 +1,106 @@
|
||||
-- These tests are for new backend
|
||||
local compile = function(f)
|
||||
if ravi.jit() then
|
||||
assert(ravi.compile(f))
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local x = function() end
|
||||
|
||||
compile(x)
|
||||
|
||||
x = function() return 42 end
|
||||
|
||||
compile(x)
|
||||
assert(x() == 42)
|
||||
|
||||
x = function() return 4.256 end
|
||||
|
||||
compile(x)
|
||||
assert(x() == 4.256)
|
||||
|
||||
x = function() return 'hello' end
|
||||
|
||||
compile(x)
|
||||
assert(x() == 'hello')
|
||||
|
||||
x = function()
|
||||
local j
|
||||
for i=1,10 do
|
||||
for k = 0,5,5 do
|
||||
j = k
|
||||
end
|
||||
end
|
||||
return j
|
||||
end
|
||||
|
||||
compile(x)
|
||||
assert(x() == 5)
|
||||
|
||||
x = function()
|
||||
local a,b = false, true
|
||||
return a
|
||||
end
|
||||
|
||||
compile(x)
|
||||
assert(not x())
|
||||
|
||||
x = function()
|
||||
local a
|
||||
if 2 < 5 then
|
||||
a = true
|
||||
else
|
||||
a = false
|
||||
end
|
||||
end
|
||||
compile(x)
|
||||
assert(not x())
|
||||
|
||||
local y
|
||||
y = function()
|
||||
return x()
|
||||
end
|
||||
compile(y)
|
||||
assert(not y())
|
||||
|
||||
x = function()
|
||||
print 'Good if this prints'
|
||||
end
|
||||
compile(x)
|
||||
x()
|
||||
|
||||
x = function()
|
||||
if 8 > 9 then
|
||||
return 8
|
||||
elseif 5 >= 4 then
|
||||
return 5
|
||||
else
|
||||
return 9
|
||||
end
|
||||
end
|
||||
compile(x)
|
||||
assert(x() == 5)
|
||||
|
||||
x = function()
|
||||
local j = -99
|
||||
for i = 10,1,-1 do
|
||||
j = i
|
||||
end
|
||||
return j
|
||||
end
|
||||
ravi.compile(x)
|
||||
assert(x() == 1)
|
||||
|
||||
x = function()
|
||||
local j = -9.9
|
||||
for i = 10.5,1.5,-1.0 do
|
||||
j = i
|
||||
end
|
||||
return j
|
||||
end
|
||||
ravi.compile(x)
|
||||
assert(x() == 1.5)
|
||||
|
||||
|
||||
print'Ok'
|
@ -0,0 +1,489 @@
|
||||
===================
|
||||
Introduction to Lua
|
||||
===================
|
||||
|
||||
Introduction
|
||||
============
|
||||
`Lua <https://www.lua.org>`_ is a small but powerful interpreted language that is implemented as a C library. This guide is meant to help you quickly become familiar with the main features of Lua. This guide assumes you know C, C++, or Java, and perhaps a scripting language like Python - it is not a beginner's guide. Nor is it a tutorial for Lua.
|
||||
|
||||
Key Features of Lua
|
||||
===================
|
||||
* Lua versions matter
|
||||
* Lua is dynamically typed like Python
|
||||
* By default variables in Lua are global unless declared local
|
||||
* There is a single complex / aggregate type called a 'table', which combines hash table/map and array features
|
||||
* Functions in Lua are values stored in variables; in particular functions do not have names
|
||||
* Globals in Lua are just values stored in a special Lua table
|
||||
* Functions in Lua are closures - they can capture variables from outer scope and such variables live on even though the surrounding scope is no longer alive
|
||||
* Lua functions can return multiple values
|
||||
* Lua has integer (since 5.3) and floating point types that map to native C types
|
||||
* A special ``nil`` value represents non-existent value
|
||||
* Any value that is not ``false`` or ``nil`` is true
|
||||
* The result of logical ``and`` and logical ``or`` is not true or false; these operators select one of the values
|
||||
* ``'~='`` is not equals operator and ``'..'`` is string concatenation operator
|
||||
* Lua has some nice syntactic sugar for tables and functions
|
||||
* A Lua script is called a chunk - and is the unit of compilation in Lua
|
||||
* The Lua stack is a heap allocated structure - and you can think of Lua as a library that manipulates this stack
|
||||
* Lua functions can be yielded from and resumed later on, i.e., Lua supports coroutines
|
||||
* Lua is single threaded but its VM is small and encapsulated in a single data structure - hence each OS thread can be given its own
|
||||
Lua VM
|
||||
* Lua's error handling is based on C setjmp/longjmp, and errors are caught via a special function call mechanism
|
||||
* Lua has a meta mechanism that enables a DIY class / object system with some syntactic sugar to make it look nice
|
||||
* Lua supports operator overloading via 'meta' methods
|
||||
* You can create user defined types in C and make them available in Lua
|
||||
* Lua compiles code to bytecode before execution
|
||||
* Lua bytecode is not officially documented and changes from one Lua version to another; moreover the binary dump of the bytecodes is
|
||||
not portable across architectures and also can change between versions
|
||||
* Lua's compiler is designed to be fast and frugal - it generates code as it parses, there is no intermediate AST construction
|
||||
* Like C, Lua comes with a very small standard library - in fact Lua's standard library is just a wrapper for C standard library
|
||||
plus some basic utilities for Lua
|
||||
* Lua's standard library includes pattern matching for strings in which the patterns themselves are strings, rather like regular expressions in Python or Perl, but simpler.
|
||||
* Lua provides a debug API that can be used to manipulate Lua's internals to a degree - and can be used to implement a debugger
|
||||
* Lua has an incremental garbage collector
|
||||
* Lua is Open Source but has a closed development model - external contributions are not possible
|
||||
* LuaJIT is a JIT compiler for Lua but features an optional high performance C interface mechanism that makes it incompatible with Lua
|
||||
|
||||
In the rest of this document I will expand on each of these aspects of Lua.
|
||||
|
||||
Lua versions matter
|
||||
===================
|
||||
For all practical purposes only Lua versions 5.1, 5.2 and 5.3 matter. Note however that each of these is considered a major version and therefore is not fully backward compatible (e.g. Lua 5.3 cannot necessarily run Lua 5.1 code) although there is a large common subset.
|
||||
|
||||
* Lua 5.2 has a new mechanism for resolving undeclared variables compared to 5.1
|
||||
* Lua 5.3 has integer number subtype and bitwise operators that did not exist in 5.1 or 5.2
|
||||
* LuaJIT is 5.1 based but supports a large subset of 5.2 features with some notable exceptions such as the change mentioned above
|
||||
|
||||
Mostly what this document covers should be applicable to all these versions, except as otherwise noted.
|
||||
|
||||
Lua is dynamically typed
|
||||
========================
|
||||
This means that values have types but variables do not. Example::
|
||||
|
||||
x = 1 -- x holds an integer
|
||||
x = 5.0 -- x now holds a floating pont value
|
||||
x = {} -- x now holds an empty table
|
||||
x = function() end -- x now holds a function with empty body
|
||||
|
||||
Variables are global unless declared local
|
||||
==========================================
|
||||
In the example above, ``x`` is global.
|
||||
But saying::
|
||||
|
||||
local x = 1
|
||||
|
||||
makes ``x`` local, i.e. its scope and visibility is constrained to the enclosing block of code, and any nested blocks. Note that
|
||||
local variables avoid a lookup in the 'global' table and hence are more efficient. Thus it is common practice to cache values in
|
||||
local variables. For example, ``print`` is a global function - and following creates a local variable that caches it::
|
||||
|
||||
local print = print -- caches global print() function
|
||||
print('hello world!') -- calls the same function as global print()
|
||||
|
||||
There are some exceptions to the rule:
|
||||
|
||||
* the iterator variables declared in a ``for`` loop are implicitly local.
|
||||
* function parameters are local to the function
|
||||
|
||||
The 'table' type
|
||||
================
|
||||
Lua's only complex / aggregate data type is a table. Tables are used for many things in Lua, even internally within Lua.
|
||||
Here are some examples::
|
||||
|
||||
local a = {} -- creates an empty table
|
||||
local b = {10,20,30} -- creates a table with three array elements at positions 1,2,3
|
||||
-- this is short cut for:
|
||||
-- local b = {}
|
||||
-- b[1] = 10
|
||||
-- b[2] = 20
|
||||
-- b[3] = 30
|
||||
local c = { name='Ravi' } -- creates a table with one hash map entry
|
||||
-- this is short cut for:
|
||||
-- local c = {}
|
||||
-- c['name'] = 'Ravi'
|
||||
|
||||
Internally the table is a composite hash table / array structure. Consecutive values starting at integer index 1 are inserted into the array, else the values go into the hash table. Hence, in the example below::
|
||||
|
||||
local t = {}
|
||||
t[1] = 20 -- goes into array
|
||||
t[2] = 10 -- goes into array
|
||||
t[100] = 1 -- goes into hash table as not consecutive
|
||||
t.name = 'Ravi' -- goes into hash table
|
||||
-- t.name is syntactic sugar for t['name']
|
||||
|
||||
To iterate over array values you can write::
|
||||
|
||||
for i = 1,#t do
|
||||
print(t[i])
|
||||
end
|
||||
|
||||
Note that above will only print 20,10.
|
||||
|
||||
To iterate over all values write::
|
||||
|
||||
for k,v in pairs(t) do
|
||||
print(k,v)
|
||||
end
|
||||
|
||||
Unfortunately, you need to get a good understanding of when values will go into the array part of a table, because some Lua library functions work only on the array part. Example::
|
||||
|
||||
table.sort(t)
|
||||
|
||||
You will see that only values at indices 1 and 2 were sorted.
|
||||
Another frequent problem is that the only way to reliably know the total number of elements in a table is to count the values.
|
||||
The ``#`` operator returns the length of the consecutive array elements starting at index 1.
|
||||
|
||||
Functions are values stored in variables
|
||||
========================================
|
||||
You already saw that we can write::
|
||||
|
||||
local x = function()
|
||||
end
|
||||
|
||||
This creates a function and stores it in local variable ``x``. This is the same as::
|
||||
|
||||
local function x()
|
||||
end
|
||||
|
||||
Omitting the ``local`` keyword would create ``x`` in global scope.
|
||||
|
||||
Functions can be defined within functions - in fact all Lua functions are defined within a 'chunk' of code, which gets wrapped inside a Lua function.
|
||||
|
||||
Internally a function has a 'prototype' that holds the compiled code and other meta data regarding the function. An instance of the
|
||||
function in created when the code executes. You can think of the 'prototype' as the 'class' of the function, and the function instance is akin to an object created from this class.
|
||||
|
||||
Globals are just values in a special table
|
||||
==========================================
|
||||
Globals are handled in an interesting way. Whenever a name is used that is not found in any of the enclosing scopes and is not declared ``local``, then Lua will access/create a variable in a table accessed by the name ``_ENV`` (this applies to Lua 5.2 and above - Lua 5.1 had a different mechanism). Actually ``_ENV`` is just a captured value that points to a special table in Lua by default. This table access becomes evident when you look at the bytecode generated for some Lua code::
|
||||
|
||||
function hello()
|
||||
print('hello world')
|
||||
end
|
||||
|
||||
Generates following (in Lua 5.3)::
|
||||
|
||||
function <stdin:1,3> (4 instructions at 00000151C0AA9530)
|
||||
0 params, 2 slots, 1 upvalue, 0 locals, 2 constants, 0 functions
|
||||
1 [2] GETTABUP 0 0 -1 ; _ENV "print"
|
||||
2 [2] LOADK 1 -2 ; "hello world"
|
||||
3 [2] CALL 0 2 1
|
||||
4 [3] RETURN 0 1
|
||||
constants (2) for 00000151C0AA9530:
|
||||
1 "print"
|
||||
2 "hello world"
|
||||
locals (0) for 00000151C0AA9530:
|
||||
upvalues (1) for 00000151C0AA9530:
|
||||
0 _ENV 0 0
|
||||
|
||||
The ``GETTABUP`` instruction looks up the name 'print' in the captured table variable ``_ENV``. Lua uses the term 'upvalue' for captured variables.
|
||||
|
||||
Functions in Lua are closures
|
||||
=============================
|
||||
Lua functions can reference variables in outer scopes - and such references can be captured by the function so that even if the outer scope does not exist anymore the variable still lives on::
|
||||
|
||||
-- x() returns two anonymous functions
|
||||
x = function()
|
||||
local a = 1
|
||||
return function(b)
|
||||
a = a+b
|
||||
return a
|
||||
end,
|
||||
function(b)
|
||||
a = a+b
|
||||
return a
|
||||
end
|
||||
end
|
||||
|
||||
-- call x
|
||||
m,n = x()
|
||||
m(1) -- returns 2
|
||||
n(1) -- returns 3
|
||||
|
||||
In the example above, the local variable ``a`` in function ``x()`` is captured inside the two anonymous functions that reference it. You can see this if you dump Lua 5.3 bytecode for ``m``::
|
||||
|
||||
function <stdin:1,1> (6 instructions at 00000151C0AD3AB0)
|
||||
1 param, 2 slots, 1 upvalue, 1 local, 0 constants, 0 functions
|
||||
1 [1] GETUPVAL 1 0 ; a
|
||||
2 [1] ADD 1 1 0
|
||||
3 [1] SETUPVAL 1 0 ; a
|
||||
4 [1] GETUPVAL 1 0 ; a
|
||||
5 [1] RETURN 1 2
|
||||
6 [1] RETURN 0 1
|
||||
constants (0) for 00000151C0AD3AB0:
|
||||
locals (1) for 00000151C0AD3AB0:
|
||||
0 b 1 7
|
||||
upvalues (1) for 00000151C0AD3AB0:
|
||||
0 a 1 0
|
||||
|
||||
The ``GETUPVAL`` and ``SETUPVAL`` instructions access captured variables or upvalues as they are known in Lua.
|
||||
|
||||
Lua functions can return multiple values
|
||||
========================================
|
||||
An example of this already appeared above. Here is another::
|
||||
|
||||
function foo()
|
||||
return 1, 'text'
|
||||
end
|
||||
|
||||
x,y = foo()
|
||||
|
||||
Lua has integer and floating point numeric types
|
||||
================================================
|
||||
Since Lua 5.3 Lua's number type has integer and floating point representations. This is automatically managed; however a library function is provided to tell you what Lua thinks the number type is.
|
||||
|
||||
::
|
||||
|
||||
x = 1 -- integer
|
||||
y = 4.2 -- double
|
||||
|
||||
print(math.type(x)) -- says 'integer'
|
||||
print(math.type(y)) -- says 'float'
|
||||
|
||||
On 64-bit architecture by default an integer is represented as C ``int64_t`` and floating point as ``double``. The representation of the numeric type as native C types is one of the secrets of Lua's performance, as the numeric types do not require 'boxing'.
|
||||
|
||||
In Lua 5.3, there is a special division operator ``//`` that does integer division if the operands are both integer. Example::
|
||||
|
||||
x = 4
|
||||
y = 3
|
||||
|
||||
print(x//y) -- integer division results in 0
|
||||
print(x/y) -- floating division results in 1.3333333333333
|
||||
|
||||
Note that officially the ``//`` operator does floor division, hence if one or both of its operands is floating point then the result is also a floating point representing the floor of the division of its operands.
|
||||
|
||||
Having integer types has also made it natural to have support for bitwise operators in Lua 5.3.
|
||||
|
||||
A special ``nil`` value represents non-existent value
|
||||
=====================================================
|
||||
Lua has special value ``nil`` that represents no value, and evaluates to false in boolean expressions.
|
||||
|
||||
Any value that is not ``false`` or ``nil`` is true
|
||||
==================================================
|
||||
As mentioned above ``nil`` evaluates to false.
|
||||
|
||||
Logical ``and`` and logical ``or`` select one of the values
|
||||
===========================================================
|
||||
When you perform a logical ``and`` or ``or`` the result is not boolean; these operators select one of the values. This is best
|
||||
illustrated via examples::
|
||||
|
||||
false or 'hello' -- selects 'hello'
|
||||
'hello' and 'world' -- selects 'world'
|
||||
false and 'hello' -- selects false
|
||||
nil or false -- selects false
|
||||
nil and false -- selects nil
|
||||
|
||||
* ``and`` selects the first value if it evaluates to false else the second value.
|
||||
* ``or`` selects the first value if it evaluates to true else the second value.
|
||||
|
||||
``'~='`` is not equals operator and ``'..'`` is string concatenation operator
|
||||
=============================================================================
|
||||
For example::
|
||||
|
||||
print(1 ~= 2) -- prints 'true'
|
||||
print('hello ' .. 'world!') -- prints 'hello world!')
|
||||
|
||||
Lua has some nice syntactic sugar for tables and functions
|
||||
==========================================================
|
||||
If you are calling a Lua function with a single string or table argument then the parenthesis can be omitted::
|
||||
|
||||
print 'hello world' -- syntactic sugar for print('hello world')
|
||||
options { verbose=true, debug=true } -- syntactic sugar for options( { ... } )
|
||||
|
||||
Above is often used to create a DSL. For instance, see:
|
||||
|
||||
* `Lua's bug list <https://github.com/lua/lua/blob/master/bugs>`_
|
||||
* `Premake <https://github.com/premake/premake-core/wiki/Your-First-Script>`_ - a tool similar to CMake
|
||||
|
||||
You have already seen that::
|
||||
|
||||
t = { surname = 'majumdar' } -- t.surname is sugar for t['surname']
|
||||
t.name = 'dibyendu' -- syntactic sugar for t['name'] = 'dibyendu'
|
||||
|
||||
A useful use case for tables is as modules. Thus a standard library module like ``math`` is simply a table of functions. Here is an example::
|
||||
|
||||
module = { print, type }
|
||||
module.print('hello')
|
||||
module.print 'hello'
|
||||
module.type('hello')
|
||||
|
||||
Finally, you can emulate an object oriented syntax using the ``:`` operator::
|
||||
|
||||
x:foo('hello') -- syntactic sugar for foo(x, 'hello')
|
||||
|
||||
As we shall see, this feature enables Lua to support object orientation.
|
||||
|
||||
A Lua script is called a chunk - and is the unit of compilation in Lua
|
||||
======================================================================
|
||||
When you present a script to Lua, it is compiled. The script can be a file or a string. Internally the content of the script is wrapped inside a Lua function. So that means that a script can have ``local`` variables, as these live in the wrapping function.
|
||||
|
||||
It is common practice for scripts to return a table of functions - as then the script can be treated as a module. There is a library function 'require' which loads a script as a module.
|
||||
|
||||
Suppose you have following script saved in a file ``sample.lua``::
|
||||
|
||||
-- sample script
|
||||
local function foo() end
|
||||
local function bar() end
|
||||
|
||||
return { foo=foo, bar=bar } -- i.e. ['foo'] = foo, ['bar'] = bar
|
||||
|
||||
Above script returns a table containing two functions.
|
||||
|
||||
Now another script can load this as follows::
|
||||
|
||||
local sample = require 'sample' -- Will call sample.lua script and save its table of functions
|
||||
|
||||
The library function ``require()`` does more than what is described above, of course. For instance it ensures that the module is only loaded once, and it uses various search paths to locate the script. It can even load C modules. Anyway, now the table returned from
|
||||
the sample script is stored in the local variable 'sample' and we can write::
|
||||
|
||||
sample.foo()
|
||||
sample.bar()
|
||||
|
||||
The Lua stack is a heap allocated structure
|
||||
===========================================
|
||||
Lua's code operates on heap allocated stacks, rather than the native machine stack. Since Lua is also a C library you can think of Lua as a library that manipulates the heap allocated stacks. In particular, Lua's C api exposes the Lua stack, and requires you to push/pop values on the stack; this approach is unique to Lua.
|
||||
|
||||
Lua functions can be yielded from and resumed later
|
||||
===================================================
|
||||
Lua allows functions to be suspended and resumed. The function suspends itself by calling a library function to yield. Sometime later
|
||||
the function may be resumed by the caller or something else - when resumed, the Lua function continues from the point of suspension.
|
||||
|
||||
When yielding you can pass values back to the caller. Similarly when resuming the caller can pass values to the function.
|
||||
|
||||
This is perhaps the most advanced feature in Lua, and not one that can be easily demonstrated in a simple way. Following is the simplest example I could think of.
|
||||
|
||||
::
|
||||
|
||||
function test()
|
||||
local message = coroutine.yield('hello')
|
||||
print(message)
|
||||
end
|
||||
|
||||
-- create a new Lua stack (thread)
|
||||
thread = coroutine.create(test)
|
||||
|
||||
-- start the coroutine
|
||||
status,message = coroutine.resume(thread) -- initial start
|
||||
|
||||
-- coroutine suspended so we have got control back
|
||||
-- the coroutine yielded message to us - lets print it
|
||||
print(message) -- says 'hello', the value returned by yield
|
||||
|
||||
-- Resume the coroutine / send it the message 'world'
|
||||
status,message = coroutine.resume(thread, 'world')
|
||||
|
||||
-- above will print 'world'
|
||||
-- status above will be true
|
||||
-- but now the coroutine has ended so further calls to resume will return status as false
|
||||
|
||||
By the fact that 'hello' is printed before 'world' we can tell that the coroutine was suspended and then resumed.
|
||||
|
||||
In the Lua documentation, the return value from ``coroutine.create()`` is called a ``thread``. However don't confuse this with threads as in C++ or Java. You can think of a Lua ``thread`` as just another Lua stack. Basically whenever Lua executes any code - the code operates on a Lua stack. Initially there is only one stack (main thread). When you create a coroutine, a new stack is allocated, and the all functions called from the coroutine will operate on this new stack. Since the Lua stack is a heap allocated structure - suspending the coroutine is equivalent to returning back to the caller using a ``longjmp()``. The stack is preserved, so that the function that yielded can be resumed later from wherever it suspended itself.
|
||||
|
||||
There is no automatic scheduling of Lua coroutines, a coroutine has to be explicitly resumed by the program.
|
||||
|
||||
Note also that Lua is single threaded - so you cannot execute the different Lua stacks in parallel in multiple OS threads; a particular Lua instance always runs in a single OS thread. At any point in time only one Lua stack can be active.
|
||||
|
||||
Lua's error handling is based on C setjmp/longjmp
|
||||
=================================================
|
||||
You raise an error in Lua by calling library functions ``error()`` or ``assert()``. Lua library functions can also raise errors. When an error is raised Lua does a C ``longjmp`` to the nearest location in the call stack where the caller used a 'protected call'. A 'protected call' is a function calling mechanism that does a C ``setjmp``.
|
||||
|
||||
Here is how a protected call is done::
|
||||
|
||||
function foo(message)
|
||||
-- raise error if message is nil
|
||||
if not message then
|
||||
error('message expected')
|
||||
else
|
||||
print(message)
|
||||
return 4.2
|
||||
end
|
||||
end
|
||||
|
||||
-- call foo('hello') in protected mode
|
||||
-- this is done using the Lua library function pcall()
|
||||
status,returnvalue = pcall(foo, 'hello')
|
||||
|
||||
-- since this call should succeed, status will be true
|
||||
-- returnvalue should contain 4.2
|
||||
assert(returnvalue == 4.2)
|
||||
|
||||
-- call foo() without arguments in protected mode
|
||||
status, returnvalue = pcall(foo)
|
||||
-- above will fail and status will be false
|
||||
-- But returnvalue will now have the error message
|
||||
|
||||
assert(not status)
|
||||
print(returnvalue)
|
||||
-- above prints 'message expected'
|
||||
|
||||
The Lua error handling mechanism has following issues:
|
||||
|
||||
* The code that can raise errors must be encapsulated in a function as ``pcall()`` can only call functions
|
||||
* The return values from ``pcall()`` depend upon whether the call terminated normally or due to an error - so caller needs to check the status of the call and only then proceed
|
||||
* On raising an error the ``longjmp`` unwinds the stack - there is no mechanism for any intermediate objects to perform cleanup as is possible in C++ using destructors, or in Java, C++, Python using ``finally`` blocks, or as done by the ``defer`` statement in Go
|
||||
* You can setup a finalizer on Lua user types that will eventually execute when the value is garbage collected - this is typically used to free up memory used by the value - but you have no control over when the finalizer will run, hence relying upon finalizers for cleanup is problematic
|
||||
|
||||
Lua is single threaded but each OS thread can be given its own Lua VM
|
||||
=====================================================================
|
||||
All of Lua's VM is encapsulated in a single data structure - the Lua State. Lua does not have global state. Thus, you can create as many Lua instances in a single process as you want. Since the VM is so small it is quite feasible to allocate a Lua VM per OS thread.
|
||||
|
||||
Lua has a meta mechanism that enables a DIY class / object system
|
||||
=================================================================
|
||||
Firstly simple object oriented method calls can be emulated in Lua by relying upon the ``:`` operator described earlier. Recollect that::
|
||||
|
||||
object:method(arg) -- is syntactic sugar for method(object, arg)
|
||||
|
||||
The next bit of syntactic sugar is shown below::
|
||||
|
||||
object = {}
|
||||
function object:method(arg)
|
||||
print('method called with ', self, arg) -- self is automatic parameter and is really object
|
||||
end
|
||||
|
||||
Above is syntactic sugar for following equivalent code::
|
||||
|
||||
object = {}
|
||||
object.method = function(self, arg)
|
||||
print('method called with ', self, arg)
|
||||
end
|
||||
|
||||
As the object is passed as the ``self`` argument, the method can access other properties and methods contained in the object, which is just a normal table.
|
||||
|
||||
::
|
||||
|
||||
object:method('hello') -- calls method(object, 'hello')
|
||||
|
||||
This mechanism is fine for Lua code but doesn't work for user defined values created in C. Lua supports another more sophisticated approach that makes use of a facility in Lua called metatables. A ``metatable`` is simply an ordinary table that you can associate with any table or user defined type created in C code. The advantage of using the ``metatable`` approach is that it also works for user defined types created in C code. Here we will look at how it can be applied to Lua code.
|
||||
|
||||
Keeping to the same example above, this approach requires us to populate a ``metatable`` with the methods. We can think of the ``metatable`` as the class of the object.::
|
||||
|
||||
Class = {} -- our metatable
|
||||
Class.__index = Class -- This is a meta property (see description below)
|
||||
|
||||
-- define method function in Class
|
||||
function Class:method(arg)
|
||||
print('method called with ', self, arg)
|
||||
end
|
||||
|
||||
-- define factory for creating new objects
|
||||
function Class:new()
|
||||
local object = {}
|
||||
setmetatable(object, self)
|
||||
return object
|
||||
end
|
||||
|
||||
* Notice that we set the field ``__index`` in the ``Class`` table to point to itself. This is a special field that Lua recognizes and whenever you access a field in an object, if the field is not found in the object and if the object has a ``metatable`` with ``__index`` field set, the Lua will lookup the field you want in the ``metatable``.
|
||||
* Secondly we set ``Class`` to be the ``metatable`` for the object in the new method.
|
||||
|
||||
As a result of above, in the example below::
|
||||
|
||||
object = Class:new()
|
||||
object:method('hello')
|
||||
|
||||
Lua notices that there is no ``method`` field in object. But object has a ``metatable`` assigned to it, and this has ``__index`` set, so Lua looks up ``Class.__index['method']`` and finds the method.
|
||||
|
||||
Essentially this approach enables the concept of a shared class (e.g. Class in this example) that holds common fields. These fields can be methods or other ordinary values - and since the ``metatable`` is shared by all objects created using the ``Class:new()`` method, then we have a simple OO system!
|
||||
|
||||
This feature can be extended to support inheritance as well, but personally I do not find this useful, and suggest you look up Lua documentation if you want to play with inheritance. My advice is to avoid implementing complex object systems in Lua. However, the ``metatable`` approach is invaluable for user defined types created in C as these types can be used in more typesafe manner by using OO notation.
|
||||
|
||||
|
||||
|
||||
|
@ -1,315 +0,0 @@
|
||||
========================================
|
||||
JIT Compilation for Ravi using ``libgccjit``
|
||||
========================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
The latest `gcc 5.2 release <http://gcc.gnu.org/>`_ contains a new component called ``libgccjit``. This basically exposes an API via a shared library to the compilation functions within gcc.
|
||||
|
||||
I am keen to provide support for this in Ravi. From initial look it seems to contain all the features I need to implement a JIT compiler for Ravi. Obviously having implemented the LLVM version it is going to be a little easier as I can mostly do a port of the LLVM version.
|
||||
|
||||
License
|
||||
-------
|
||||
Ravi itself is licensed under MIT license (including the code that implements the JIT compiler) - however I think that when linked to ``libgccjit`` the effective license will be GPLv3.
|
||||
|
||||
Why another JIT engine?
|
||||
-----------------------
|
||||
Well partly as I feel I have a moral obligation to support gcc, given it has been instrumental in bringing about the OpenSource / Free Software ecosystem.
|
||||
|
||||
Secondly I am always looking for alternatives that will let me reduce the footprint of Ravi. The ``libgccjit`` is offered as a shared library - this is a great thing. I hate to have to statically link LLVM.
|
||||
|
||||
LLVM implementation and ``libgccjit`` implementation will both be kept in sync so that user can choose either option. Right now the LLVM implementation is more advanced and new features are implemented there first and then ported to the ``libgccjit`` implementation.
|
||||
|
||||
Building GCC
|
||||
------------
|
||||
I am running Ubuntu 14.04 LTS on VMWare virtual machine.
|
||||
|
||||
I built gcc 5.2 from source as follows.
|
||||
|
||||
1. Extracted gcc-5.2 source to ``~/gcc-5.2.0``.
|
||||
2. Created a build folder ``~/buildgcc``.
|
||||
3. Installed various pre-requisites for gcc.
|
||||
4. Then ran following from inside the build folder::
|
||||
|
||||
../gcc-5.2.0/configure --prefix=~/local --enable-host-shared --enable-languages=jit,c++ --disable-bootstrap --disable-multilib
|
||||
|
||||
5. Next performed the build as follows::
|
||||
|
||||
make
|
||||
make install
|
||||
|
||||
On Mac OSX Yosemite
|
||||
-------------------
|
||||
It appears that the `HomeBrew <http://brew.sh/>`_ project supports creating the ``libgccjit 5.2`` library. However the default formula doesn't quite work and needs to be patched for libgccjit to work properly. A patched formula can be found at `here <https://github.com/dibyendumajumdar/ravi/blob/master/patches/gcc.rb>`_. To use the patched version edit the gcc formula and copy the patched version. After that following should build and install gcc 5.2 including the JIT library::
|
||||
|
||||
brew install gcc --with-jit --without-multilib
|
||||
|
||||
Current Status
|
||||
--------------
|
||||
Many bytecodes are now compiled - see below for detailed status. The current version of Ravi passes the Lua test cases using ``libgccjit``.
|
||||
|
||||
Building Ravi with ``libgccjit`` on Linux
|
||||
-------------------------------------
|
||||
.. warning:: Note that right now the Ravi's ``libgccjit`` based JIT implementation is work in progress - please expect bugs.
|
||||
|
||||
You can build Ravi with ``libgccjit`` linked in as follows::
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
export LD_LIBRARY_PATH=~/local/lib64:$LD_LIBRARY_PATH
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=~/local/bin/gcc -DCMAKE_CXX_COMPILER=~/local/bin/g++ -DLLVM_DIR=~/LLVM/share/llvm/cmake -DLLVM_JIT=ON -DGCC_JIT=OFF ..
|
||||
make
|
||||
|
||||
Above assumes that gccjit is installed under ``~/local`` as described in Building GCC section above.
|
||||
|
||||
A helloworld test program is built. To run it though you need to ensure that your ``PATH`` and ``LD_LIBRARY_PATH`` variables include ``~/local/bin`` and ``~/local/lib`` respectively.
|
||||
|
||||
Initial Observations
|
||||
--------------------
|
||||
In terms of packaging ``libgccjit`` consists of a C header file, a C++ header file and one shared library. That is pretty neat as it simplifies the usage.
|
||||
|
||||
Setting up of the Lua types is proving easier in ``libgccjit`` due to the fact that Lua uses unions extensively and ``libgccjit`` supports defining union types. This means that most of the Lua types can be translated more naturally. LLVM on the other hand does not support unions so I had to carefully define structs that would match the size of the union, and in the JIT compilation use casts where needed.
|
||||
|
||||
JIT Status of Lua/Ravi Bytecodes
|
||||
---------------------------------
|
||||
Following is the status as of 4 July 2015.
|
||||
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| name | JITed? | description |
|
||||
+=========================+==========+==================================================+
|
||||
| OP_MOVE | YES | R(A) := R(B) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_LOADK | YES | R(A) := Kst(Bx) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_LOADKX | NO | R(A) := Kst(extra arg) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_LOADBOOL | YES | R(A) := (Bool)B; if (C) pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_LOADNIL | YES | R(A), R(A+1), ..., R(A+B) := nil |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_GETUPVAL | YES | R(A) := UpValue[B] |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_GETTABUP | YES | R(A) := UpValue[B][RK(C)] |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_GETTABLE | YES | R(A) := R(B)[RK(C)] |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_SETTABUP | YES | UpValue[A][RK(B)] := RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_SETUPVAL | YES | UpValue[B] := R(A) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_SETTABLE | YES | R(A)[RK(B)] := RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_NEWTABLE | YES | R(A) := {} (size = B,C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_SELF | YES | R(A+1) := R(B); R(A) := R(B)[RK(C)] |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_ADD | YES | R(A) := RK(B) + RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_SUB | YES | R(A) := RK(B) - RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_MUL | YES | R(A) := RK(B) * RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_MOD | NO | R(A) := RK(B) % RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_POW | NO | R(A) := RK(B) ^ RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_DIV | YES | R(A) := RK(B) / RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_IDIV | NO | R(A) := RK(B) // RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_BAND | NO | R(A) := RK(B) & RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_BOR | NO | R(A) := RK(B) | RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_BXOR | NO | R(A) := RK(B) ~ RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_SHL | NO | R(A) := RK(B) << RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_SHR | NO | R(A) := RK(B) >> RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_UNM | NO | R(A) := -R(B) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_BNOT | NO | R(A) := ~R(B) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_NOT | YES | R(A) := not R(B) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_LEN | YES | R(A) := length of R(B) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_CONCAT | YES | R(A) := R(B).. ... ..R(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_JMP | YES | c+=sBx; if (A) close all upvalues >= R(A - 1) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_EQ | YES | if ((RK(B) == RK(C)) ~= A) then pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_LT | YES | if ((RK(B) < RK(C)) ~= A) then pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_LE | YES | if ((RK(B) <= RK(C)) ~= A) then pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_TEST | YES | if not (R(A) <=> C) then pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_TESTSET | YES | if (R(B) <=> C) then R(A) := R(B) else pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_CALL | YES | R(A), .. ,R(A+C-2) := R(A)(R(A+1), .. ,R(A+B-1)) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_TAILCALL | YES | return R(A)(R(A+1), ... ,R(A+B-1)) |
|
||||
| | | Compiled as OP_CALL so no tail call optimization |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RETURN | YES | return R(A), ... ,R(A+B-2) (see note) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_FORLOOP | NO | R(A)+=R(A+2); |
|
||||
| | | if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) } |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_FORPREP | NO | R(A)-=R(A+2); pc+=sBx |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_TFORCALL | YES | R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_TFORLOOP | YES | if R(A+1) ~= nil then { R(A)=R(A+1); pc += sBx } |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_SETLIST | YES | R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_CLOSURE | YES | R(A) := closure(KPROTO[Bx]) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_VARARG | YES | R(A), R(A+1), ..., R(A+B-2) = vararg |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_EXTRAARG | N/A | extra (larger) argument for previous opcode |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_NEWARRAYI | YES | R(A) := array of int |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_NEWARRAYF | YES | R(A) := array of float |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_LOADIZ | YES | R(A) := tointeger(0) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_LOADFZ | YES | R(A) := tonumber(0) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_ADDFF | YES | R(A) := RK(B) + RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_ADDFI | YES | R(A) := RK(B) + RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_ADDII | YES | R(A) := RK(B) + RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SUBFF | YES | R(A) := RK(B) - RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SUBFI | YES | R(A) := RK(B) - RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SUBIF | YES | R(A) := RK(B) - RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SUBII | YES | R(A) := RK(B) - RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_MULFF | YES | R(A) := RK(B) * RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_MULFI | YES | R(A) := RK(B) * RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_MULII | YES | R(A) := RK(B) * RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_DIVFF | YES | R(A) := RK(B) / RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_DIVFI | YES | R(A) := RK(B) / RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_DIVIF | YES | R(A) := RK(B) / RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_DIVII | YES | R(A) := RK(B) / RK(C) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_TOINT | YES | R(A) := toint(R(A)) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_TOFLT | YES | R(A) := tofloat(R(A)) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_TOARRAYI | YES | R(A) := to_arrayi(R(A)) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_TOARRAYF | YES | R(A) := to_arrayf(R(A)) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_MOVEI | YES | R(A) := R(B), check R(B) is integer |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_MOVEF | YES | R(A) := R(B), check R(B) is number |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_MOVEAI | YES | R(A) := R(B), check R(B) is array of integer |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_MOVEAF | YES | R(A) := R(B), check R(B) is array of numbers |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_GETTABLE_AI | YES | R(A) := R(B)[RK(C)] where R(B) is array of |
|
||||
| | | integers and RK(C) is integer |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_GETTABLE_AF | YES | R(A) := R(B)[RK(C)] where R(B) is array of |
|
||||
| | | numbers and RK(C) is integer |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SETTABLE_AI | YES | R(A)[RK(B)] := RK(C) where RK(B) is an integer |
|
||||
| | | R(A) is array of integers, and RK(C) is an int |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SETTABLE_AF | YES | R(A)[RK(B)] := RK(C) where RK(B) is an integer |
|
||||
| | | R(A) is array of numbers, and RK(C) is a number |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_FORLOOP_IP | YES | R(A)+=R(A+2); |
|
||||
| | | if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) } |
|
||||
| | | Specialization for integer step > 1 |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_FORPREP_IP | YES | R(A)-=R(A+2); pc+=sBx |
|
||||
| | | Specialization for integer step > 1 |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_FORLOOP_I1 | YES | R(A)+=R(A+2); |
|
||||
| | | if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) } |
|
||||
| | | Specialization for integer step == 1 |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_FORPREP_I1 | YES | R(A)-=R(A+2); pc+=sBx |
|
||||
| | | Specialization for integer step == 1 |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SETUPVALI | NO | UpValue[B] := tointeger(R(A)) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SETUPVALF | NO | UpValue[B] := tonumber(R(A)) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SETUPVALAI | NO | UpValue[B] := toarrayint(R(A)) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SETUPVALAF | NO | UpValue[B] := toarrayflt(R(A)) |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SETTABLE_AII | YES | R(A)[RK(B)] := RK(C) where RK(B) is an integer |
|
||||
| | | R(A) is array of integers, and RK(C) is an int |
|
||||
| | | No conversion as input is known to be int |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SETTABLE_AFF | YES | R(A)[RK(B)] := RK(C) where RK(B) is an integer |
|
||||
| | | R(A) is array of numbers, and RK(C) is a number |
|
||||
| | | No conversion as input is known to be float |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_BAND_II | NO | R(A) := RK(B) & RK(C), operands are int |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_BOR_II | NO | R(A) := RK(B) | RK(C), operands are int |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_BXOR_II | NO | R(A) := RK(B) ~ RK(C), operands are int |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SHL_II | NO | R(A) := RK(B) << RK(C), operands are int |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_SHR_II | NO | R(A) := RK(B) >> RK(C), operands are int |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_BNOT_I | NO | R(A) := ~R(B), int operand |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_EQ_II | YES | if ((RK(B) == RK(C)) ~= A) then pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_EQ_FF | YES | if ((RK(B) == RK(C)) ~= A) then pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_LT_II | YES | if ((RK(B) < RK(C)) ~= A) then pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_LT_FF | YES | if ((RK(B) < RK(C)) ~= A) then pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_LE_II | YES | if ((RK(B) <= RK(C)) ~= A) then pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
| OP_RAVI_LE_FF | YES | if ((RK(B) <= RK(C)) ~= A) then pc++ |
|
||||
+-------------------------+----------+--------------------------------------------------+
|
||||
|
||||
Ravi's libgccjit JIT compiler source
|
||||
------------------------------------
|
||||
The libgccjit JIT implementation is in following sources:
|
||||
|
||||
* ravijit.h - defines the JIT API
|
||||
* ravi_gccjit.h - defines the types used by the code generator, and declares prototypes
|
||||
|
||||
* ravijit.cpp - basic JIT infrastructure and Ravi API definition
|
||||
* ravi_gcctypes.c - contains JIT type definitions for Lua objects
|
||||
* ravi_gcccodegen.c - JIT compiler - main driver for compiling Lua bytecodes
|
||||
* ravi_gccload.c - implements OP_LOADK and OP_MOVE, and related operations, also OP_LOADBOOL
|
||||
* ravi_gcccomp.c - implements OP_EQ, OP_LT, OP_LE, OP_TEST and OP_TESTSET.
|
||||
* ravi_gccreturn.c - implements OP_RETURN
|
||||
* ravi_gccforprep.c - implements OP_RAVI_FORPREP_I1 and OP_RAVI_FORPREP_IP
|
||||
* ravi_gccforloop.c - implements OP_RAVI_FORLOOP_I1 and OP_RAVI_FORLOOP_IP
|
||||
* ravi_gcctforcall.c - implements OP_TFORCALL and OP_TFORLOOP
|
||||
* ravi_gccarith1.c - implements various type specialized arithmetic operations - these are Ravi extensions
|
||||
* ravi_gccarith2.c - implements Lua opcodes such as OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_UNM
|
||||
* ravi_gcccall.c - implements OP_CALL, OP_JMP
|
||||
* ravi_gcctable.c - implements OP_GETTABLE, OP_SETTABLE and various other table operations, OP_SELF, and also upvalue operations
|
||||
* ravi_gccrest.c - OP_CLOSURE, OP_VARARG, OP_CONCAT
|
@ -0,0 +1,357 @@
|
||||
# Makefile for building Ravi based on Lua Makefile
|
||||
# This Makefile builds an interpreter only version right now - no JIT
|
||||
|
||||
# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
|
||||
|
||||
# Your platform. See PLATS for possible values.
|
||||
PLAT= none
|
||||
|
||||
#CC= gcc -std=gnu99
|
||||
CFLAGS= -O2 -Wall -Wextra -DLUA_COMPAT_5_2 -DLUA_COMPAT_5_1 $(SYSCFLAGS) $(MYCFLAGS) -I../include
|
||||
CXXFLAGS=$(CFLAGS) -fno-rtti -Wno-sign-compare -std=c++14 -fno-exceptions -I../include
|
||||
LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS)
|
||||
LIBS= -lm $(SYSLIBS) $(MYLIBS)
|
||||
VPATH=../include
|
||||
|
||||
AR= ar rcu
|
||||
RANLIB= ranlib
|
||||
RM= rm -f
|
||||
|
||||
SYSCFLAGS=
|
||||
SYSLDFLAGS=
|
||||
SYSLIBS=
|
||||
|
||||
MYCFLAGS=
|
||||
MYLDFLAGS=
|
||||
MYLIBS=
|
||||
MYOBJS=
|
||||
|
||||
# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
|
||||
|
||||
PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
|
||||
|
||||
LUA_A= libravinojit.a
|
||||
CORE_CPP_O=ravijit.o
|
||||
CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \
|
||||
lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \
|
||||
ltm.o lundump.o lvm.o lzio.o ravi_profile.o ravi_membuf.o \
|
||||
ravi_jitshared.o ravi_nojit.o $(CORE_CPP_O)
|
||||
LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \
|
||||
lmathlib.o loslib.o lstrlib.o ltablib.o lutf8lib.o loadlib.o linit.o \
|
||||
bit.o
|
||||
BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS)
|
||||
|
||||
LUA_T= ravi
|
||||
LUA_O= lua.o
|
||||
|
||||
ALL_O= $(BASE_O) $(LUA_O)
|
||||
ALL_T= $(LUA_A) $(LUA_T)
|
||||
ALL_A= $(LUA_A)
|
||||
|
||||
# Targets start here.
|
||||
default: $(PLAT)
|
||||
|
||||
all: $(ALL_T)
|
||||
|
||||
o: $(ALL_O)
|
||||
|
||||
a: $(ALL_A)
|
||||
|
||||
$(LUA_A): $(BASE_O)
|
||||
$(AR) $@ $(BASE_O)
|
||||
$(RANLIB) $@
|
||||
|
||||
$(LUA_T): $(LUA_O) $(LUA_A)
|
||||
$(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) $(ALL_T) $(ALL_O)
|
||||
|
||||
depend:
|
||||
@$(CC) $(CFLAGS) -MM *.c
|
||||
@$(CC) $(CXXFLAGS) -MM ravijit.cpp
|
||||
|
||||
echo:
|
||||
@echo "PLAT= $(PLAT)"
|
||||
@echo "CC= $(CC)"
|
||||
@echo "CFLAGS= $(CFLAGS)"
|
||||
@echo "LDFLAGS= $(SYSLDFLAGS)"
|
||||
@echo "LIBS= $(LIBS)"
|
||||
@echo "AR= $(AR)"
|
||||
@echo "RANLIB= $(RANLIB)"
|
||||
@echo "RM= $(RM)"
|
||||
|
||||
# Convenience targets for popular platforms
|
||||
ALL= all
|
||||
|
||||
none:
|
||||
@echo "Please do 'make PLATFORM' where PLATFORM is one of these:"
|
||||
@echo " $(PLATS)"
|
||||
|
||||
aix:
|
||||
$(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall"
|
||||
|
||||
bsd:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E"
|
||||
|
||||
c89:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_C89" CC="gcc -std=c89"
|
||||
@echo ''
|
||||
@echo '*** C89 does not guarantee 64-bit integers for Lua.'
|
||||
@echo ''
|
||||
|
||||
|
||||
freebsd:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -lreadline"
|
||||
|
||||
generic: $(ALL)
|
||||
|
||||
linux:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline"
|
||||
|
||||
macosx:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc
|
||||
|
||||
mingw:
|
||||
$(MAKE) "LUA_A=ravi.dll" "LUA_T=ravi.exe" \
|
||||
"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
|
||||
"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" ravi.exe
|
||||
|
||||
posix:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX"
|
||||
|
||||
solaris:
|
||||
$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN -D_REENTRANT" SYSLIBS="-ldl"
|
||||
|
||||
# list targets that do not create files (but not all makes understand .PHONY)
|
||||
.PHONY: all $(PLATS) default o a clean depend echo none
|
||||
|
||||
# DO NOT DELETE
|
||||
|
||||
bit.o: bit.c ../include/lua.h ../include/luaconf.h ../include/lauxlib.h \
|
||||
../include/lua.h
|
||||
lapi.o: lapi.c ../include/lprefix.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/lapi.h ../include/llimits.h ../include/lua.h \
|
||||
../include/lstate.h ../include/lobject.h ../include/ltm.h \
|
||||
../include/lzio.h ../include/lmem.h ../include/ldebug.h ../include/ldo.h \
|
||||
../include/lfunc.h ../include/lgc.h ../include/lmem.h \
|
||||
../include/lobject.h ../include/lstate.h ../include/lstring.h \
|
||||
../include/lgc.h ../include/ltable.h ../include/ltm.h \
|
||||
../include/lundump.h ../include/lvm.h ../include/ldo.h
|
||||
lauxlib.o: lauxlib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h
|
||||
lbaselib.o: lbaselib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
lbitlib.o: lbitlib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
lcode.o: lcode.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lcode.h ../include/llex.h \
|
||||
../include/lobject.h ../include/llimits.h ../include/lua.h \
|
||||
../include/lzio.h ../include/lmem.h ../include/lopcodes.h \
|
||||
../include/lparser.h ../include/ldebug.h ../include/lstate.h \
|
||||
../include/ltm.h ../include/ldo.h ../include/lgc.h ../include/llex.h \
|
||||
../include/lmem.h ../include/lobject.h ../include/lopcodes.h \
|
||||
../include/lparser.h ../include/lstring.h ../include/lgc.h \
|
||||
../include/ltable.h ../include/lvm.h ../include/ldo.h
|
||||
lcorolib.o: lcorolib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
lctype.o: lctype.c ../include/lprefix.h ../include/lctype.h \
|
||||
../include/lua.h ../include/luaconf.h ../include/llimits.h
|
||||
ldblib.o: ldblib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
ldebug.o: ldebug.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lapi.h ../include/llimits.h \
|
||||
../include/lua.h ../include/lstate.h ../include/lobject.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h ../include/lcode.h \
|
||||
../include/llex.h ../include/lopcodes.h ../include/lparser.h \
|
||||
../include/ldebug.h ../include/ldo.h ../include/lfunc.h \
|
||||
../include/lobject.h ../include/lopcodes.h ../include/lstate.h \
|
||||
../include/lstring.h ../include/lgc.h ../include/ltable.h \
|
||||
../include/ltm.h ../include/lvm.h ../include/ldo.h
|
||||
ldo.o: ldo.c ../include/lprefix.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/lapi.h ../include/llimits.h ../include/lua.h \
|
||||
../include/lstate.h ../include/lobject.h ../include/ltm.h \
|
||||
../include/lzio.h ../include/lmem.h ../include/ldebug.h ../include/ldo.h \
|
||||
../include/lfunc.h ../include/lgc.h ../include/lmem.h \
|
||||
../include/lobject.h ../include/lopcodes.h ../include/lparser.h \
|
||||
../include/lstate.h ../include/lstring.h ../include/lgc.h \
|
||||
../include/ltable.h ../include/ltm.h ../include/lundump.h \
|
||||
../include/lvm.h ../include/ldo.h ../include/lzio.h ../include/ravijit.h \
|
||||
../include/ravi_jitshared.h ../include/lprefix.h ../include/lauxlib.h \
|
||||
../include/ldebug.h ../include/lfunc.h ../include/lopcodes.h \
|
||||
../include/lstring.h ../include/ltable.h ../include/lvm.h \
|
||||
../include/ravi_membuf.h
|
||||
ldump.o: ldump.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lobject.h ../include/llimits.h \
|
||||
../include/lua.h ../include/lstate.h ../include/lobject.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h \
|
||||
../include/lundump.h
|
||||
lfunc.o: lfunc.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lfunc.h ../include/lobject.h \
|
||||
../include/llimits.h ../include/lua.h ../include/lgc.h \
|
||||
../include/lstate.h ../include/ltm.h ../include/lzio.h ../include/lmem.h \
|
||||
../include/lmem.h ../include/lobject.h ../include/lstate.h \
|
||||
../include/ravijit.h
|
||||
lgc.o: lgc.c ../include/lprefix.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/ldebug.h ../include/lstate.h ../include/lua.h \
|
||||
../include/lobject.h ../include/llimits.h ../include/ltm.h \
|
||||
../include/lzio.h ../include/lmem.h ../include/ldo.h ../include/lfunc.h \
|
||||
../include/lgc.h ../include/lmem.h ../include/lobject.h \
|
||||
../include/lstate.h ../include/lstring.h ../include/lgc.h \
|
||||
../include/ltable.h ../include/ltm.h
|
||||
linit.o: linit.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lualib.h ../include/lua.h \
|
||||
../include/lauxlib.h
|
||||
liolib.o: liolib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
llex.o: llex.c ../include/lprefix.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/lctype.h ../include/lua.h ../include/llimits.h \
|
||||
../include/ldebug.h ../include/lstate.h ../include/lobject.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h ../include/ldo.h \
|
||||
../include/lgc.h ../include/llex.h ../include/lobject.h \
|
||||
../include/lparser.h ../include/lstate.h ../include/lstring.h \
|
||||
../include/lgc.h ../include/ltable.h ../include/lzio.h
|
||||
lmathlib.o: lmathlib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
lmem.o: lmem.c ../include/lprefix.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/ldebug.h ../include/lstate.h ../include/lua.h \
|
||||
../include/lobject.h ../include/llimits.h ../include/ltm.h \
|
||||
../include/lzio.h ../include/lmem.h ../include/ldo.h ../include/lgc.h \
|
||||
../include/lmem.h ../include/lobject.h ../include/lstate.h
|
||||
loadlib.o: loadlib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
lobject.o: lobject.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lctype.h ../include/lua.h \
|
||||
../include/llimits.h ../include/ldebug.h ../include/lstate.h \
|
||||
../include/lobject.h ../include/ltm.h ../include/lzio.h \
|
||||
../include/lmem.h ../include/ldo.h ../include/lmem.h \
|
||||
../include/lobject.h ../include/lstate.h ../include/lstring.h \
|
||||
../include/lgc.h ../include/lvm.h ../include/ldo.h
|
||||
lopcodes.o: lopcodes.c ../include/lprefix.h ../include/lopcodes.h \
|
||||
../include/llimits.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/lobject.h ../include/lstate.h ../include/lobject.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h ../include/ldebug.h \
|
||||
../include/lstate.h
|
||||
loslib.o: loslib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
lparser.o: lparser.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lcode.h ../include/llex.h \
|
||||
../include/lobject.h ../include/llimits.h ../include/lua.h \
|
||||
../include/lzio.h ../include/lmem.h ../include/lopcodes.h \
|
||||
../include/lparser.h ../include/ldebug.h ../include/lstate.h \
|
||||
../include/ltm.h ../include/ldo.h ../include/lfunc.h ../include/llex.h \
|
||||
../include/lmem.h ../include/lobject.h ../include/lopcodes.h \
|
||||
../include/lparser.h ../include/lstate.h ../include/lstring.h \
|
||||
../include/lgc.h ../include/ltable.h
|
||||
lstate.o: lstate.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lapi.h ../include/llimits.h \
|
||||
../include/lua.h ../include/lstate.h ../include/lobject.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h ../include/ldebug.h \
|
||||
../include/ldo.h ../include/lfunc.h ../include/lgc.h ../include/llex.h \
|
||||
../include/lmem.h ../include/lstate.h ../include/lstring.h \
|
||||
../include/lgc.h ../include/ltable.h ../include/ltm.h \
|
||||
../include/ravijit.h ../include/ravi_profile.h ../include/lopcodes.h
|
||||
lstring.o: lstring.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/ldebug.h ../include/lstate.h \
|
||||
../include/lua.h ../include/lobject.h ../include/llimits.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h ../include/ldo.h \
|
||||
../include/lmem.h ../include/lobject.h ../include/lstate.h \
|
||||
../include/lstring.h ../include/lgc.h
|
||||
lstrlib.o: lstrlib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
ltable.o: ltable.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/ldebug.h ../include/lstate.h \
|
||||
../include/lua.h ../include/lobject.h ../include/llimits.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h ../include/ldo.h \
|
||||
../include/lgc.h ../include/lmem.h ../include/lobject.h \
|
||||
../include/lstate.h ../include/lstring.h ../include/lgc.h \
|
||||
../include/ltable.h ../include/lvm.h ../include/ldo.h
|
||||
ltablib.o: ltablib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
ltests.o: ltests.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lapi.h ../include/llimits.h \
|
||||
../include/lua.h ../include/lstate.h ../include/lobject.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h \
|
||||
../include/lauxlib.h ../include/lcode.h ../include/llex.h \
|
||||
../include/lopcodes.h ../include/lparser.h ../include/lctype.h \
|
||||
../include/ldebug.h ../include/ldo.h ../include/lfunc.h \
|
||||
../include/lmem.h ../include/lopcodes.h ../include/lstate.h \
|
||||
../include/lstring.h ../include/lgc.h ../include/ltable.h \
|
||||
../include/lualib.h
|
||||
ltm.o: ltm.c ../include/lprefix.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/ldebug.h ../include/lstate.h ../include/lua.h \
|
||||
../include/lobject.h ../include/llimits.h ../include/ltm.h \
|
||||
../include/lzio.h ../include/lmem.h ../include/ldo.h \
|
||||
../include/lobject.h ../include/lstate.h ../include/lstring.h \
|
||||
../include/lgc.h ../include/ltable.h ../include/ltm.h ../include/lvm.h \
|
||||
../include/ldo.h
|
||||
lua.o: lua.c ../include/lprefix.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/lauxlib.h ../include/lua.h ../include/lualib.h
|
||||
luac.o: luac.c ../include/lprefix.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/lauxlib.h ../include/lua.h ../include/lobject.h \
|
||||
../include/llimits.h ../include/lstate.h ../include/lobject.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h \
|
||||
../include/lundump.h ../include/ldebug.h ../include/lstate.h \
|
||||
../include/lopcodes.h
|
||||
lundump.o: lundump.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/ldebug.h ../include/lstate.h \
|
||||
../include/lua.h ../include/lobject.h ../include/llimits.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h ../include/ldo.h \
|
||||
../include/lfunc.h ../include/lmem.h ../include/lobject.h \
|
||||
../include/lstring.h ../include/lgc.h ../include/lundump.h \
|
||||
../include/lzio.h
|
||||
lutf8lib.o: lutf8lib.c ../include/lprefix.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/lualib.h
|
||||
lvm.o: lvm.c ../include/lprefix.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/ldebug.h ../include/lstate.h ../include/lua.h \
|
||||
../include/lobject.h ../include/llimits.h ../include/ltm.h \
|
||||
../include/lzio.h ../include/lmem.h ../include/ldo.h ../include/lfunc.h \
|
||||
../include/lgc.h ../include/lobject.h ../include/lopcodes.h \
|
||||
../include/lstate.h ../include/lstring.h ../include/lgc.h \
|
||||
../include/ltable.h ../include/ltm.h ../include/lvm.h ../include/ldo.h \
|
||||
../include/ravi_profile.h ../include/lopcodes.h
|
||||
lzio.o: lzio.c ../include/lprefix.h ../include/lua.h ../include/luaconf.h \
|
||||
../include/llimits.h ../include/lua.h ../include/lmem.h \
|
||||
../include/llimits.h ../include/lstate.h ../include/lobject.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h ../include/lzio.h
|
||||
ravi_jitshared.o: ravi_jitshared.c ../include/ravi_jitshared.h \
|
||||
../include/lprefix.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/ldebug.h ../include/lstate.h \
|
||||
../include/lobject.h ../include/llimits.h ../include/ltm.h \
|
||||
../include/lzio.h ../include/lmem.h ../include/ldo.h ../include/lfunc.h \
|
||||
../include/lopcodes.h ../include/lstring.h ../include/lgc.h \
|
||||
../include/ltable.h ../include/lvm.h ../include/ravi_membuf.h
|
||||
ravi_membuf.o: ravi_membuf.c ../include/ravi_membuf.h
|
||||
ravi_nojit.o: ravi_nojit.c ../include/ravijit.h \
|
||||
../include/ravi_jitshared.h ../include/lprefix.h ../include/lauxlib.h \
|
||||
../include/lua.h ../include/luaconf.h ../include/ldebug.h \
|
||||
../include/lstate.h ../include/lobject.h ../include/llimits.h \
|
||||
../include/ltm.h ../include/lzio.h ../include/lmem.h ../include/ldo.h \
|
||||
../include/lfunc.h ../include/lopcodes.h ../include/lstring.h \
|
||||
../include/lgc.h ../include/ltable.h ../include/lvm.h \
|
||||
../include/ravi_membuf.h
|
||||
ravi_profile.o: ravi_profile.c ../include/ravi_profile.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/lopcodes.h ../include/llimits.h \
|
||||
../include/lstate.h ../include/lobject.h ../include/ltm.h \
|
||||
../include/lzio.h ../include/lmem.h
|
||||
ravijit.o: ravijit.cpp ../include/ravijit.h ../include/ravi_jitshared.h \
|
||||
../include/lprefix.h ../include/lauxlib.h ../include/lua.h \
|
||||
../include/luaconf.h ../include/ldebug.h ../include/lstate.h \
|
||||
../include/lobject.h ../include/llimits.h ../include/ltm.h \
|
||||
../include/lzio.h ../include/lmem.h ../include/ldo.h ../include/lfunc.h \
|
||||
../include/lopcodes.h ../include/lstring.h ../include/lgc.h \
|
||||
../include/ltable.h ../include/lvm.h ../include/ravi_membuf.h \
|
||||
../include/lapi.h ../include/lauxlib.h ../include/lfunc.h \
|
||||
../include/lobject.h ../include/lopcodes.h ../include/lstate.h \
|
||||
../include/lua.h
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
** Lua BitOp -- a bit operations library for Lua 5.1/5.2.
|
||||
** http://bitop.luajit.org/
|
||||
**
|
||||
** Copyright (C) 2008-2012 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 ]
|
||||
*/
|
||||
|
||||
#define LUA_BITOP_VERSION "1.0.2"
|
||||
|
||||
#define LUA_LIB
|
||||
#include "lua.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int32_t SBits;
|
||||
typedef uint32_t UBits;
|
||||
|
||||
/* Convert argument to bit type. */
|
||||
static inline UBits barg(lua_State *L, int idx)
|
||||
{
|
||||
return (UBits)luaL_checkinteger(L, idx);
|
||||
}
|
||||
|
||||
/* Return bit type. */
|
||||
#define BRET(b) lua_pushinteger(L, (lua_Integer)(SBits)(b)); return 1;
|
||||
|
||||
static int bit_tobit(lua_State *L) { BRET(barg(L, 1)) }
|
||||
static int bit_bnot(lua_State *L) { BRET(~barg(L, 1)) }
|
||||
|
||||
#define BIT_OP(func, opr) \
|
||||
static int func(lua_State *L) { int i; UBits b = barg(L, 1); \
|
||||
for (i = lua_gettop(L); i > 1; i--) b opr barg(L, i); BRET(b) }
|
||||
BIT_OP(bit_band, &=)
|
||||
BIT_OP(bit_bor, |=)
|
||||
BIT_OP(bit_bxor, ^=)
|
||||
|
||||
#define bshl(b, n) (b << n)
|
||||
#define bshr(b, n) (b >> n)
|
||||
#define bsar(b, n) ((SBits)b >> n)
|
||||
#define brol(b, n) ((b << n) | (b >> (32-n)))
|
||||
#define bror(b, n) ((b << (32-n)) | (b >> n))
|
||||
#define BIT_SH(func, fn) \
|
||||
static int func(lua_State *L) { \
|
||||
UBits b = barg(L, 1); UBits n = barg(L, 2) & 31; BRET(fn(b, n)) }
|
||||
BIT_SH(bit_lshift, bshl)
|
||||
BIT_SH(bit_rshift, bshr)
|
||||
BIT_SH(bit_arshift, bsar)
|
||||
BIT_SH(bit_rol, brol)
|
||||
BIT_SH(bit_ror, bror)
|
||||
|
||||
static int bit_bswap(lua_State *L)
|
||||
{
|
||||
UBits b = barg(L, 1);
|
||||
b = (b >> 24) | ((b >> 8) & 0xff00) | ((b & 0xff00) << 8) | (b << 24);
|
||||
BRET(b)
|
||||
}
|
||||
|
||||
static int bit_tohex(lua_State *L)
|
||||
{
|
||||
UBits b = barg(L, 1);
|
||||
SBits n = lua_isnone(L, 2) ? 8 : (SBits)barg(L, 2);
|
||||
const char *hexdigits = "0123456789abcdef";
|
||||
char buf[8];
|
||||
int i;
|
||||
if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }
|
||||
if (n > 8) n = 8;
|
||||
for (i = (int)n; --i >= 0; ) { buf[i] = hexdigits[b & 15]; b >>= 4; }
|
||||
lua_pushlstring(L, buf, (size_t)n);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct luaL_Reg bit_funcs[] = {
|
||||
{ "tobit", bit_tobit },
|
||||
{ "bnot", bit_bnot },
|
||||
{ "band", bit_band },
|
||||
{ "bor", bit_bor },
|
||||
{ "bxor", bit_bxor },
|
||||
{ "lshift", bit_lshift },
|
||||
{ "rshift", bit_rshift },
|
||||
{ "arshift", bit_arshift },
|
||||
{ "rol", bit_rol },
|
||||
{ "ror", bit_ror },
|
||||
{ "bswap", bit_bswap },
|
||||
{ "tohex", bit_tohex },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
/* Signed right-shifts are implementation-defined per C89/C99.
|
||||
** But the de facto standard are arithmetic right-shifts on two's
|
||||
** complement CPUs. This behaviour is required here, so test for it.
|
||||
*/
|
||||
#define BAD_SAR (bsar(-8, 2) != (SBits)-2)
|
||||
|
||||
LUALIB_API int luaopen_bit(lua_State *L)
|
||||
{
|
||||
UBits b;
|
||||
lua_pushnumber(L, (lua_Number)1437217655L);
|
||||
b = barg(L, -1);
|
||||
if (b != (UBits)1437217655L || BAD_SAR) { /* Perform a simple self-test. */
|
||||
const char *msg = "compiled with incompatible luaconf.h";
|
||||
if (BAD_SAR)
|
||||
msg = "arithmetic right-shift broken";
|
||||
luaL_error(L, "bit library self-test failed (%s)", msg);
|
||||
}
|
||||
luaL_newlib(L, bit_funcs);
|
||||
return 1;
|
||||
}
|
||||
|
@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Sparse c2xml
|
||||
*
|
||||
* Dumps the parse tree as an xml document
|
||||
*
|
||||
* Copyright (C) 2007 Rob Taylor
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <allocate.h>
|
||||
#include <dmr_c.h>
|
||||
#include <expression.h>
|
||||
#include <parse.h>
|
||||
#include <port.h>
|
||||
#include <symbol.h>
|
||||
#include <token.h>
|
||||
#include <scope.h>
|
||||
|
||||
#define LUA_LIB
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
|
||||
struct parser_state {
|
||||
lua_State *L;
|
||||
struct dmr_C *C;
|
||||
struct allocator int_allocator;
|
||||
int idcount;
|
||||
int tabidx;
|
||||
int stack[30];
|
||||
int stackpos;
|
||||
};
|
||||
|
||||
static void push_tabindex(struct parser_state *S)
|
||||
{
|
||||
assert(S->stackpos >= -1 && S->stackpos < 28);
|
||||
S->stackpos++;
|
||||
S->stack[S->stackpos] = S->tabidx;
|
||||
S->tabidx = 1;
|
||||
}
|
||||
|
||||
static void pop_tabindex(struct parser_state *S)
|
||||
{
|
||||
assert(S->stackpos >= 0);
|
||||
S->tabidx = S->stack[S->stackpos];
|
||||
S->stackpos--;
|
||||
}
|
||||
|
||||
static void *visited(struct parser_state *S, int id) {
|
||||
int *p = (int *)dmrC_allocator_allocate(&S->int_allocator, 0);
|
||||
*p = id;
|
||||
return p;
|
||||
}
|
||||
|
||||
static void examine_symbol(struct parser_state *S, struct symbol *sym);
|
||||
|
||||
static void newProp(struct parser_state *S, const char *name, const char *value)
|
||||
{
|
||||
lua_pushstring(S->L, name);
|
||||
lua_pushstring(S->L, value);
|
||||
lua_settable(S->L, -3);
|
||||
}
|
||||
|
||||
static void newNumProp(struct parser_state *S, const char *name, int value)
|
||||
{
|
||||
lua_pushstring(S->L, name);
|
||||
lua_pushinteger(S->L, value);
|
||||
lua_settable(S->L, -3);
|
||||
}
|
||||
|
||||
static void newIdProp(struct parser_state *S, const char *name, unsigned int id)
|
||||
{
|
||||
char buf[256];
|
||||
snprintf(buf, 256, "_%d", id);
|
||||
newProp(S, name, buf);
|
||||
}
|
||||
|
||||
static void popNamedTable(struct parser_state *S, const char *name)
|
||||
{
|
||||
lua_assert(lua_istable(S->L, -1));
|
||||
lua_assert(lua_istable(S->L, -2));
|
||||
pop_tabindex(S);
|
||||
lua_pushstring(S->L, name);
|
||||
lua_pushvalue(S->L, -2); /* top table */
|
||||
lua_settable(S->L, -4); /* bottom table */
|
||||
lua_pop(S->L, 1); /* pop top table */
|
||||
}
|
||||
|
||||
static void popTable(struct parser_state *S)
|
||||
{
|
||||
lua_assert(lua_istable(S->L, -1));
|
||||
lua_assert(lua_istable(S->L, -2));
|
||||
pop_tabindex(S);
|
||||
int id = S->tabidx++;
|
||||
lua_seti(S->L, -2, id); /* bottom table */
|
||||
}
|
||||
|
||||
static void new_sym_node(struct parser_state *S, struct symbol *sym, const char *name)
|
||||
{
|
||||
const char *ident = dmrC_show_ident(S->C, sym->ident);
|
||||
|
||||
assert(name != NULL);
|
||||
assert(sym != NULL);
|
||||
|
||||
lua_newtable(S->L);
|
||||
push_tabindex(S);
|
||||
newNumProp(S, "id", S->idcount);
|
||||
newProp(S, "type", name);
|
||||
|
||||
if (sym->ident && ident)
|
||||
newProp(S, "ident", ident);
|
||||
newProp(S, "file", dmrC_stream_name(S->C, sym->pos.stream));
|
||||
|
||||
newNumProp(S, "startline", sym->pos.line);
|
||||
newNumProp(S, "startcol", sym->pos.pos);
|
||||
|
||||
if (sym->endpos.type) {
|
||||
newNumProp(S, "endline", sym->endpos.line);
|
||||
newNumProp(S, "endcol", sym->endpos.pos);
|
||||
if (sym->pos.stream != sym->endpos.stream)
|
||||
newProp(S, "endfile", dmrC_stream_name(S->C, sym->endpos.stream));
|
||||
}
|
||||
sym->aux = visited(S, S->idcount);
|
||||
|
||||
S->idcount++;
|
||||
}
|
||||
|
||||
static void examine_members(struct parser_state *S, struct symbol_list *list)
|
||||
{
|
||||
struct symbol *sym;
|
||||
|
||||
FOR_EACH_PTR(list, sym) {
|
||||
examine_symbol(S, sym);
|
||||
} END_FOR_EACH_PTR(sym);
|
||||
}
|
||||
|
||||
static void examine_modifiers(struct parser_state *S, struct symbol *sym)
|
||||
{
|
||||
struct mod_name {
|
||||
unsigned long mod;
|
||||
const char *name;
|
||||
} * m;
|
||||
|
||||
static struct mod_name mod_names[] = {
|
||||
{MOD_AUTO, "auto"},
|
||||
{MOD_REGISTER, "register"},
|
||||
{MOD_STATIC, "static"},
|
||||
{MOD_EXTERN, "extern"},
|
||||
{MOD_CONST, "const"},
|
||||
{MOD_VOLATILE, "volatile"},
|
||||
{MOD_SIGNED, "signed"},
|
||||
{MOD_UNSIGNED, "unsigned"},
|
||||
{MOD_CHAR, "char"},
|
||||
{MOD_SHORT, "short"},
|
||||
{MOD_LONG, "long"},
|
||||
{MOD_LONGLONG, "long long"},
|
||||
{MOD_LONGLONGLONG, "long long long"},
|
||||
{MOD_TYPEDEF, "typedef"},
|
||||
{MOD_TLS, "tls"},
|
||||
{MOD_INLINE, "inline"},
|
||||
{MOD_ADDRESSABLE, "addressable"},
|
||||
{MOD_NOCAST, "nocast"},
|
||||
{MOD_NODEREF, "noderef"},
|
||||
{MOD_ACCESSED, "accessed"},
|
||||
{MOD_TOPLEVEL, "toplevel"},
|
||||
{MOD_ASSIGNED, "assigned"},
|
||||
{MOD_TYPE, "type"},
|
||||
{MOD_SAFE, "safe"},
|
||||
{MOD_USERTYPE, "usertype"},
|
||||
{MOD_NORETURN, "noreturn"},
|
||||
{MOD_EXPLICITLY_SIGNED, "explicitly-signed"},
|
||||
{MOD_BITWISE, "bitwise"},
|
||||
{MOD_PURE, "pure"},
|
||||
};
|
||||
|
||||
if (sym->ns != NS_SYMBOL)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(mod_names); i++) {
|
||||
m = mod_names + i;
|
||||
if (sym->ctype.modifiers & m->mod) {
|
||||
newNumProp(S, m->name, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (dmrC_is_prototype(sym))
|
||||
newNumProp(S, "prototype", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
examine_layout(struct parser_state *S, struct symbol *sym)
|
||||
{
|
||||
dmrC_examine_symbol_type(S->C->S, sym);
|
||||
|
||||
newNumProp(S, "bitsize", sym->bit_size);
|
||||
newNumProp(S, "alignment", sym->ctype.alignment);
|
||||
newNumProp(S, "offset", sym->offset);
|
||||
if (dmrC_is_bitfield_type(sym)) {
|
||||
newNumProp(S, "bitoffset", sym->bit_offset);
|
||||
}
|
||||
}
|
||||
|
||||
static void examine_symbol(struct parser_state *S, struct symbol *sym)
|
||||
{
|
||||
const char *base;
|
||||
int array_size;
|
||||
|
||||
if (!sym)
|
||||
return;
|
||||
if (sym->aux) /*already visited */
|
||||
return;
|
||||
|
||||
if (sym->ident && sym->ident->reserved)
|
||||
return;
|
||||
|
||||
int savedpos = lua_gettop(S->L);
|
||||
new_sym_node(S, sym, dmrC_get_type_name(sym->type));
|
||||
examine_modifiers(S, sym);
|
||||
examine_layout(S, sym);
|
||||
|
||||
if (sym->ctype.base_type) {
|
||||
if ((base = dmrC_builtin_typename(S->C, sym->ctype.base_type)) == NULL) {
|
||||
if (!sym->ctype.base_type->aux) {
|
||||
examine_symbol(S, sym->ctype.base_type);
|
||||
}
|
||||
newNumProp(S, "basetype", *((int *)sym->ctype.base_type->aux));
|
||||
} else {
|
||||
newProp(S, "builtintype", base);
|
||||
}
|
||||
}
|
||||
if (sym->array_size) {
|
||||
/* TODO: modify dmrC_get_expression_value to give error return */
|
||||
array_size = dmrC_get_expression_value(S->C, sym->array_size);
|
||||
newNumProp(S, "arraysize", array_size);
|
||||
}
|
||||
|
||||
|
||||
switch (sym->type) {
|
||||
case SYM_STRUCT:
|
||||
case SYM_UNION:
|
||||
examine_members(S, sym->symbol_list);
|
||||
break;
|
||||
case SYM_FN: {
|
||||
int savedpos2 = lua_gettop(S->L);
|
||||
lua_newtable(S->L);
|
||||
push_tabindex(S);
|
||||
examine_members(S, sym->arguments);
|
||||
popNamedTable(S, "arguments");
|
||||
//examine_members(C, sym->symbol_list);
|
||||
lua_assert(savedpos2 == lua_gettop(S->L));
|
||||
break;
|
||||
}
|
||||
case SYM_UNINITIALIZED:
|
||||
newProp(S, "builtintype", dmrC_builtin_typename(S->C, sym));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
popTable(S);
|
||||
|
||||
lua_assert(savedpos == lua_gettop(S->L));
|
||||
return;
|
||||
}
|
||||
|
||||
static struct position *get_expansion_end (struct token *token)
|
||||
{
|
||||
struct token *p1, *p2;
|
||||
|
||||
for (p1=NULL, p2=NULL;
|
||||
!dmrC_eof_token(token);
|
||||
p2 = p1, p1 = token, token = token->next);
|
||||
|
||||
if (p2)
|
||||
return &(p2->pos);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void examine_macro(struct parser_state *S, struct symbol *sym)
|
||||
{
|
||||
struct position *pos;
|
||||
|
||||
/* this should probably go in the main codebase*/
|
||||
pos = get_expansion_end(sym->expansion);
|
||||
if (pos)
|
||||
sym->endpos = *pos;
|
||||
else
|
||||
sym->endpos = sym->pos;
|
||||
|
||||
new_sym_node(S, sym, "macro");
|
||||
}
|
||||
|
||||
static void examine_namespace(struct parser_state *S, struct symbol *sym)
|
||||
{
|
||||
if (sym->ident && sym->ident->reserved)
|
||||
return;
|
||||
|
||||
switch(sym->ns) {
|
||||
case NS_MACRO:
|
||||
examine_macro(S, sym);
|
||||
break;
|
||||
case NS_TYPEDEF:
|
||||
case NS_STRUCT:
|
||||
case NS_SYMBOL:
|
||||
examine_symbol(S, sym);
|
||||
break;
|
||||
case NS_NONE:
|
||||
case NS_LABEL:
|
||||
case NS_ITERATOR:
|
||||
case NS_UNDEF:
|
||||
case NS_PREPROCESSOR:
|
||||
case NS_KEYWORD:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
//dmrC_die(S->C, "Unrecognised namespace type %d",sym->ns);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int get_stream_id (struct dmr_C *C, const char *name)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<C->T->input_stream_nr; i++) {
|
||||
if (strcmp(name, dmrC_stream_name(C, i))==0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void examine_symbol_list(struct parser_state *S, int stream_id, struct symbol_list *list)
|
||||
{
|
||||
struct symbol *sym;
|
||||
if (!list)
|
||||
return;
|
||||
FOR_EACH_PTR(list, sym) {
|
||||
if (sym->pos.stream == stream_id)
|
||||
examine_namespace(S, sym);
|
||||
} END_FOR_EACH_PTR(sym);
|
||||
}
|
||||
|
||||
static int dmrC_getsymbols(lua_State *L)
|
||||
{
|
||||
struct symbol_list *symlist;
|
||||
struct string_list *filelist = NULL;
|
||||
char *file;
|
||||
|
||||
struct dmr_C *C = new_dmr_C();
|
||||
|
||||
const char *codebuffer = luaL_checkstring(L, 1);
|
||||
char *argv[] = { NULL };
|
||||
int argc = 0;
|
||||
|
||||
symlist = dmrC_sparse_initialize(C, argc, argv, &filelist);
|
||||
|
||||
struct parser_state parser_state = {
|
||||
.L = L,
|
||||
.C = C,
|
||||
.idcount = 0,
|
||||
.stack = {0},
|
||||
.stackpos = -1,
|
||||
.tabidx = 1
|
||||
};
|
||||
dmrC_allocator_init(&parser_state.int_allocator, "integers", sizeof(int), __alignof__(int), CHUNK);
|
||||
|
||||
lua_newtable(L);
|
||||
int luastack = lua_gettop(L);
|
||||
push_tabindex(&parser_state);
|
||||
#if 0
|
||||
FOR_EACH_PTR(filelist, file) {
|
||||
int fd = get_stream_id(C, file);
|
||||
examine_symbol_list(C, fd, symlist);
|
||||
dmrC_sparse_keep_tokens(C, file);
|
||||
examine_symbol_list(C, fd, C->file_scope->symbols);
|
||||
examine_symbol_list(C, fd, C->global_scope->symbols);
|
||||
} END_FOR_EACH_PTR(file);
|
||||
#endif
|
||||
char *buffer = strdup(codebuffer);
|
||||
if (dmrC_sparse_buffer(C, "buffer", buffer, 1)) {
|
||||
int fd = get_stream_id(C, "buffer");
|
||||
examine_symbol_list(&parser_state, fd, C->file_scope->symbols);
|
||||
examine_symbol_list(&parser_state, fd, C->global_scope->symbols);
|
||||
}
|
||||
free(buffer);
|
||||
|
||||
destroy_dmr_C(C);
|
||||
dmrC_allocator_destroy(&parser_state.int_allocator);
|
||||
|
||||
lua_assert(luastack == lua_gettop(L));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const luaL_Reg dmrclib[] = {
|
||||
{ "getsymbols", dmrC_getsymbols },{ NULL, NULL } };
|
||||
|
||||
LUAMOD_API int raviopen_dmrcluaapi(lua_State *L) {
|
||||
luaL_newlib(L, dmrclib);
|
||||
return 1;
|
||||
}
|
@ -1,382 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <ravi_gccjit.h>
|
||||
|
||||
// R(A) := -R(B), floating point
|
||||
void ravi_emit_UNMF(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
// rb->value_.n
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_n(def, rb);
|
||||
// result = -rb->value_.n;
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_unary_op(
|
||||
def->function_context, NULL, GCC_JIT_UNARY_OP_MINUS,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs));
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := -R(B), integer
|
||||
void ravi_emit_UNMI(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
// rb->value_.n
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_i(def, rb);
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_unary_op(
|
||||
def->function_context, NULL, GCC_JIT_UNARY_OP_MINUS,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(lhs));
|
||||
ravi_emit_store_reg_i_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) + RK(C), all floating
|
||||
void ravi_emit_ADDFF(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.n
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_n(def, rb);
|
||||
// rc->value_.n
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_n(def, rc);
|
||||
// result = rb->value_.n + rc->value_.n
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_PLUS,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
// ra->value_.n = result
|
||||
// ra->tt_ = LUA_TNUMFLT
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) * RK(C), float*float
|
||||
void ravi_emit_MULFF(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.n
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_n(def, rb);
|
||||
// rc->value_.n
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_n(def, rc);
|
||||
// result = rb->value_.n * rc->value_.n
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MULT,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
// ra->value_.n = result
|
||||
// ra->tt_ = LUA_TNUMFLT
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) - RK(C), float-float
|
||||
void ravi_emit_SUBFF(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.n
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_n(def, rb);
|
||||
// rc->value_.n
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_n(def, rc);
|
||||
// result = rb->value_.n - rc->value_.n
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MINUS,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
// ra->value_.n = result
|
||||
// ra->tt_ = LUA_TNUMFLT
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) / RK(C), float/float
|
||||
void ravi_emit_DIVFF(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.n
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_n(def, rb);
|
||||
// rc->value_.n
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_n(def, rc);
|
||||
// result = rb->value_.n / rc->value_.n
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_DIVIDE,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
// ra->value_.n = result
|
||||
// ra->tt_ = LUA_TNUMFLT
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) + RK(C), float+int
|
||||
void ravi_emit_ADDFI(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.n
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_n(def, rb);
|
||||
// rc->value_.i
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_i(def, rc);
|
||||
// result = rb->value_.n + (lua_number)rc->value_.i
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_PLUS,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_context_new_cast(def->function_context, NULL,
|
||||
gcc_jit_lvalue_as_rvalue(rhs),
|
||||
def->ravi->types->lua_NumberT));
|
||||
// ra->value_.n = result
|
||||
// ra->tt_ = LUA_TNUMFLT
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) * RK(C), float*int
|
||||
void ravi_emit_MULFI(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.n
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_n(def, rb);
|
||||
// rc->value_.i
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_i(def, rc);
|
||||
// result = rb->value_.n * (lua_number)rc->value_.i
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MULT,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_context_new_cast(def->function_context, NULL,
|
||||
gcc_jit_lvalue_as_rvalue(rhs),
|
||||
def->ravi->types->lua_NumberT));
|
||||
// ra->value_.n = result
|
||||
// ra->tt_ = LUA_TNUMFLT
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) - RK(C), float-int
|
||||
void ravi_emit_SUBFI(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.n
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_n(def, rb);
|
||||
// rc->value_.i
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_i(def, rc);
|
||||
// result = rb->value_.n - (lua_number)rc->value_.i
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MINUS,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_context_new_cast(def->function_context, NULL,
|
||||
gcc_jit_lvalue_as_rvalue(rhs),
|
||||
def->ravi->types->lua_NumberT));
|
||||
// ra->value_.n = result
|
||||
// ra->tt_ = LUA_TNUMFLT
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) / RK(C), float/int
|
||||
void ravi_emit_DIVFI(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.n
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_n(def, rb);
|
||||
// rc->value_.i
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_i(def, rc);
|
||||
// result = rb->value_.n / (lua_number)rc->value_.i
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_DIVIDE,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_context_new_cast(def->function_context, NULL,
|
||||
gcc_jit_lvalue_as_rvalue(rhs),
|
||||
def->ravi->types->lua_NumberT));
|
||||
// ra->value_.n = result
|
||||
// ra->tt_ = LUA_TNUMFLT
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) - RK(C), int-float
|
||||
void ravi_emit_SUBIF(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.i
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_i(def, rb);
|
||||
// rc->value_.n
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_n(def, rc);
|
||||
// result = (lua_Number) rb->value_.i - rc->value_.n
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MINUS,
|
||||
def->ravi->types->lua_NumberT,
|
||||
gcc_jit_context_new_cast(def->function_context, NULL,
|
||||
gcc_jit_lvalue_as_rvalue(lhs),
|
||||
def->ravi->types->lua_NumberT),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
// ra->value_.n = result
|
||||
// ra->tt_ = LUA_TNUMFLT
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) / RK(C), int/float
|
||||
void ravi_emit_DIVIF(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.i
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_i(def, rb);
|
||||
// rc->value_.n
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_n(def, rc);
|
||||
// result = (lua_Number) rb->value_.i / rc->value_.n
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_DIVIDE,
|
||||
def->ravi->types->lua_NumberT,
|
||||
gcc_jit_context_new_cast(def->function_context, NULL,
|
||||
gcc_jit_lvalue_as_rvalue(lhs),
|
||||
def->ravi->types->lua_NumberT),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
// ra->value_.n = result
|
||||
// ra->tt_ = LUA_TNUMFLT
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) + RK(C), int+int
|
||||
void ravi_emit_ADDII(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.i
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_i(def, rb);
|
||||
// rc->value_.i
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_i(def, rc);
|
||||
// result = rb->value_.i + rc->value_.i
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_PLUS,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
// ra->value_.i = result
|
||||
// ra->tt_ = LUA_TNUMINT
|
||||
ravi_emit_store_reg_i_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) * RK(C), int*int
|
||||
void ravi_emit_MULII(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.i
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_i(def, rb);
|
||||
// rc->value_.i
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_i(def, rc);
|
||||
// result = rb->value_.i * rc->value_.i
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MULT,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
// ra->value_.i = result
|
||||
// ra->tt_ = LUA_TNUMINT
|
||||
ravi_emit_store_reg_i_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) - RK(C), int-int
|
||||
void ravi_emit_SUBII(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.i
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_i(def, rb);
|
||||
// rc->value_.i
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_i(def, rc);
|
||||
// result = rb->value_.i - rc->value_.i
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MINUS,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
// ra->value_.i = result
|
||||
// ra->tt_ = LUA_TNUMINT
|
||||
ravi_emit_store_reg_i_withtype(def, result, ra);
|
||||
}
|
||||
|
||||
// R(A) := RK(B) / RK(C), int/int but result is float
|
||||
void ravi_emit_DIVII(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
// rb->value_.i
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_i(def, rb);
|
||||
// rc->value_.i
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_i(def, rc);
|
||||
// result = (lua_Number)rb->value_.i / (lua_Number)rc->value_.i
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_DIVIDE,
|
||||
def->ravi->types->lua_IntegerT,
|
||||
gcc_jit_context_new_cast(def->function_context, NULL,
|
||||
gcc_jit_lvalue_as_rvalue(lhs),
|
||||
def->ravi->types->lua_NumberT),
|
||||
gcc_jit_context_new_cast(def->function_context, NULL,
|
||||
gcc_jit_lvalue_as_rvalue(rhs),
|
||||
def->ravi->types->lua_NumberT));
|
||||
// ra->value_.i = result
|
||||
// ra->tt_ = LUA_TNUMINT
|
||||
ravi_emit_store_reg_i_withtype(def, result, ra);
|
||||
}
|
@ -1,247 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <ravi_gccjit.h>
|
||||
|
||||
// OP_ADD, OP_SUB, OP_MUL and OP_DIV
|
||||
void ravi_emit_ARITH(ravi_function_def_t *def, int A, int B, int C, OpCode op,
|
||||
TMS tms, int pc) {
|
||||
|
||||
// TValue *rb = RKB(i);
|
||||
// TValue *rc = RKC(i);
|
||||
// lua_Number nb; lua_Number nc;
|
||||
// if (ttisinteger(rb) && ttisinteger(rc)) {
|
||||
// lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
|
||||
// setivalue(ra, intop(+, ib, ic));
|
||||
//}
|
||||
// else if (tonumber(rb, &nb) && tonumber(rc, &nc)) {
|
||||
// setfltvalue(ra, luai_numadd(L, nb, nc));
|
||||
//}
|
||||
// else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); }
|
||||
|
||||
gcc_jit_lvalue *nb = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->lua_NumberT,
|
||||
unique_name(def, "ARITH_nb", pc));
|
||||
gcc_jit_lvalue *nc = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->lua_NumberT,
|
||||
unique_name(def, "ARITH_nc", pc));
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
|
||||
gcc_jit_lvalue *rb_type = ravi_emit_load_type(def, rb);
|
||||
gcc_jit_lvalue *rc_type = ravi_emit_load_type(def, rc);
|
||||
|
||||
gcc_jit_block *float_op = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "ARITH_float.op", pc));
|
||||
gcc_jit_block *try_meta = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "ARITH_try_meta", pc));
|
||||
gcc_jit_block *done_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "done", pc));
|
||||
|
||||
if (op != OP_DIV) {
|
||||
gcc_jit_rvalue *cmp1 = ravi_emit_is_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(rb_type), LUA__TNUMINT);
|
||||
gcc_jit_rvalue *cmp2 = ravi_emit_is_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(rc_type), LUA__TNUMINT);
|
||||
|
||||
gcc_jit_rvalue *andvalue = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_LOGICAL_AND,
|
||||
def->ravi->types->C_boolT, cmp1, cmp2);
|
||||
|
||||
// Check if both RB and RC are integers
|
||||
gcc_jit_block *then_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "ARITH_if_integer", pc));
|
||||
gcc_jit_block *else_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "ARITH_if_not_integer", pc));
|
||||
ravi_emit_conditional_branch(def, andvalue, then_block, else_block);
|
||||
ravi_set_current_block(def, then_block);
|
||||
|
||||
// Both are integers
|
||||
gcc_jit_lvalue *lhs = ravi_emit_load_reg_i(def, rb);
|
||||
gcc_jit_lvalue *rhs = ravi_emit_load_reg_i(def, rc);
|
||||
|
||||
gcc_jit_rvalue *result = NULL;
|
||||
switch (op) {
|
||||
case OP_ADD:
|
||||
result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_PLUS,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
break;
|
||||
case OP_SUB:
|
||||
result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MINUS,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
break;
|
||||
case OP_MUL:
|
||||
result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MULT,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
break;
|
||||
default:
|
||||
lua_assert(0);
|
||||
}
|
||||
|
||||
ravi_emit_store_reg_i_withtype(def, result, ra);
|
||||
|
||||
ravi_emit_branch(def, done_block);
|
||||
|
||||
// Not integer
|
||||
ravi_set_current_block(def, else_block);
|
||||
}
|
||||
|
||||
// Is RB a float?
|
||||
gcc_jit_rvalue *cmp1 = ravi_emit_is_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(rb_type), LUA__TNUMFLT);
|
||||
|
||||
gcc_jit_block *convert_rb = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "ARITH_convert_rb", pc));
|
||||
gcc_jit_block *test_rc = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "ARITH_test_rc", pc));
|
||||
gcc_jit_block *load_rb = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "ARITH_load_rb", pc));
|
||||
|
||||
// If RB is floating then load RB, else convert RB
|
||||
ravi_emit_conditional_branch(def, cmp1, load_rb, convert_rb);
|
||||
|
||||
// Convert RB
|
||||
ravi_set_current_block(def, convert_rb);
|
||||
|
||||
// Call luaV_tonumber_()
|
||||
gcc_jit_rvalue *rb_isnum =
|
||||
ravi_function_call2_rvalue(def, def->ravi->types->luaV_tonumberT,
|
||||
gcc_jit_lvalue_get_address(rb, NULL),
|
||||
gcc_jit_lvalue_get_address(nb, NULL));
|
||||
cmp1 = ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ, rb_isnum,
|
||||
ravi_int_constant(def, 1));
|
||||
|
||||
// If not number then go to meta block
|
||||
// Else proceed to test RC
|
||||
ravi_emit_conditional_branch(def, cmp1, test_rc, try_meta);
|
||||
|
||||
ravi_set_current_block(def, load_rb);
|
||||
|
||||
// Copy RB to local nb
|
||||
gcc_jit_lvalue *src = ravi_emit_load_reg_n(def, rb);
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, nb,
|
||||
gcc_jit_lvalue_as_rvalue(src));
|
||||
|
||||
ravi_emit_branch(def, test_rc);
|
||||
|
||||
ravi_set_current_block(def, test_rc);
|
||||
|
||||
// Is RC a float?
|
||||
cmp1 = ravi_emit_is_value_of_type(def, gcc_jit_lvalue_as_rvalue(rc_type),
|
||||
LUA__TNUMFLT);
|
||||
|
||||
gcc_jit_block *convert_rc = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "ARITH_convert_rc", pc));
|
||||
gcc_jit_block *load_rc = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "ARITH_load_rc", pc));
|
||||
|
||||
// If RC is float load RC
|
||||
// else try to convert RC
|
||||
ravi_emit_conditional_branch(def, cmp1, load_rc, convert_rc);
|
||||
|
||||
ravi_set_current_block(def, convert_rc);
|
||||
|
||||
// Call luaV_tonumber_()
|
||||
gcc_jit_rvalue *rc_isnum =
|
||||
ravi_function_call2_rvalue(def, def->ravi->types->luaV_tonumberT,
|
||||
gcc_jit_lvalue_get_address(rc, NULL),
|
||||
gcc_jit_lvalue_get_address(nc, NULL));
|
||||
cmp1 = ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ, rc_isnum,
|
||||
ravi_int_constant(def, 1));
|
||||
|
||||
// If not number then go to meta block
|
||||
// else both RB and RC float so go to op
|
||||
ravi_emit_conditional_branch(def, cmp1, float_op, try_meta);
|
||||
|
||||
ravi_set_current_block(def, load_rc);
|
||||
|
||||
// Copy RC to local;
|
||||
src = ravi_emit_load_reg_n(def, rc);
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, nc,
|
||||
gcc_jit_lvalue_as_rvalue(src));
|
||||
|
||||
ravi_emit_branch(def, float_op);
|
||||
|
||||
ravi_set_current_block(def, float_op);
|
||||
|
||||
gcc_jit_lvalue *lhs = nb;
|
||||
gcc_jit_lvalue *rhs = nc;
|
||||
|
||||
gcc_jit_rvalue *result = NULL;
|
||||
// Add and set RA
|
||||
switch (op) {
|
||||
case OP_ADD:
|
||||
result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_PLUS,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
break;
|
||||
case OP_SUB:
|
||||
result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MINUS,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
break;
|
||||
case OP_MUL:
|
||||
result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MULT,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
break;
|
||||
case OP_DIV:
|
||||
result = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_DIVIDE,
|
||||
def->ravi->types->lua_NumberT, gcc_jit_lvalue_as_rvalue(lhs),
|
||||
gcc_jit_lvalue_as_rvalue(rhs));
|
||||
break;
|
||||
default:
|
||||
lua_assert(0);
|
||||
}
|
||||
|
||||
ravi_emit_store_reg_n_withtype(def, result, ra);
|
||||
|
||||
ravi_emit_branch(def, done_block);
|
||||
|
||||
// Neither integer nor float so try meta
|
||||
ravi_set_current_block(def, try_meta);
|
||||
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call5_rvalue(
|
||||
def, def->ravi->types->luaT_trybinTMT,
|
||||
gcc_jit_param_as_rvalue(def->L), gcc_jit_lvalue_get_address(rb, NULL),
|
||||
gcc_jit_lvalue_get_address(rc, NULL),
|
||||
gcc_jit_lvalue_get_address(ra, NULL), ravi_int_constant(def, tms)));
|
||||
ravi_emit_branch(def, done_block);
|
||||
|
||||
ravi_set_current_block(def, done_block);
|
||||
}
|
@ -1,170 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <ravi_gccjit.h>
|
||||
#include <assert.h>
|
||||
|
||||
// OP_JMP
|
||||
void ravi_emit_JMP(ravi_function_def_t *def, int A, int j, int pc) {
|
||||
|
||||
//#define dojump(ci,i,e)
|
||||
// { int a = GETARG_A(i);
|
||||
// if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
|
||||
// ci->u.l.savedpc += GETARG_sBx(i) + e; }
|
||||
//
|
||||
// dojump(ci, i, 0);
|
||||
|
||||
assert(def->jmp_targets[j]->jmp);
|
||||
if (def->current_block_terminated) {
|
||||
gcc_jit_block *jmp_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_JMP", pc));
|
||||
ravi_set_current_block(def, jmp_block);
|
||||
}
|
||||
// ravi_debug_printf2(def, "OP_JMP(%d) jmp to %d\n", ravi_int_constant(def,
|
||||
// pc+1), ravi_int_constant(def, j+1));
|
||||
|
||||
// if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
|
||||
if (A > 0) {
|
||||
ravi_emit_load_base(def);
|
||||
// base + a - 1
|
||||
gcc_jit_lvalue *val = ravi_emit_get_register(def, A - 1);
|
||||
// Call luaF_close
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call2_rvalue(def, def->ravi->types->luaF_closeT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(val, NULL)));
|
||||
}
|
||||
|
||||
ravi_emit_branch(def, def->jmp_targets[j]->jmp);
|
||||
|
||||
gcc_jit_block *block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_JMP_post", pc));
|
||||
ravi_set_current_block(def, block);
|
||||
}
|
||||
|
||||
// Handle OP_CALL
|
||||
void ravi_emit_CALL(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
|
||||
// int nresults = c - 1;
|
||||
// if (b != 0)
|
||||
// L->top = ra + b; /* else previous instruction set top */
|
||||
// int c = luaD_precall(L, ra, nresults); /* C or JITed function? */
|
||||
// if (c) {
|
||||
// if (c == 1 && nresults >= 0)
|
||||
// L->top = ci->top; /* adjust results if C function */
|
||||
// }
|
||||
// else { /* Lua function */
|
||||
// luaV_execute(L);
|
||||
// }
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// int nresults = c - 1;
|
||||
int nresults = C - 1;
|
||||
|
||||
// if (b != 0)
|
||||
if (B != 0) {
|
||||
ravi_emit_set_L_top_toreg(def, A + B);
|
||||
}
|
||||
|
||||
// luaD_precall() returns following
|
||||
// 1 - C function called, results to be adjusted
|
||||
// 2 - JITed Lua function called, no action
|
||||
// 0 - Run interpreter on Lua function
|
||||
|
||||
// int c = luaD_precall(L, ra, nresults); /* C or JITed function? */
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_rvalue *nresults_const = gcc_jit_context_new_rvalue_from_int(
|
||||
def->function_context, def->ravi->types->C_intT, nresults);
|
||||
gcc_jit_rvalue *precall_result = ravi_function_call4_rvalue(
|
||||
def, def->ravi->types->luaD_precallT, gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(ra, NULL), nresults_const,
|
||||
ravi_int_constant(def, 1));
|
||||
/* Need to save the result of the luaD_precall() so that we can do another
|
||||
* check later on
|
||||
*/
|
||||
gcc_jit_lvalue *tmp_var = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->C_intT,
|
||||
unique_name(def, "OP_CALL_luaD_precall_result", pc));
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, tmp_var,
|
||||
precall_result);
|
||||
gcc_jit_rvalue *zero_const = gcc_jit_context_new_rvalue_from_int(
|
||||
def->function_context, def->ravi->types->C_intT, 0);
|
||||
gcc_jit_rvalue *precall_bool =
|
||||
ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ,
|
||||
gcc_jit_lvalue_as_rvalue(tmp_var), zero_const);
|
||||
|
||||
gcc_jit_block *then_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_CALL_if_lua_function", pc));
|
||||
gcc_jit_block *else_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_CALL_else_lua_function", pc));
|
||||
gcc_jit_block *end_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_CALL_done", pc));
|
||||
|
||||
ravi_emit_conditional_branch(def, precall_bool, then_block, else_block);
|
||||
ravi_set_current_block(def, then_block);
|
||||
|
||||
// Lua function, not compiled, so call luaV_execute
|
||||
gcc_jit_rvalue *b = ravi_function_call1_rvalue(
|
||||
def, def->ravi->types->luaV_executeT, gcc_jit_param_as_rvalue(def->L));
|
||||
|
||||
// If the return value is non zero then we need to refresh L->top = ci->top
|
||||
gcc_jit_rvalue *b_not_zero = ravi_emit_comparison(
|
||||
def, GCC_JIT_COMPARISON_NE, b, ravi_int_constant(def, 0));
|
||||
|
||||
gcc_jit_block *if_b_block = gcc_jit_function_new_block(
|
||||
def->jit_function,
|
||||
unique_name(def, "OP_CALL_if_luaV_execute_b_value", pc));
|
||||
ravi_emit_conditional_branch(def, b_not_zero, if_b_block, else_block);
|
||||
|
||||
ravi_set_current_block(def, if_b_block);
|
||||
|
||||
ravi_emit_refresh_L_top(def);
|
||||
ravi_emit_branch(def, end_block);
|
||||
|
||||
ravi_set_current_block(def, else_block);
|
||||
|
||||
if (nresults >= 0) {
|
||||
// In case the precall returned 1 then a C function was
|
||||
// called so we need to update L->top
|
||||
// if (c == 1 && nresults >= 0)
|
||||
// L->top = ci->top; /* adjust results if C function */
|
||||
gcc_jit_rvalue *one_const = gcc_jit_context_new_rvalue_from_int(
|
||||
def->function_context, def->ravi->types->C_intT, 1);
|
||||
gcc_jit_rvalue *precall_C =
|
||||
ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ,
|
||||
gcc_jit_lvalue_as_rvalue(tmp_var), one_const);
|
||||
|
||||
gcc_jit_block *then1_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_CALL_if_C_function", pc));
|
||||
ravi_emit_conditional_branch(def, precall_C, then1_block, end_block);
|
||||
ravi_set_current_block(def, then1_block);
|
||||
|
||||
// L->top = ci->top; /* adjust results if C function */
|
||||
ravi_emit_refresh_L_top(def);
|
||||
}
|
||||
|
||||
ravi_emit_branch(def, end_block);
|
||||
ravi_set_current_block(def, end_block);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,356 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <ravi_gccjit.h>
|
||||
#include <assert.h>
|
||||
|
||||
// implements EQ, LE and LT - by using the supplied lua function to call.
|
||||
void ravi_emit_EQ_LE_LT(ravi_function_def_t *def, int A, int B, int C, int j,
|
||||
int jA, gcc_jit_function *callee, const char *opname,
|
||||
OpCode opCode, int pc) {
|
||||
// case OP_EQ: {
|
||||
// TValue *rb = RKB(i);
|
||||
// TValue *rc = RKC(i);
|
||||
// Protect(
|
||||
// if (cast_int(luaV_equalobj(L, rb, rc)) != GETARG_A(i))
|
||||
// ci->u.l.savedpc++;
|
||||
// else
|
||||
// donextjump(ci);
|
||||
// )
|
||||
// } break;
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// Get pointer to register B
|
||||
gcc_jit_lvalue *regB = ravi_emit_get_register_or_constant(def, B);
|
||||
// Get pointer to register C
|
||||
gcc_jit_lvalue *regC = ravi_emit_get_register_or_constant(def, C);
|
||||
|
||||
gcc_jit_rvalue *result = NULL;
|
||||
switch (opCode) {
|
||||
|
||||
case OP_RAVI_LT_II:
|
||||
case OP_RAVI_LE_II:
|
||||
case OP_RAVI_EQ_II: {
|
||||
gcc_jit_lvalue *p1 = ravi_emit_load_reg_i(def, regB);
|
||||
gcc_jit_lvalue *p2 = ravi_emit_load_reg_i(def, regC);
|
||||
|
||||
switch (opCode) {
|
||||
case OP_RAVI_EQ_II:
|
||||
result = ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ,
|
||||
gcc_jit_lvalue_as_rvalue(p1),
|
||||
gcc_jit_lvalue_as_rvalue(p2));
|
||||
break;
|
||||
case OP_RAVI_LT_II:
|
||||
result = ravi_emit_comparison(def, GCC_JIT_COMPARISON_LT,
|
||||
gcc_jit_lvalue_as_rvalue(p1),
|
||||
gcc_jit_lvalue_as_rvalue(p2));
|
||||
break;
|
||||
case OP_RAVI_LE_II:
|
||||
result = ravi_emit_comparison(def, GCC_JIT_COMPARISON_LE,
|
||||
gcc_jit_lvalue_as_rvalue(p1),
|
||||
gcc_jit_lvalue_as_rvalue(p2));
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
result = gcc_jit_context_new_cast(def->function_context, NULL, result,
|
||||
def->ravi->types->C_intT);
|
||||
|
||||
} break;
|
||||
|
||||
case OP_RAVI_LT_FF:
|
||||
case OP_RAVI_LE_FF:
|
||||
case OP_RAVI_EQ_FF: {
|
||||
gcc_jit_lvalue *p1 = ravi_emit_load_reg_n(def, regB);
|
||||
gcc_jit_lvalue *p2 = ravi_emit_load_reg_n(def, regC);
|
||||
|
||||
switch (opCode) {
|
||||
case OP_RAVI_EQ_FF:
|
||||
result = ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ,
|
||||
gcc_jit_lvalue_as_rvalue(p1),
|
||||
gcc_jit_lvalue_as_rvalue(p2));
|
||||
break;
|
||||
case OP_RAVI_LT_FF:
|
||||
result = ravi_emit_comparison(def, GCC_JIT_COMPARISON_LT,
|
||||
gcc_jit_lvalue_as_rvalue(p1),
|
||||
gcc_jit_lvalue_as_rvalue(p2));
|
||||
break;
|
||||
case OP_RAVI_LE_FF:
|
||||
result = ravi_emit_comparison(def, GCC_JIT_COMPARISON_LE,
|
||||
gcc_jit_lvalue_as_rvalue(p1),
|
||||
gcc_jit_lvalue_as_rvalue(p2));
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
result = gcc_jit_context_new_cast(def->function_context, NULL, result,
|
||||
def->ravi->types->C_intT);
|
||||
|
||||
} break;
|
||||
|
||||
default:
|
||||
// Call luaV_equalobj with register B and C
|
||||
result =
|
||||
ravi_function_call3_rvalue(def, callee, gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(regB, NULL),
|
||||
gcc_jit_lvalue_get_address(regC, NULL));
|
||||
}
|
||||
|
||||
// Test if result is equal to operand A
|
||||
gcc_jit_rvalue *A_const = ravi_int_constant(def, A);
|
||||
gcc_jit_rvalue *result_eq_A =
|
||||
ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ, result, A_const);
|
||||
// If result == A then we need to execute the next statement which is a jump
|
||||
char temp[80];
|
||||
snprintf(temp, sizeof temp, "%s_then", opname);
|
||||
gcc_jit_block *then_block =
|
||||
gcc_jit_function_new_block(def->jit_function, unique_name(def, temp, pc));
|
||||
|
||||
snprintf(temp, sizeof temp, "%s_else", opname);
|
||||
gcc_jit_block *else_block =
|
||||
gcc_jit_function_new_block(def->jit_function, unique_name(def, temp, pc));
|
||||
ravi_emit_conditional_branch(def, result_eq_A, then_block, else_block);
|
||||
ravi_set_current_block(def, then_block);
|
||||
|
||||
// if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
|
||||
if (jA > 0) {
|
||||
// jA is the A operand of the Jump instruction
|
||||
|
||||
// Reload pointer to base as the call to luaV_equalobj() may
|
||||
// have invoked a Lua function and as a result the stack may have
|
||||
// been reallocated - so the previous base pointer could be stale
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// base + a - 1
|
||||
gcc_jit_lvalue *val = ravi_emit_get_register(def, jA - 1);
|
||||
|
||||
// Call luaF_close
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call2_rvalue(def, def->ravi->types->luaF_closeT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(val, NULL)));
|
||||
}
|
||||
// Do the jump
|
||||
ravi_emit_branch(def, def->jmp_targets[j]->jmp);
|
||||
// Add the else block and make it current so that the next instruction flows
|
||||
// here
|
||||
ravi_set_current_block(def, else_block);
|
||||
}
|
||||
|
||||
gcc_jit_rvalue *ravi_emit_boolean_testfalse(ravi_function_def_t *def,
|
||||
gcc_jit_lvalue *reg, bool negate) {
|
||||
// (isnil() || isbool() && b == 0)
|
||||
|
||||
gcc_jit_lvalue *var = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->C_boolT,
|
||||
unique_name(def, "isfalse", 0));
|
||||
gcc_jit_lvalue *type = ravi_emit_load_type(def, reg);
|
||||
|
||||
// Test if type == LUA_TNIL (0)
|
||||
gcc_jit_rvalue *isnil = ravi_emit_is_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(type), LUA__TNIL);
|
||||
|
||||
// Test if type == LUA_TBOOLEAN
|
||||
gcc_jit_rvalue *isbool = ravi_emit_is_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(type), LUA__TBOOLEAN);
|
||||
|
||||
// Test if bool value == 0
|
||||
gcc_jit_lvalue *bool_value = ravi_emit_load_reg_b(def, reg);
|
||||
gcc_jit_rvalue *zero = gcc_jit_context_new_rvalue_from_int(
|
||||
def->function_context, def->ravi->types->C_intT, 0);
|
||||
gcc_jit_rvalue *boolzero = ravi_emit_comparison(
|
||||
def, GCC_JIT_COMPARISON_EQ, gcc_jit_lvalue_as_rvalue(bool_value), zero);
|
||||
|
||||
// Test type == LUA_TBOOLEAN && bool value == 0
|
||||
gcc_jit_rvalue *andvalue = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_LOGICAL_AND,
|
||||
def->ravi->types->C_boolT, isbool, boolzero);
|
||||
|
||||
gcc_jit_rvalue *orvalue = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_LOGICAL_OR,
|
||||
def->ravi->types->C_boolT, isnil, andvalue);
|
||||
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, var, orvalue);
|
||||
|
||||
gcc_jit_rvalue *result = NULL;
|
||||
if (negate) {
|
||||
result = gcc_jit_context_new_unary_op(
|
||||
def->function_context, NULL, GCC_JIT_UNARY_OP_LOGICAL_NEGATE,
|
||||
def->ravi->types->C_boolT, gcc_jit_lvalue_as_rvalue(var));
|
||||
} else {
|
||||
result = gcc_jit_lvalue_as_rvalue(var);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ravi_emit_TEST(ravi_function_def_t *def, int A, int B, int C, int j,
|
||||
int jA, int pc) {
|
||||
|
||||
// case OP_TEST: {
|
||||
// if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra))
|
||||
// ci->u.l.savedpc++;
|
||||
// else
|
||||
// donextjump(ci);
|
||||
// } break;
|
||||
|
||||
(void)B;
|
||||
|
||||
// if (C) {
|
||||
// ravi_debug_printf3(def, "OP_TEST(%d C=1)) if (!reg(A=%d)) then skip next
|
||||
// else jmp to %d\n", ravi_int_constant(def, pc+1),
|
||||
// ravi_int_constant(def, A), ravi_int_constant(def,
|
||||
// j+1));
|
||||
// }
|
||||
// else {
|
||||
// ravi_debug_printf3(def, "OP_TEST(%d C=0) if (reg(A=%d)) then skip next
|
||||
// else jmp to %d\n", ravi_int_constant(def, pc+1),
|
||||
// ravi_int_constant(def, A), ravi_int_constant(def,
|
||||
// j+1));
|
||||
// }
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// Get pointer to register A
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
// v = C ? is_false(ra) : !is_false(ra)
|
||||
gcc_jit_rvalue *v = C ? ravi_emit_boolean_testfalse(def, ra, false)
|
||||
: ravi_emit_boolean_testfalse(def, ra, true);
|
||||
|
||||
// Test NOT v
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_unary_op(
|
||||
def->function_context, NULL, GCC_JIT_UNARY_OP_LOGICAL_NEGATE,
|
||||
def->ravi->types->C_boolT, v);
|
||||
// If !v then we need to execute the next statement which is a jump
|
||||
gcc_jit_block *then_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_TEST_do_jmp", pc));
|
||||
gcc_jit_block *else_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_TEST_do_skip", pc));
|
||||
ravi_emit_conditional_branch(def, result, then_block, else_block);
|
||||
ravi_set_current_block(def, then_block);
|
||||
|
||||
// if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
|
||||
if (jA > 0) {
|
||||
// jA is the A operand of the Jump instruction
|
||||
|
||||
// base + a - 1
|
||||
gcc_jit_lvalue *val = ravi_emit_get_register(def, jA - 1);
|
||||
|
||||
// Call luaF_close
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call2_rvalue(def, def->ravi->types->luaF_closeT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(val, NULL)));
|
||||
}
|
||||
// Do the jump
|
||||
ravi_emit_branch(def, def->jmp_targets[j]->jmp);
|
||||
|
||||
// Add the else block and make it current so that the next instruction flows
|
||||
// here
|
||||
ravi_set_current_block(def, else_block);
|
||||
}
|
||||
|
||||
void ravi_emit_NOT(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
// case OP_NOT: {
|
||||
// TValue *rb = RB(i);
|
||||
// int res = l_isfalse(rb); /* next assignment may change this value */
|
||||
// setbvalue(ra, res);
|
||||
// } break;
|
||||
(void)pc;
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
// Get pointer to register B
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register(def, B);
|
||||
gcc_jit_rvalue *v = ravi_emit_boolean_testfalse(def, rb, false);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
ravi_emit_store_reg_b_withtype(
|
||||
def, gcc_jit_context_new_cast(def->function_context, NULL, v,
|
||||
def->ravi->types->C_intT),
|
||||
ra);
|
||||
}
|
||||
|
||||
void ravi_emit_TESTSET(ravi_function_def_t *def, int A, int B, int C, int j,
|
||||
int jA, int pc) {
|
||||
|
||||
// case OP_TESTSET: {
|
||||
// TValue *rb = RB(i);
|
||||
// if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))
|
||||
// ci->u.l.savedpc++;
|
||||
// else {
|
||||
// setobjs2s(L, ra, rb);
|
||||
// donextjump(ci);
|
||||
// }
|
||||
// } break;
|
||||
|
||||
(void)pc;
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// Get pointer to register B
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register(def, B);
|
||||
// v = C ? is_false(ra) : !is_false(ra)
|
||||
gcc_jit_rvalue *v = C ? ravi_emit_boolean_testfalse(def, rb, false)
|
||||
: ravi_emit_boolean_testfalse(def, rb, true);
|
||||
|
||||
// Test NOT v
|
||||
gcc_jit_rvalue *result = gcc_jit_context_new_unary_op(
|
||||
def->function_context, NULL, GCC_JIT_UNARY_OP_LOGICAL_NEGATE,
|
||||
def->ravi->types->C_boolT, v);
|
||||
|
||||
// If !v then we need to execute the next statement which is a jump
|
||||
gcc_jit_block *then_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_TESTSET_if_then", pc));
|
||||
gcc_jit_block *else_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_TESTSET_if_else", pc));
|
||||
ravi_emit_conditional_branch(def, result, then_block, else_block);
|
||||
ravi_set_current_block(def, then_block);
|
||||
|
||||
// Get pointer to register A
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
ravi_emit_struct_assign(def, ra, rb);
|
||||
|
||||
// if (a > 0) luaF_close(L, ci->u.l.base + a - 1);
|
||||
if (jA > 0) {
|
||||
// jA is the A operand of the Jump instruction
|
||||
|
||||
// base + a - 1
|
||||
gcc_jit_lvalue *val = ravi_emit_get_register(def, jA - 1);
|
||||
|
||||
// Call luaF_close
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call2_rvalue(def, def->ravi->types->luaF_closeT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(val, NULL)));
|
||||
}
|
||||
// Do the jump
|
||||
ravi_emit_branch(def, def->jmp_targets[j]->jmp);
|
||||
|
||||
// Add the else block and make it current so that the next instruction flows
|
||||
// here
|
||||
ravi_set_current_block(def, else_block);
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <ravi_gccjit.h>
|
||||
|
||||
void ravi_emit_iFORLOOP(ravi_function_def_t *def, int A, int pc,
|
||||
ravi_branch_def_t *b, int step_one) {
|
||||
|
||||
// lua_Integer step = ivalue(ra + 2);
|
||||
// lua_Integer idx = ivalue(ra) + step; /* increment index */
|
||||
// lua_Integer limit = ivalue(ra + 1);
|
||||
// if (idx <= limit) {
|
||||
// ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
||||
// setivalue(ra, idx); /* update internal index... */
|
||||
// setivalue(ra + 3, idx); /* ...and external index */
|
||||
// }
|
||||
|
||||
// We are in b->jmp as this is already the current block
|
||||
lua_assert(def->current_block == b->jmp);
|
||||
|
||||
// Create the done block
|
||||
gcc_jit_block *exit_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "FORLOOP_I1_exit", 0));
|
||||
|
||||
gcc_jit_rvalue *new_idx;
|
||||
|
||||
if (!step_one) {
|
||||
// lua_Integer step = ivalue(ra + 2);
|
||||
new_idx = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_PLUS,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(b->iidx),
|
||||
gcc_jit_lvalue_as_rvalue(b->istep));
|
||||
} else
|
||||
new_idx = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_PLUS,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(b->iidx),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->lua_IntegerT, 1));
|
||||
|
||||
// save new index
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, b->iidx, new_idx);
|
||||
|
||||
// lua_Integer limit = ivalue(ra + 1);
|
||||
|
||||
// idx > limit?
|
||||
gcc_jit_rvalue *new_idx_gt_limit = ravi_emit_comparison(
|
||||
def, GCC_JIT_COMPARISON_GT, gcc_jit_lvalue_as_rvalue(b->iidx),
|
||||
gcc_jit_lvalue_as_rvalue(b->ilimit));
|
||||
|
||||
// If idx > limit we are done
|
||||
gcc_jit_block *update_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "FORLOOP_I1_updatei", 0));
|
||||
ravi_emit_conditional_branch(def, new_idx_gt_limit, exit_block, update_block);
|
||||
|
||||
ravi_set_current_block(def, update_block);
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// setivalue(ra + 3, idx); /* ...and external index */
|
||||
gcc_jit_lvalue *rvar = ravi_emit_get_register(def, A + 3);
|
||||
ravi_emit_store_reg_i_withtype(def, gcc_jit_lvalue_as_rvalue(b->iidx), rvar);
|
||||
|
||||
// ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
||||
ravi_emit_branch(def, def->jmp_targets[pc]->jmp);
|
||||
ravi_set_current_block(def, exit_block);
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
#include <ravi_gccjit.h>
|
||||
#include <assert.h>
|
||||
|
||||
void ravi_emit_iFORPREP(ravi_function_def_t *def, int A, int pc, int step_one) {
|
||||
ravi_branch_def_t *forloop_target = def->jmp_targets[pc];
|
||||
assert(forloop_target);
|
||||
|
||||
forloop_target->ilimit = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->lua_IntegerT,
|
||||
unique_name(def, "ilimit", 0));
|
||||
if (!step_one) {
|
||||
forloop_target->istep = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->lua_IntegerT,
|
||||
unique_name(def, "istep", 0));
|
||||
}
|
||||
forloop_target->iidx = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->lua_IntegerT,
|
||||
unique_name(def, "iidx", 0));
|
||||
|
||||
// lua_Integer initv = ivalue(init);
|
||||
// setivalue(init, initv - ivalue(pstep));
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// TValue *init = ra;
|
||||
// TValue *pstep = ra + 2;
|
||||
gcc_jit_lvalue *init = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *plimit = ravi_emit_get_register(def, A + 1);
|
||||
gcc_jit_lvalue *pstep = NULL;
|
||||
if (!step_one)
|
||||
pstep = ravi_emit_get_register(def, A + 2);
|
||||
// Get ivalue(pstep)
|
||||
|
||||
gcc_jit_lvalue *limit_ivalue = ravi_emit_load_reg_i(def, plimit);
|
||||
gcc_jit_lvalue *init_ivalue = ravi_emit_load_reg_i(def, init);
|
||||
|
||||
if (!step_one) {
|
||||
// setivalue(init, initv - ivalue(pstep));
|
||||
gcc_jit_lvalue *step_ivalue = ravi_emit_load_reg_i(def, pstep);
|
||||
gcc_jit_rvalue *idx = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MINUS,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(init_ivalue),
|
||||
gcc_jit_lvalue_as_rvalue(step_ivalue));
|
||||
// Save idx
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, forloop_target->iidx,
|
||||
idx);
|
||||
|
||||
// Save step
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL,
|
||||
forloop_target->istep,
|
||||
gcc_jit_lvalue_as_rvalue(step_ivalue));
|
||||
} else {
|
||||
// setivalue(init, initv - ivalue(pstep));
|
||||
gcc_jit_rvalue *idx = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_MINUS,
|
||||
def->ravi->types->lua_IntegerT, gcc_jit_lvalue_as_rvalue(init_ivalue),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->lua_IntegerT, 1));
|
||||
|
||||
// Save idx
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, forloop_target->iidx,
|
||||
idx);
|
||||
}
|
||||
|
||||
// Save limit
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, forloop_target->ilimit,
|
||||
gcc_jit_lvalue_as_rvalue(limit_ivalue));
|
||||
|
||||
// We are done so jump to forloop
|
||||
lua_assert(def->jmp_targets[pc]->jmp);
|
||||
ravi_emit_branch(def, def->jmp_targets[pc]->jmp);
|
||||
}
|
@ -1,262 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "ravi_gccjit.h"
|
||||
|
||||
ravi_gcc_context_t *ravi_jit_new_context(void) {
|
||||
ravi_gcc_context_t *ravi = NULL;
|
||||
gcc_jit_context *gcc_ctx = gcc_jit_context_acquire();
|
||||
if (!gcc_ctx) {
|
||||
fprintf(stderr, "failed to allocate a GCC JIT context\n");
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
ravi = (ravi_gcc_context_t *)calloc(1, sizeof(ravi_gcc_context_t));
|
||||
if (!ravi) {
|
||||
fprintf(stderr, "failed to allocate a Ravi JIT context\n");
|
||||
goto on_error;
|
||||
}
|
||||
ravi->context = gcc_ctx;
|
||||
ravi->auto_ = false;
|
||||
ravi->enabled_ = true;
|
||||
ravi->min_code_size_ = 150;
|
||||
ravi->min_exec_count_ = 50;
|
||||
ravi->opt_level_ = 3;
|
||||
ravi->size_level_ = 0;
|
||||
|
||||
if (!ravi_setup_lua_types(ravi)) {
|
||||
fprintf(stderr, "failed to setup types\n");
|
||||
goto on_error;
|
||||
}
|
||||
|
||||
ravi->parent_result_ = gcc_jit_context_compile(ravi->context);
|
||||
if (gcc_jit_context_get_first_error(ravi->context)) {
|
||||
fprintf(stderr, "aborting due to JIT error: %s\n",
|
||||
gcc_jit_context_get_first_error(ravi->context));
|
||||
abort();
|
||||
}
|
||||
|
||||
return ravi;
|
||||
on_error:
|
||||
if (ravi) {
|
||||
ravi_jit_context_free(ravi);
|
||||
} else if (gcc_ctx) {
|
||||
gcc_jit_context_release(gcc_ctx);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ravi_jit_context_free(ravi_gcc_context_t *ravi) {
|
||||
if (ravi == NULL)
|
||||
return;
|
||||
if (ravi->parent_result_) {
|
||||
gcc_jit_result_release(ravi->parent_result_);
|
||||
ravi->parent_result_ = NULL;
|
||||
}
|
||||
if (ravi->context) {
|
||||
gcc_jit_context_release(ravi->context);
|
||||
ravi->context = NULL;
|
||||
}
|
||||
if (ravi->types) {
|
||||
free(ravi->types);
|
||||
ravi->types = NULL;
|
||||
}
|
||||
free(ravi);
|
||||
}
|
||||
|
||||
ravi_gcc_codegen_t *ravi_jit_new_codegen(ravi_gcc_context_t *ravi) {
|
||||
ravi_gcc_codegen_t *cg = NULL;
|
||||
cg = (ravi_gcc_codegen_t *)calloc(1, sizeof(ravi_gcc_codegen_t));
|
||||
if (cg == NULL) {
|
||||
fprintf(stderr, "error creating a new context: out of memory\n");
|
||||
goto on_error;
|
||||
}
|
||||
cg->id = 1;
|
||||
cg->temp[0] = 0;
|
||||
cg->ravi = ravi;
|
||||
return cg;
|
||||
|
||||
on_error:
|
||||
if (cg)
|
||||
ravi_jit_codegen_free(cg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ravi_jit_codegen_free(ravi_gcc_codegen_t *codegen) {
|
||||
if (codegen == NULL)
|
||||
return;
|
||||
free(codegen);
|
||||
}
|
||||
|
||||
bool ravi_jit_has_errored(ravi_gcc_context_t *ravi) {
|
||||
const char *msg = gcc_jit_context_get_first_error(ravi->context);
|
||||
if (msg) {
|
||||
fprintf(stderr, "JIT error: %s\n", msg);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO we probably do not need all the headers
|
||||
// below
|
||||
|
||||
#define LUA_CORE
|
||||
|
||||
#include "lua.h"
|
||||
#include "lobject.h"
|
||||
#include "lstate.h"
|
||||
#include "lauxlib.h"
|
||||
|
||||
#include "ravi_gccjit.h"
|
||||
|
||||
// Initialize the JIT State and attach it to the
|
||||
// Global Lua State
|
||||
// If a JIT State already exists then this function
|
||||
// will return -1
|
||||
int raviV_initjit(struct lua_State *L) {
|
||||
global_State *G = G(L);
|
||||
if (G->ravi_state != NULL)
|
||||
return -1;
|
||||
ravi_State *jit = (ravi_State *)calloc(1, sizeof(ravi_State));
|
||||
jit->jit = ravi_jit_new_context();
|
||||
jit->code_generator = ravi_jit_new_codegen(jit->jit);
|
||||
G->ravi_state = jit;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Free up the JIT State
|
||||
void raviV_close(struct lua_State *L) {
|
||||
global_State *G = G(L);
|
||||
if (G->ravi_state == NULL)
|
||||
return;
|
||||
ravi_jit_codegen_free(G->ravi_state->code_generator);
|
||||
ravi_jit_context_free(G->ravi_state->jit);
|
||||
free(G->ravi_state);
|
||||
}
|
||||
|
||||
// Dump the LLVM IR
|
||||
void raviV_dumpIR(struct lua_State *L, struct Proto *p) {
|
||||
(void)L;
|
||||
(void)p;
|
||||
}
|
||||
|
||||
// Dump the LLVM ASM
|
||||
void raviV_dumpASM(struct lua_State *L, struct Proto *p) {
|
||||
(void)L;
|
||||
(void)p;
|
||||
}
|
||||
|
||||
void raviV_setminexeccount(lua_State *L, int value) {
|
||||
global_State *G = G(L);
|
||||
if (!G->ravi_state)
|
||||
return;
|
||||
G->ravi_state->jit->min_exec_count_ = value;
|
||||
}
|
||||
int raviV_getminexeccount(lua_State *L) {
|
||||
global_State *G = G(L);
|
||||
if (!G->ravi_state)
|
||||
return 0;
|
||||
return G->ravi_state->jit->min_exec_count_;
|
||||
}
|
||||
|
||||
void raviV_setmincodesize(lua_State *L, int value) {
|
||||
global_State *G = G(L);
|
||||
if (!G->ravi_state)
|
||||
return;
|
||||
G->ravi_state->jit->min_code_size_ = value;
|
||||
}
|
||||
int raviV_getmincodesize(lua_State *L) {
|
||||
global_State *G = G(L);
|
||||
if (!G->ravi_state)
|
||||
return 0;
|
||||
return G->ravi_state->jit->min_code_size_;
|
||||
}
|
||||
|
||||
void raviV_setauto(lua_State *L, int value) {
|
||||
global_State *G = G(L);
|
||||
if (!G->ravi_state)
|
||||
return;
|
||||
G->ravi_state->jit->auto_ = value;
|
||||
}
|
||||
int raviV_getauto(lua_State *L) {
|
||||
global_State *G = G(L);
|
||||
if (!G->ravi_state)
|
||||
return 0;
|
||||
return G->ravi_state->jit->auto_;
|
||||
}
|
||||
|
||||
// Turn on/off the JIT compiler
|
||||
void raviV_setjitenabled(lua_State *L, int value) {
|
||||
global_State *G = G(L);
|
||||
if (!G->ravi_state)
|
||||
return;
|
||||
G->ravi_state->jit->enabled_ = value;
|
||||
}
|
||||
int raviV_getjitenabled(lua_State *L) {
|
||||
global_State *G = G(L);
|
||||
if (!G->ravi_state)
|
||||
return 0;
|
||||
return G->ravi_state->jit->enabled_;
|
||||
}
|
||||
|
||||
void raviV_setoptlevel(lua_State *L, int value) {
|
||||
global_State *G = G(L);
|
||||
if (!G->ravi_state)
|
||||
return;
|
||||
G->ravi_state->jit->opt_level_ = value;
|
||||
}
|
||||
int raviV_getoptlevel(lua_State *L) {
|
||||
global_State *G = G(L);
|
||||
if (!G->ravi_state)
|
||||
return 0;
|
||||
return G->ravi_state->jit->opt_level_;
|
||||
}
|
||||
|
||||
void raviV_setsizelevel(lua_State *L, int value) {
|
||||
(void)L;
|
||||
(void)value;
|
||||
}
|
||||
int raviV_getsizelevel(lua_State *L) {
|
||||
(void)L;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void raviV_setgcstep(lua_State *L, int value) {
|
||||
(void)L;
|
||||
(void)value;
|
||||
}
|
||||
int raviV_getgcstep(lua_State *L) {
|
||||
(void)L;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Turn on/off the JIT compiler
|
||||
void raviV_settraceenabled(lua_State *L, int value) {
|
||||
(void)L;
|
||||
(void)value;
|
||||
}
|
||||
int raviV_gettraceenabled(lua_State *L) {
|
||||
(void)L;
|
||||
return 0;
|
||||
}
|
@ -1,467 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <ravi_gccjit.h>
|
||||
|
||||
// R(A+1), ..., R(A+B) := nil
|
||||
void ravi_emit_LOADNIL(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
(void)pc;
|
||||
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call3_rvalue(
|
||||
def, def->ravi->types->raviV_op_loadnilT,
|
||||
gcc_jit_lvalue_as_rvalue(def->ci_val),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, A),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, B)));
|
||||
}
|
||||
|
||||
// R(A) := tonumber(0)
|
||||
void ravi_emit_LOADFZ(ravi_function_def_t *def, int A, int pc) {
|
||||
(void)pc;
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// ra
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
|
||||
// destvalue->value_.n = 0.0
|
||||
ravi_emit_store_reg_n_withtype(
|
||||
def, gcc_jit_context_new_rvalue_from_double(
|
||||
def->function_context, def->ravi->types->lua_NumberT, 0.0),
|
||||
dest);
|
||||
}
|
||||
|
||||
// R(A) := tointeger(0)
|
||||
void ravi_emit_LOADIZ(ravi_function_def_t *def, int A, int pc) {
|
||||
(void)pc;
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// ra
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
|
||||
// destvalue->value_.i =
|
||||
ravi_emit_store_reg_i_withtype(
|
||||
def, gcc_jit_context_new_rvalue_from_int(
|
||||
def->function_context, def->ravi->types->lua_IntegerT, 0),
|
||||
dest);
|
||||
}
|
||||
|
||||
void ravi_emit_LOADK(ravi_function_def_t *def, int A, int Bx, int pc) {
|
||||
|
||||
(void)pc;
|
||||
|
||||
// TValue *rb = k + GETARG_Bx(i);
|
||||
// setobj2s(L, ra, rb);
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// ra
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
|
||||
#if 1
|
||||
TValue *Konst = &def->p->k[Bx];
|
||||
switch (Konst->tt_) {
|
||||
case LUA_TNUMINT:
|
||||
ravi_emit_store_reg_i_withtype(
|
||||
def, gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->lua_IntegerT,
|
||||
Konst->value_.i),
|
||||
dest);
|
||||
break;
|
||||
case LUA_TNUMFLT:
|
||||
ravi_emit_store_reg_n_withtype(def, gcc_jit_context_new_rvalue_from_double(
|
||||
def->function_context,
|
||||
def->ravi->types->lua_NumberT,
|
||||
Konst->value_.n),
|
||||
dest);
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
ravi_emit_store_reg_b_withtype(
|
||||
def,
|
||||
gcc_jit_context_new_rvalue_from_int(
|
||||
def->function_context, def->ravi->types->C_intT, Konst->value_.b),
|
||||
dest);
|
||||
break;
|
||||
default: {
|
||||
#endif
|
||||
// rb
|
||||
gcc_jit_lvalue *src = ravi_emit_get_constant(def, Bx);
|
||||
|
||||
// *ra = *rb
|
||||
ravi_emit_struct_assign(def, dest, src);
|
||||
#if 1
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// R(A) := R(B)
|
||||
void ravi_emit_MOVE(ravi_function_def_t *def, int A, int B) {
|
||||
// setobjs2s(L, ra, RB(i));
|
||||
|
||||
lua_assert(A != B);
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// rb
|
||||
gcc_jit_lvalue *src = ravi_emit_get_register(def, B);
|
||||
// ra
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
|
||||
// *ra = *rb
|
||||
ravi_emit_struct_assign(def, dest, src);
|
||||
}
|
||||
|
||||
// R(A) := (Bool)B; if (C) pc++
|
||||
void ravi_emit_LOADBOOL(ravi_function_def_t *def, int A, int B, int C, int j,
|
||||
int pc) {
|
||||
|
||||
// setbvalue(ra, GETARG_B(i));
|
||||
// if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */
|
||||
|
||||
// ravi_debug_printf4(def, "LOADBOOL(pc=%d) set reg(A=%d) to boolean(B=%d);
|
||||
// if ((C=%d) != 0) skip next\n", ravi_int_constant(def, pc+1),
|
||||
// ravi_int_constant(def, A), ravi_int_constant(def, B),
|
||||
// ravi_int_constant(def, C));
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
// ra
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
// dest->i = 0
|
||||
ravi_emit_store_reg_b_withtype(
|
||||
def, gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, B),
|
||||
dest);
|
||||
if (C) {
|
||||
// Skip next instruction if C
|
||||
ravi_emit_branch(def, def->jmp_targets[j]->jmp);
|
||||
|
||||
gcc_jit_block *block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_LOADBOOL_skip_next", pc));
|
||||
ravi_set_current_block(def, block);
|
||||
}
|
||||
}
|
||||
|
||||
// R(A) := R(B), check R(B) is int
|
||||
void ravi_emit_MOVEI(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
|
||||
// TValue *rb = RB(i);
|
||||
// lua_Integer j;
|
||||
// if (tointeger(rb, &j)) {
|
||||
// setivalue(ra, j);
|
||||
// }
|
||||
// else
|
||||
// luaG_runerror(L, "integer expected");
|
||||
|
||||
gcc_jit_lvalue *var = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->lua_IntegerT,
|
||||
unique_name(def, "OP_RAVI_MOVEI_i", pc));
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *src = ravi_emit_get_register(def, B);
|
||||
|
||||
gcc_jit_lvalue *src_type = ravi_emit_load_type(def, src);
|
||||
|
||||
// Compare src->tt == LUA_TNUMINT
|
||||
gcc_jit_rvalue *cmp1 = ravi_emit_is_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(src_type), LUA__TNUMINT);
|
||||
|
||||
gcc_jit_block *then1 = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RAVI_MOVEI_if_integer", pc));
|
||||
gcc_jit_block *else1 = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RAVI_MOVEI_if_not_integer", pc));
|
||||
gcc_jit_block *end1 = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RAVI_MOVEI_done", pc));
|
||||
|
||||
ravi_emit_conditional_branch(def, cmp1, then1, else1);
|
||||
ravi_set_current_block(def, then1);
|
||||
|
||||
// Already a int - move
|
||||
gcc_jit_lvalue *tmp = ravi_emit_load_reg_i(def, src);
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, var,
|
||||
gcc_jit_lvalue_as_rvalue(tmp));
|
||||
ravi_emit_branch(def, end1);
|
||||
|
||||
// we need to convert
|
||||
ravi_set_current_block(def, else1);
|
||||
|
||||
// Call luaV_tointeger_()
|
||||
gcc_jit_rvalue *var_isint =
|
||||
ravi_function_call2_rvalue(def, def->ravi->types->luaV_tointegerT,
|
||||
gcc_jit_lvalue_get_address(src, NULL),
|
||||
gcc_jit_lvalue_get_address(var, NULL));
|
||||
gcc_jit_rvalue *zero = gcc_jit_context_new_rvalue_from_int(
|
||||
def->function_context, def->ravi->types->C_intT, 0);
|
||||
gcc_jit_rvalue *tobool =
|
||||
ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ, var_isint, zero);
|
||||
|
||||
// Did conversion fail?
|
||||
gcc_jit_block *else2 = gcc_jit_function_new_block(
|
||||
def->jit_function,
|
||||
unique_name(def, "OP_RAVI_MOVEI_if_conversion_failed", pc));
|
||||
ravi_emit_conditional_branch(def, tobool, else2, end1);
|
||||
|
||||
// Conversion failed, so raise error
|
||||
ravi_set_current_block(def, else2);
|
||||
ravi_emit_raise_lua_error(def, "integer expected");
|
||||
|
||||
ravi_emit_branch(def, end1);
|
||||
|
||||
// Conversion OK
|
||||
ravi_set_current_block(def, end1);
|
||||
|
||||
// Set R(A)
|
||||
ravi_emit_store_reg_i_withtype(def, gcc_jit_lvalue_as_rvalue(var), dest);
|
||||
}
|
||||
|
||||
void ravi_emit_MOVEF(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
|
||||
// case OP_RAVI_MOVEF: {
|
||||
// TValue *rb = RB(i);
|
||||
// lua_Number j;
|
||||
// if (tonumber(rb, &j)) {
|
||||
// setfltvalue(ra, j);
|
||||
// }
|
||||
// else
|
||||
// luaG_runerror(L, "float expected");
|
||||
// } break;
|
||||
|
||||
gcc_jit_lvalue *var = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->lua_NumberT,
|
||||
unique_name(def, "OP_RAVI_MOVEF_n", pc));
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *src = ravi_emit_get_register(def, B);
|
||||
|
||||
gcc_jit_lvalue *src_type = ravi_emit_load_type(def, src);
|
||||
|
||||
// Compare src->tt == LUA_TNUMFLT
|
||||
gcc_jit_rvalue *cmp1 = ravi_emit_is_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(src_type), LUA__TNUMFLT);
|
||||
|
||||
gcc_jit_block *then1 = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RAVI_MOVEF_if_float", pc));
|
||||
gcc_jit_block *else1 = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RAVI_MOVEF_if_not_float", pc));
|
||||
gcc_jit_block *end1 = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RAVI_MOVEF_done", pc));
|
||||
|
||||
ravi_emit_conditional_branch(def, cmp1, then1, else1);
|
||||
ravi_set_current_block(def, then1);
|
||||
|
||||
// Already a float - copy to var
|
||||
gcc_jit_lvalue *tmp = ravi_emit_load_reg_n(def, src);
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, var,
|
||||
gcc_jit_lvalue_as_rvalue(tmp));
|
||||
ravi_emit_branch(def, end1);
|
||||
|
||||
// we need to convert
|
||||
ravi_set_current_block(def, else1);
|
||||
|
||||
// Call luaV_tonumber()
|
||||
gcc_jit_rvalue *var_isflt =
|
||||
ravi_function_call2_rvalue(def, def->ravi->types->luaV_tonumberT,
|
||||
gcc_jit_lvalue_get_address(src, NULL),
|
||||
gcc_jit_lvalue_get_address(var, NULL));
|
||||
gcc_jit_rvalue *zero = gcc_jit_context_new_rvalue_from_int(
|
||||
def->function_context, def->ravi->types->C_intT, 0);
|
||||
gcc_jit_rvalue *tobool =
|
||||
ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ, var_isflt, zero);
|
||||
|
||||
// Did conversion fail?
|
||||
gcc_jit_block *else2 = gcc_jit_function_new_block(
|
||||
def->jit_function,
|
||||
unique_name(def, "OP_RAVI_MOVEF_if_conversion_failed", pc));
|
||||
ravi_emit_conditional_branch(def, tobool, else2, end1);
|
||||
|
||||
// Conversion failed, so raise error
|
||||
ravi_set_current_block(def, else2);
|
||||
ravi_emit_raise_lua_error(def, "number expected");
|
||||
|
||||
ravi_emit_branch(def, end1);
|
||||
|
||||
// Conversion OK
|
||||
ravi_set_current_block(def, end1);
|
||||
|
||||
// Set R(A)
|
||||
ravi_emit_store_reg_n_withtype(def, gcc_jit_lvalue_as_rvalue(var), dest);
|
||||
}
|
||||
|
||||
void ravi_emit_TOINT(ravi_function_def_t *def, int A, int pc) {
|
||||
|
||||
// case OP_RAVI_TOINT: {
|
||||
// lua_Integer j;
|
||||
// if (tointeger(ra, &j)) {
|
||||
// setivalue(ra, j);
|
||||
// }
|
||||
// else
|
||||
// luaG_runerror(L, "integer expected");
|
||||
// } break;
|
||||
|
||||
gcc_jit_lvalue *var = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->lua_IntegerT,
|
||||
unique_name(def, "OP_RAVI_TOINT_i", pc));
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *src = dest;
|
||||
|
||||
gcc_jit_lvalue *src_type = ravi_emit_load_type(def, src);
|
||||
|
||||
// Is src->tt != LUA_TNUMINT?
|
||||
gcc_jit_rvalue *cmp1 = ravi_emit_is_not_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(src_type), LUA__TNUMINT);
|
||||
|
||||
gcc_jit_block *then1 = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RAVI_TOINT_if_not_integer", pc));
|
||||
gcc_jit_block *end1 = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RAVI_TOINT_done", pc));
|
||||
|
||||
ravi_emit_conditional_branch(def, cmp1, then1, end1);
|
||||
ravi_set_current_block(def, then1);
|
||||
|
||||
// Call luaV_tointeger_()
|
||||
gcc_jit_rvalue *var_isint =
|
||||
ravi_function_call2_rvalue(def, def->ravi->types->luaV_tointegerT,
|
||||
gcc_jit_lvalue_get_address(src, NULL),
|
||||
gcc_jit_lvalue_get_address(var, NULL));
|
||||
gcc_jit_rvalue *zero = gcc_jit_context_new_rvalue_from_int(
|
||||
def->function_context, def->ravi->types->C_intT, 0);
|
||||
gcc_jit_rvalue *failed_conversion =
|
||||
ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ, var_isint, zero);
|
||||
|
||||
// Did conversion fail?
|
||||
gcc_jit_block *then2 = gcc_jit_function_new_block(
|
||||
def->jit_function,
|
||||
unique_name(def, "OP_RAVI_TOINT_if_conversion_failed", pc));
|
||||
gcc_jit_block *else2 = gcc_jit_function_new_block(
|
||||
def->jit_function,
|
||||
unique_name(def, "OP_RAVI_TOINT_if_conversion_ok", pc));
|
||||
ravi_emit_conditional_branch(def, failed_conversion, then2, else2);
|
||||
|
||||
ravi_set_current_block(def, then2);
|
||||
|
||||
// Conversion failed, so raise error
|
||||
ravi_emit_raise_lua_error(def, "integer expected");
|
||||
|
||||
ravi_emit_branch(def, else2);
|
||||
|
||||
// Conversion OK
|
||||
ravi_set_current_block(def, else2);
|
||||
|
||||
ravi_emit_store_reg_i_withtype(def, gcc_jit_lvalue_as_rvalue(var), dest);
|
||||
|
||||
ravi_emit_branch(def, end1);
|
||||
|
||||
ravi_set_current_block(def, end1);
|
||||
}
|
||||
|
||||
void ravi_emit_TOFLT(ravi_function_def_t *def, int A, int pc) {
|
||||
|
||||
// case OP_RAVI_TOFLT: {
|
||||
// lua_Number j;
|
||||
// if (tonumber(ra, &j)) {
|
||||
// setfltvalue(ra, j);
|
||||
// }
|
||||
// else
|
||||
// luaG_runerror(L, "float expected");
|
||||
// } break;
|
||||
|
||||
gcc_jit_lvalue *var = gcc_jit_function_new_local(
|
||||
def->jit_function, NULL, def->ravi->types->lua_NumberT,
|
||||
unique_name(def, "OP_RAVI_TOFLT_n", pc));
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *src = dest;
|
||||
|
||||
gcc_jit_lvalue *src_type = ravi_emit_load_type(def, src);
|
||||
|
||||
// Is src->tt != LUA_TNUMFLT?
|
||||
gcc_jit_rvalue *cmp1 = ravi_emit_is_not_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(src_type), LUA__TNUMFLT);
|
||||
|
||||
gcc_jit_block *then1 = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RAVI_TOFLT_if_not_float", pc));
|
||||
gcc_jit_block *end1 = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RAVI_TOFLT_done", pc));
|
||||
|
||||
ravi_emit_conditional_branch(def, cmp1, then1, end1);
|
||||
ravi_set_current_block(def, then1);
|
||||
|
||||
// Call luaV_tonumber()
|
||||
gcc_jit_rvalue *var_ptr = gcc_jit_lvalue_get_address(var, NULL);
|
||||
// ravi_debug_printf3(def, "number %p = %f before call to luaV_number\n",
|
||||
// var_ptr, gcc_jit_lvalue_as_rvalue(var));
|
||||
gcc_jit_rvalue *var_isflt = ravi_function_call2_rvalue(
|
||||
def, def->ravi->types->luaV_tonumberT,
|
||||
gcc_jit_lvalue_get_address(src, NULL), var_ptr);
|
||||
gcc_jit_rvalue *zero = gcc_jit_context_new_rvalue_from_int(
|
||||
def->function_context, def->ravi->types->C_intT, 0);
|
||||
gcc_jit_rvalue *failed_conversion =
|
||||
ravi_emit_comparison(def, GCC_JIT_COMPARISON_EQ, var_isflt, zero);
|
||||
|
||||
// Did conversion fail?
|
||||
gcc_jit_block *then2 = gcc_jit_function_new_block(
|
||||
def->jit_function,
|
||||
unique_name(def, "OP_RAVI_TOFLT_if_conversion_failed", pc));
|
||||
gcc_jit_block *else2 = gcc_jit_function_new_block(
|
||||
def->jit_function,
|
||||
unique_name(def, "OP_RAVI_TOFLT_if_conversion_ok", pc));
|
||||
ravi_emit_conditional_branch(def, failed_conversion, then2, else2);
|
||||
|
||||
ravi_set_current_block(def, then2);
|
||||
|
||||
// Conversion failed, so raise error
|
||||
ravi_emit_raise_lua_error(def, "number expected");
|
||||
|
||||
ravi_emit_branch(def, else2);
|
||||
|
||||
// Conversion OK
|
||||
ravi_set_current_block(def, else2);
|
||||
|
||||
// ravi_debug_printf2(def, "number ok = %f\n", gcc_jit_lvalue_as_rvalue(var));
|
||||
ravi_emit_store_reg_n_withtype(def, gcc_jit_lvalue_as_rvalue(var), dest);
|
||||
|
||||
ravi_emit_branch(def, end1);
|
||||
|
||||
ravi_set_current_block(def, end1);
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
#include <ravi_gccjit.h>
|
||||
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
void ravi_emit_CONCAT(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call5_rvalue(
|
||||
def, def->ravi->types->raviV_op_concatT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(def->ci_val),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, A),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, B),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, C)));
|
||||
}
|
||||
|
||||
void ravi_emit_CLOSURE(ravi_function_def_t *def, int A, int Bx, int pc) {
|
||||
(void)pc;
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call5_rvalue(
|
||||
def, def->ravi->types->raviV_op_closureT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(def->ci_val), def->lua_closure,
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, A),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, Bx)));
|
||||
}
|
||||
|
||||
void ravi_emit_VARARG(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
(void)pc;
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call5_rvalue(
|
||||
def, def->ravi->types->raviV_op_varargT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(def->ci_val), def->lua_closure,
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, A),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, B)));
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <ravi_gccjit.h>
|
||||
|
||||
void ravi_emit_RETURN(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
|
||||
// Here is what OP_RETURN looks like. We only compile steps
|
||||
// marked with //*. This is because the rest is only relevant in the
|
||||
// interpreter
|
||||
|
||||
// case OP_RETURN: {
|
||||
// int b = GETARG_B(i);
|
||||
//* if (cl->p->sizep > 0) luaF_close(L, base);
|
||||
//* b = luaD_poscall(L, ra, (b != 0 ? b - 1 : L->top - ra));
|
||||
// if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */
|
||||
// return; /* external invocation: return */
|
||||
// else { /* invocation via reentry: continue execution */
|
||||
// ci = L->ci;
|
||||
// if (b) L->top = ci->top;
|
||||
// goto newframe; /* restart luaV_execute over new Lua function */
|
||||
// }
|
||||
// }
|
||||
|
||||
// As Lua inserts redundant OP_RETURN instructions it is
|
||||
// possible that this is one of them. If this is the case then the
|
||||
// current block may already be terminated - so we have to insert
|
||||
// a new block
|
||||
if (def->current_block_terminated) {
|
||||
gcc_jit_block *block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RETURN", pc));
|
||||
ravi_set_current_block(def, block);
|
||||
}
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// Get pointer to register A
|
||||
gcc_jit_lvalue *ra_ptr = ravi_emit_get_register(def, A);
|
||||
|
||||
// if (cl->p->sizep > 0) luaF_close(L, base);
|
||||
// Get pointer to Proto->sizep
|
||||
gcc_jit_lvalue *psize = ravi_emit_get_Proto_sizep(def);
|
||||
|
||||
// Test if psize > 0
|
||||
gcc_jit_rvalue *psize_gt_0 = ravi_emit_comparison(
|
||||
def, GCC_JIT_COMPARISON_GT, gcc_jit_lvalue_as_rvalue(psize),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, 0));
|
||||
|
||||
gcc_jit_block *then_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RETURN_if_sizep_gt_0", pc));
|
||||
gcc_jit_block *else_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_RETURN_else_sizep_gt_0", pc));
|
||||
|
||||
ravi_emit_conditional_branch(def, psize_gt_0, then_block, else_block);
|
||||
|
||||
ravi_set_current_block(def, then_block);
|
||||
gcc_jit_block_add_eval(def->current_block, NULL,
|
||||
ravi_function_call2_rvalue(
|
||||
def, def->ravi->types->luaF_closeT,
|
||||
gcc_jit_param_as_rvalue(def->L), def->base_ref));
|
||||
// gcc_jit_lvalue_as_rvalue(def->base)));
|
||||
|
||||
ravi_emit_branch(def, else_block);
|
||||
ravi_set_current_block(def, else_block);
|
||||
|
||||
gcc_jit_rvalue *nresults = NULL;
|
||||
if (B != 0)
|
||||
nresults = ravi_int_constant(def, B - 1);
|
||||
else
|
||||
nresults = ravi_emit_num_stack_elements(
|
||||
def, gcc_jit_lvalue_get_address(ra_ptr, NULL));
|
||||
|
||||
//* b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : L->top - ra));
|
||||
gcc_jit_rvalue *b = ravi_function_call4_rvalue(
|
||||
def, def->ravi->types->luaD_poscallT, gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(def->ci_val),
|
||||
gcc_jit_lvalue_get_address(ra_ptr, NULL), nresults);
|
||||
|
||||
gcc_jit_block_end_with_return(def->current_block, NULL, b);
|
||||
def->current_block_terminated = true;
|
||||
}
|
@ -1,577 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <ravi_gccjit.h>
|
||||
#include <assert.h>
|
||||
|
||||
// R(A+1) := R(B); R(A) := R(B)[RK(C)]
|
||||
void ravi_emit_SELF(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
// StkId rb = RB(i);
|
||||
// setobjs2s(L, ra + 1, rb);
|
||||
// Protect(luaV_gettable(L, rb, RKC(i), ra));
|
||||
(void)pc;
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register(def, B);
|
||||
gcc_jit_lvalue *ra1 = ravi_emit_get_register(def, A + 1);
|
||||
ravi_emit_struct_assign(def, ra1, rb);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call4_rvalue(def, def->ravi->types->luaV_gettableT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(rb, NULL),
|
||||
gcc_jit_lvalue_get_address(rc, NULL),
|
||||
gcc_jit_lvalue_get_address(ra, NULL)));
|
||||
}
|
||||
|
||||
// R(A) := length of R(B)
|
||||
void ravi_emit_LEN(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
// Protect(luaV_objlen(L, ra, RB(i)));
|
||||
(void)pc;
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register(def, B);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call3_rvalue(def, def->ravi->types->luaV_objlenT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(ra, NULL),
|
||||
gcc_jit_lvalue_get_address(rb, NULL)));
|
||||
}
|
||||
|
||||
// R(A)[RK(B)] := RK(C)
|
||||
void ravi_emit_SETTABLE(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
// Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
|
||||
(void)pc;
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call4_rvalue(def, def->ravi->types->luaV_settableT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(ra, NULL),
|
||||
gcc_jit_lvalue_get_address(rb, NULL),
|
||||
gcc_jit_lvalue_get_address(rc, NULL)));
|
||||
}
|
||||
|
||||
// R(A) := R(B)[RK(C)]
|
||||
void ravi_emit_GETTABLE(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
// Protect(luaV_gettable(L, RB(i), RKC(i), ra));
|
||||
(void)pc;
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call4_rvalue(def, def->ravi->types->luaV_gettableT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(rb, NULL),
|
||||
gcc_jit_lvalue_get_address(rc, NULL),
|
||||
gcc_jit_lvalue_get_address(ra, NULL)));
|
||||
}
|
||||
|
||||
void ravi_emit_GETTABLE_AF(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc, bool omitArrayGetRangeCheck) {
|
||||
//#define raviH_get_float_inline(L, t, key, v)
|
||||
//{ unsigned ukey = (unsigned)((key));
|
||||
// lua_Number *data = (lua_Number *)t->ravi_array.data;
|
||||
// if (ukey < t->ravi_array.len) {
|
||||
// setfltvalue(v, data[ukey]);
|
||||
// }else
|
||||
// luaG_runerror(L, "array out of bounds");
|
||||
//}
|
||||
|
||||
// TValue *rb = RB(i);
|
||||
// TValue *rc = RKC(i);
|
||||
// lua_Integer idx = ivalue(rc);
|
||||
// Table *t = hvalue(rb);
|
||||
// raviH_get_float_inline(L, t, idx, ra);
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
gcc_jit_lvalue *key = ravi_emit_load_reg_i(def, rc);
|
||||
gcc_jit_rvalue *t = ravi_emit_load_reg_h(def, rb);
|
||||
gcc_jit_rvalue *data = ravi_emit_load_reg_h_floatarray(def, t);
|
||||
gcc_jit_lvalue *len = ravi_emit_load_ravi_arraylength(def, t);
|
||||
gcc_jit_rvalue *ukey = gcc_jit_context_new_cast(
|
||||
def->function_context, NULL, gcc_jit_lvalue_as_rvalue(key),
|
||||
def->ravi->types->lua_UnsignedT);
|
||||
|
||||
gcc_jit_block *then_block = NULL;
|
||||
gcc_jit_block *else_block = NULL;
|
||||
gcc_jit_block *end_block = NULL;
|
||||
|
||||
if (omitArrayGetRangeCheck) {
|
||||
gcc_jit_rvalue *ulen = gcc_jit_context_new_cast(
|
||||
def->function_context, NULL, gcc_jit_lvalue_as_rvalue(len),
|
||||
def->ravi->types->lua_UnsignedT);
|
||||
|
||||
gcc_jit_rvalue *cmp =
|
||||
ravi_emit_comparison(def, GCC_JIT_COMPARISON_LT, ukey, ulen);
|
||||
then_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "GETTABLE_AF_if_in_range", pc));
|
||||
else_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "GETTABLE_AF_if_not_in_range", pc));
|
||||
end_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "GETTABLE_AF_if_end", pc));
|
||||
ravi_emit_conditional_branch(def, cmp, then_block, else_block);
|
||||
ravi_set_current_block(def, then_block);
|
||||
}
|
||||
gcc_jit_rvalue *value = ravi_emit_array_get(def, data, ukey);
|
||||
ravi_emit_store_reg_n_withtype(def, value, ra);
|
||||
|
||||
if (omitArrayGetRangeCheck) {
|
||||
ravi_emit_branch(def, end_block);
|
||||
|
||||
ravi_set_current_block(def, else_block);
|
||||
|
||||
ravi_emit_raise_lua_error(def, "array out of bounds");
|
||||
ravi_emit_branch(def, end_block);
|
||||
|
||||
ravi_set_current_block(def, end_block);
|
||||
}
|
||||
}
|
||||
|
||||
void ravi_emit_GETTABLE_AI(ravi_function_def_t *def, int A, int B, int C,
|
||||
int pc, bool omitArrayGetRangeCheck) {
|
||||
//#define raviH_get_int_inline(L, t, key, v)
|
||||
//{ unsigned ukey = (unsigned)((key));
|
||||
// lua_Integer *data = (lua_Integer *)t->ravi_array.data;
|
||||
// if (ukey < t->ravi_array.len) {
|
||||
// setivalue(v, data[ukey]);
|
||||
// } else
|
||||
// luaG_runerror(L, "array out of bounds");
|
||||
//}
|
||||
|
||||
// TValue *rb = RB(i);
|
||||
// TValue *rc = RKC(i);
|
||||
// lua_Integer idx = ivalue(rc);
|
||||
// Table *t = hvalue(rb);
|
||||
// raviH_get_int_inline(L, t, idx, ra);
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
gcc_jit_lvalue *key = ravi_emit_load_reg_i(def, rc);
|
||||
gcc_jit_rvalue *t = ravi_emit_load_reg_h(def, rb);
|
||||
gcc_jit_rvalue *data = ravi_emit_load_reg_h_intarray(def, t);
|
||||
gcc_jit_lvalue *len = ravi_emit_load_ravi_arraylength(def, t);
|
||||
gcc_jit_rvalue *ukey = gcc_jit_context_new_cast(
|
||||
def->function_context, NULL, gcc_jit_lvalue_as_rvalue(key),
|
||||
def->ravi->types->lua_UnsignedT);
|
||||
|
||||
gcc_jit_block *then_block = NULL;
|
||||
gcc_jit_block *else_block = NULL;
|
||||
gcc_jit_block *end_block = NULL;
|
||||
|
||||
if (omitArrayGetRangeCheck) {
|
||||
gcc_jit_rvalue *ulen = gcc_jit_context_new_cast(
|
||||
def->function_context, NULL, gcc_jit_lvalue_as_rvalue(len),
|
||||
def->ravi->types->lua_UnsignedT);
|
||||
|
||||
gcc_jit_rvalue *cmp =
|
||||
ravi_emit_comparison(def, GCC_JIT_COMPARISON_LT, ukey, ulen);
|
||||
then_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "GETTABLE_AI_if_in_range", pc));
|
||||
else_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "GETTABLE_AI_if_not_in_range", pc));
|
||||
end_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "GETTABLE_AI_if_end", pc));
|
||||
ravi_emit_conditional_branch(def, cmp, then_block, else_block);
|
||||
ravi_set_current_block(def, then_block);
|
||||
}
|
||||
gcc_jit_rvalue *value = ravi_emit_array_get(def, data, ukey);
|
||||
|
||||
ravi_emit_store_reg_i_withtype(def, value, ra);
|
||||
if (omitArrayGetRangeCheck) {
|
||||
ravi_emit_branch(def, end_block);
|
||||
|
||||
ravi_set_current_block(def, else_block);
|
||||
|
||||
ravi_emit_raise_lua_error(def, "array out of bounds");
|
||||
ravi_emit_branch(def, end_block);
|
||||
|
||||
ravi_set_current_block(def, end_block);
|
||||
}
|
||||
}
|
||||
|
||||
void ravi_emit_SETTABLE_AI_AF(ravi_function_def_t *def, int A, int B, int C,
|
||||
bool known_tt, lua_typecode_t tt, int pc) {
|
||||
|
||||
//#define raviH_set_int_inline(L, t, key, value)
|
||||
//{ unsigned ukey = (unsigned)((key));
|
||||
// lua_Integer *data = (lua_Integer *)t->ravi_array.data;
|
||||
// if (ukey < t->ravi_array.len) {
|
||||
// data[ukey] = value;
|
||||
// } else
|
||||
// raviH_set_int(L, t, ukey, value);
|
||||
//}
|
||||
|
||||
// Table *t = hvalue(ra);
|
||||
// TValue *rb = RKB(i);
|
||||
// TValue *rc = RKC(i);
|
||||
// lua_Integer idx = ivalue(rb);
|
||||
// lua_Integer value = ivalue(rc);
|
||||
// raviH_set_int_inline(L, t, idx, value);
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
gcc_jit_lvalue *key = ravi_emit_load_reg_i(def, rb);
|
||||
gcc_jit_lvalue *value = NULL;
|
||||
|
||||
switch (tt) {
|
||||
case LUA__TNUMINT:
|
||||
value = known_tt ? ravi_emit_load_reg_i(def, rc)
|
||||
: ravi_emit_tonumtype(def, rc, LUA__TNUMINT, pc);
|
||||
break;
|
||||
case LUA__TNUMFLT:
|
||||
value = known_tt ? ravi_emit_load_reg_n(def, rc)
|
||||
: ravi_emit_tonumtype(def, rc, LUA__TNUMFLT, pc);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
abort();
|
||||
}
|
||||
|
||||
gcc_jit_rvalue *t = ravi_emit_load_reg_h(def, ra);
|
||||
gcc_jit_rvalue *data = NULL;
|
||||
switch (tt) {
|
||||
case LUA__TNUMINT:
|
||||
data = ravi_emit_load_reg_h_intarray(def, t);
|
||||
break;
|
||||
case LUA__TNUMFLT:
|
||||
data = ravi_emit_load_reg_h_floatarray(def, t);
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
abort();
|
||||
}
|
||||
|
||||
gcc_jit_lvalue *len = ravi_emit_load_ravi_arraylength(def, t);
|
||||
gcc_jit_rvalue *ukey = gcc_jit_context_new_cast(
|
||||
def->function_context, NULL, gcc_jit_lvalue_as_rvalue(key),
|
||||
def->ravi->types->lua_UnsignedT);
|
||||
gcc_jit_rvalue *ulen = gcc_jit_context_new_cast(
|
||||
def->function_context, NULL, gcc_jit_lvalue_as_rvalue(len),
|
||||
def->ravi->types->lua_UnsignedT);
|
||||
|
||||
gcc_jit_rvalue *cmp =
|
||||
ravi_emit_comparison(def, GCC_JIT_COMPARISON_LT, ukey, ulen);
|
||||
gcc_jit_block *then_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "SETTABLE_AX_if_in_range", pc));
|
||||
gcc_jit_block *else_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "SETTABLE_AX_if_not_in_range", pc));
|
||||
gcc_jit_block *end_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "SETTABLE_AX_if_end", pc));
|
||||
ravi_emit_conditional_branch(def, cmp, then_block, else_block);
|
||||
ravi_set_current_block(def, then_block);
|
||||
|
||||
gcc_jit_lvalue *ptr = ravi_emit_array_get_ptr(def, data, ukey);
|
||||
|
||||
gcc_jit_block_add_assignment(def->current_block, NULL, ptr,
|
||||
gcc_jit_lvalue_as_rvalue(value));
|
||||
ravi_emit_branch(def, end_block);
|
||||
|
||||
ravi_set_current_block(def, else_block);
|
||||
|
||||
gcc_jit_function *f = NULL;
|
||||
switch (tt) {
|
||||
case LUA__TNUMINT:
|
||||
f = def->ravi->types->raviH_set_intT;
|
||||
break;
|
||||
case LUA__TNUMFLT:
|
||||
f = def->ravi->types->raviH_set_floatT;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
abort();
|
||||
}
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call4_rvalue(def, f, gcc_jit_param_as_rvalue(def->L), t,
|
||||
ukey, gcc_jit_lvalue_as_rvalue(value)));
|
||||
ravi_emit_branch(def, end_block);
|
||||
|
||||
ravi_set_current_block(def, end_block);
|
||||
}
|
||||
|
||||
// R(A) := UpValue[B]
|
||||
void ravi_emit_GETUPVAL(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
// int b = GETARG_B(i);
|
||||
// setobj2s(L, ra, cl->upvals[b]->v);
|
||||
(void)pc;
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_rvalue *upval = ravi_emit_get_upvals(def, B);
|
||||
gcc_jit_lvalue *v = ravi_emit_load_upval_v(def, upval);
|
||||
ravi_emit_struct_assign(
|
||||
def, ra, gcc_jit_rvalue_dereference(gcc_jit_lvalue_as_rvalue(v), NULL));
|
||||
}
|
||||
|
||||
// UpValue[B] := R(A)
|
||||
void ravi_emit_SETUPVAL(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
#if 1
|
||||
// Work around libgccjit compilation failure
|
||||
// The inline version causes segmentation fault during compilation
|
||||
(void)pc;
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call4_rvalue(def, def->ravi->types->raviV_op_setupvalT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(def->lua_closure_val),
|
||||
gcc_jit_lvalue_get_address(ra, NULL),
|
||||
ravi_int_constant(def, B)));
|
||||
#else
|
||||
// UpVal *uv = cl->upvals[GETARG_B(i)];
|
||||
// setobj(L, uv->v, ra);
|
||||
// luaC_upvalbarrier(L, uv);
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_rvalue *upval = ravi_emit_get_upvals(def, B);
|
||||
gcc_jit_lvalue *v = ravi_emit_load_upval_v(def, upval);
|
||||
ravi_emit_struct_assign(def, v, ra);
|
||||
|
||||
gcc_jit_lvalue *type = ravi_emit_load_type(def, v);
|
||||
|
||||
// (type & BIT_ISCOLLECTIBLE) != 0
|
||||
gcc_jit_rvalue *bit_iscollectible = ravi_int_constant(def, BIT_ISCOLLECTABLE);
|
||||
gcc_jit_rvalue *is_collectible_bit = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_BITWISE_AND,
|
||||
def->ravi->types->C_intT, gcc_jit_lvalue_as_rvalue(type),
|
||||
bit_iscollectible);
|
||||
gcc_jit_rvalue *zero = ravi_int_constant(def, 0);
|
||||
gcc_jit_rvalue *is_collectible = ravi_emit_comparison(
|
||||
def, GCC_JIT_COMPARISON_NE, is_collectible_bit, zero);
|
||||
|
||||
// Is upvalue closed?
|
||||
// (up->v == &up->u.value)
|
||||
gcc_jit_lvalue *value = ravi_emit_load_upval_value(def, upval);
|
||||
gcc_jit_rvalue *upisclosed = ravi_emit_comparison(
|
||||
def, GCC_JIT_COMPARISON_EQ, gcc_jit_lvalue_as_rvalue(v),
|
||||
gcc_jit_lvalue_get_address(value, NULL));
|
||||
|
||||
// Collectible type and upvalue is closed
|
||||
// ((type & BIT_ISCOLLECTIBLE) != 0) && ((up)->v == &(up)->u.value))
|
||||
gcc_jit_rvalue *andcond = gcc_jit_context_new_binary_op(
|
||||
def->function_context, NULL, GCC_JIT_BINARY_OP_LOGICAL_AND,
|
||||
def->ravi->types->C_boolT, is_collectible, upisclosed);
|
||||
|
||||
gcc_jit_block *then = gcc_jit_function_new_block(
|
||||
def->jit_function,
|
||||
unique_name(def, "SETUPVAL_if_collectible_and_upval_is_closed", pc));
|
||||
gcc_jit_block *end = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "SETUPVAL_if_end", pc));
|
||||
|
||||
ravi_emit_conditional_branch(def, andcond, then, end);
|
||||
ravi_set_current_block(def, then);
|
||||
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call2_rvalue(def, def->ravi->types->luaC_upvalbarrierT,
|
||||
gcc_jit_param_as_rvalue(def->L), upval));
|
||||
ravi_emit_branch(def, end);
|
||||
|
||||
ravi_set_current_block(def, end);
|
||||
#endif
|
||||
}
|
||||
|
||||
// UpValue[A][RK(B)] := RK(C)
|
||||
void ravi_emit_SETTABUP(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
|
||||
// int a = GETARG_A(i);
|
||||
// Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
|
||||
|
||||
(void)pc;
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *rb = ravi_emit_get_register_or_constant(def, B);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
|
||||
gcc_jit_rvalue *upval = ravi_emit_get_upvals(def, A);
|
||||
gcc_jit_lvalue *v = ravi_emit_load_upval_v(def, upval);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call4_rvalue(def, def->ravi->types->luaV_settableT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(v),
|
||||
gcc_jit_lvalue_get_address(rb, NULL),
|
||||
gcc_jit_lvalue_get_address(rc, NULL)));
|
||||
}
|
||||
|
||||
// R(A) := UpValue[B][RK(C)]
|
||||
void ravi_emit_GETTABUP(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
// int b = GETARG_B(i);
|
||||
// Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
|
||||
|
||||
(void)pc;
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *rc = ravi_emit_get_register_or_constant(def, C);
|
||||
|
||||
gcc_jit_rvalue *upval = ravi_emit_get_upvals(def, B);
|
||||
gcc_jit_lvalue *v = ravi_emit_load_upval_v(def, upval);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call4_rvalue(def, def->ravi->types->luaV_gettableT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(v),
|
||||
gcc_jit_lvalue_get_address(rc, NULL),
|
||||
gcc_jit_lvalue_get_address(ra, NULL)));
|
||||
}
|
||||
|
||||
void ravi_emit_NEWTABLE(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
// case OP_NEWTABLE: {
|
||||
// int b = GETARG_B(i);
|
||||
// int c = GETARG_C(i);
|
||||
// Table *t = luaH_new(L);
|
||||
// sethvalue(L, ra, t);
|
||||
// if (b != 0 || c != 0)
|
||||
// luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
|
||||
// checkGC(L, ra + 1);
|
||||
// } break;
|
||||
(void)pc;
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call5_rvalue(
|
||||
def, def->ravi->types->raviV_op_newtableT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(def->ci_val),
|
||||
gcc_jit_lvalue_get_address(ra, NULL),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, B),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, C)));
|
||||
}
|
||||
|
||||
void ravi_emit_NEWARRAYINT(ravi_function_def_t *def, int A, int pc) {
|
||||
(void)pc;
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call3_rvalue(def, def->ravi->types->raviV_op_newarrayintT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(def->ci_val),
|
||||
gcc_jit_lvalue_get_address(ra, NULL)));
|
||||
}
|
||||
|
||||
void ravi_emit_NEWARRAYFLOAT(ravi_function_def_t *def, int A, int pc) {
|
||||
(void)pc;
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call3_rvalue(def, def->ravi->types->raviV_op_newarrayfloatT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(def->ci_val),
|
||||
gcc_jit_lvalue_get_address(ra, NULL)));
|
||||
}
|
||||
|
||||
void ravi_emit_SETLIST(ravi_function_def_t *def, int A, int B, int C, int pc) {
|
||||
(void)pc;
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call5_rvalue(
|
||||
def, def->ravi->types->raviV_op_setlistT,
|
||||
gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_as_rvalue(def->ci_val),
|
||||
gcc_jit_lvalue_get_address(ra, NULL),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, B),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, C)));
|
||||
}
|
||||
|
||||
void ravi_emit_TOARRAY(ravi_function_def_t *def, int A, int array_type_expected,
|
||||
const char *errmsg, int pc) {
|
||||
|
||||
// if (!ttistable(ra) || hvalue(ra)->ravi_array.type != RAVI_TARRAYINT)
|
||||
// luaG_runerror(L, "integer[] expected");
|
||||
OpCode op = OP_RAVI_TOTAB;
|
||||
lua_typecode_t expected_type = RAVI__TLTABLE;
|
||||
switch (array_type_expected) {
|
||||
case RAVI_TARRAYINT:
|
||||
op = OP_RAVI_TOARRAYI;
|
||||
expected_type = RAVI__TIARRAY;
|
||||
break;
|
||||
case RAVI_TARRAYFLT:
|
||||
op = OP_RAVI_TOARRAYF;
|
||||
expected_type = RAVI__TFARRAY;
|
||||
break;
|
||||
case RAVI_TTABLE:
|
||||
default: break;
|
||||
}
|
||||
|
||||
ravi_emit_load_base(def);
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *type = ravi_emit_load_type(def, ra);
|
||||
|
||||
// type != expected_type ?
|
||||
gcc_jit_rvalue *cmp1 = ravi_emit_is_not_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(type), expected_type);
|
||||
|
||||
gcc_jit_block *raise_error = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "TOARRAY_if_not_table", pc));
|
||||
gcc_jit_block *done = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "TOARRAY_done", pc));
|
||||
ravi_emit_conditional_branch(def, cmp1, raise_error, done);
|
||||
ravi_set_current_block(def, raise_error);
|
||||
|
||||
// Conversion failed, so raise error
|
||||
ravi_emit_raise_lua_error(def, errmsg);
|
||||
ravi_emit_branch(def, done);
|
||||
|
||||
ravi_set_current_block(def, done);
|
||||
}
|
||||
|
||||
void ravi_emit_MOVEAI(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
ravi_emit_TOARRAY(def, B, RAVI_TARRAYINT, "integer[] expected", pc);
|
||||
gcc_jit_lvalue *src = ravi_emit_get_register(def, B);
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
ravi_emit_struct_assign(def, dest, src);
|
||||
}
|
||||
|
||||
void ravi_emit_MOVEAF(ravi_function_def_t *def, int A, int B, int pc) {
|
||||
ravi_emit_TOARRAY(def, B, RAVI_TARRAYFLT, "number[] expected", pc);
|
||||
gcc_jit_lvalue *src = ravi_emit_get_register(def, B);
|
||||
gcc_jit_lvalue *dest = ravi_emit_get_register(def, A);
|
||||
ravi_emit_struct_assign(def, dest, src);
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
/******************************************************************************
|
||||
* Copyright (C) 2015 Dibyendu Majumdar
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include <ravi_gccjit.h>
|
||||
|
||||
void ravi_emit_TFORCALL(ravi_function_def_t *def, int A, int B, int C, int j,
|
||||
int jA, int pc) {
|
||||
|
||||
// case OP_TFORCALL: {
|
||||
// StkId cb = ra + 3; /* call base */
|
||||
// setobjs2s(L, cb + 2, ra + 2);
|
||||
// setobjs2s(L, cb + 1, ra + 1);
|
||||
// setobjs2s(L, cb, ra);
|
||||
// L->top = cb + 3; /* func. + 2 args (state and index) */
|
||||
// Protect(luaD_call(L, cb, GETARG_C(i), 1));
|
||||
// L->top = ci->top;
|
||||
// i = *(ci->u.l.savedpc++); /* go to next instruction */
|
||||
// ra = RA(i);
|
||||
// lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
|
||||
// goto l_tforloop;
|
||||
// }
|
||||
// case OP_TFORLOOP: {
|
||||
// l_tforloop:
|
||||
// if (!ttisnil(ra + 1)) { /* continue loop? */
|
||||
// setobjs2s(L, ra, ra + 1); /* save control variable */
|
||||
// ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
||||
// }
|
||||
// } break;
|
||||
(void)B;
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// Get pointer to register A
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *ra1 = ravi_emit_get_register(def, A + 1);
|
||||
gcc_jit_lvalue *ra2 = ravi_emit_get_register(def, A + 2);
|
||||
gcc_jit_lvalue *cb = ravi_emit_get_register(def, A + 3);
|
||||
gcc_jit_lvalue *cb1 = ravi_emit_get_register(def, A + 4);
|
||||
gcc_jit_lvalue *cb2 = ravi_emit_get_register(def, A + 5);
|
||||
|
||||
ravi_emit_struct_assign(def, cb2, ra2);
|
||||
ravi_emit_struct_assign(def, cb1, ra1);
|
||||
ravi_emit_struct_assign(def, cb, ra);
|
||||
|
||||
// L->top = cb + 3; /* func. + 2 args (state and index) */
|
||||
ravi_emit_set_L_top_toreg(def, A + 6);
|
||||
|
||||
// Protect(luaD_call(L, cb, GETARG_C(i)));
|
||||
gcc_jit_block_add_eval(
|
||||
def->current_block, NULL,
|
||||
ravi_function_call3_rvalue(
|
||||
def, def->ravi->types->luaD_callT, gcc_jit_param_as_rvalue(def->L),
|
||||
gcc_jit_lvalue_get_address(cb, NULL),
|
||||
gcc_jit_context_new_rvalue_from_int(def->function_context,
|
||||
def->ravi->types->C_intT, C)));
|
||||
// reload base
|
||||
ravi_emit_load_base(def);
|
||||
// L->top = ci->top;
|
||||
ravi_emit_refresh_L_top(def);
|
||||
ra = ravi_emit_get_register(def, jA);
|
||||
ra1 = ravi_emit_get_register(def, jA + 1);
|
||||
gcc_jit_lvalue *type = ravi_emit_load_type(def, ra1);
|
||||
|
||||
// Test if type != LUA_TNIL (0)
|
||||
gcc_jit_rvalue *isnotnil = ravi_emit_is_not_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(type), LUA__TNIL);
|
||||
gcc_jit_block *then_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_TFORCALL_if_not_nil", pc));
|
||||
gcc_jit_block *else_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_TFORCALL_if_nil", pc));
|
||||
ravi_emit_conditional_branch(def, isnotnil, then_block, else_block);
|
||||
|
||||
ravi_set_current_block(def, then_block);
|
||||
|
||||
ravi_emit_struct_assign(def, ra, ra1);
|
||||
// Do the jump
|
||||
ravi_emit_branch(def, def->jmp_targets[j]->jmp);
|
||||
|
||||
// Add the else block and make it current so that the next instruction flows
|
||||
// here
|
||||
ravi_set_current_block(def, else_block);
|
||||
}
|
||||
|
||||
void ravi_emit_TFORLOOP(ravi_function_def_t *def, int A, int j, int pc) {
|
||||
// case OP_TFORLOOP: {
|
||||
// l_tforloop:
|
||||
// if (!ttisnil(ra + 1)) { /* continue loop? */
|
||||
// setobjs2s(L, ra, ra + 1); /* save control variable */
|
||||
// ci->u.l.savedpc += GETARG_sBx(i); /* jump back */
|
||||
// }
|
||||
// } break;
|
||||
|
||||
// Load pointer to base
|
||||
ravi_emit_load_base(def);
|
||||
|
||||
// Get pointer to register A
|
||||
gcc_jit_lvalue *ra = ravi_emit_get_register(def, A);
|
||||
gcc_jit_lvalue *ra1 = ravi_emit_get_register(def, A + 1);
|
||||
gcc_jit_lvalue *type = ravi_emit_load_type(def, ra1);
|
||||
|
||||
// Test if type != LUA_TNIL (0)
|
||||
gcc_jit_rvalue *isnotnil = ravi_emit_is_not_value_of_type(
|
||||
def, gcc_jit_lvalue_as_rvalue(type), LUA__TNIL);
|
||||
gcc_jit_block *then_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_TFORLOOP_if_not_nil", pc));
|
||||
gcc_jit_block *else_block = gcc_jit_function_new_block(
|
||||
def->jit_function, unique_name(def, "OP_TFORLOOP_if_nil", pc));
|
||||
ravi_emit_conditional_branch(def, isnotnil, then_block, else_block);
|
||||
|
||||
ravi_set_current_block(def, then_block);
|
||||
|
||||
ravi_emit_struct_assign(def, ra, ra1);
|
||||
// Do the jump
|
||||
ravi_emit_branch(def, def->jmp_targets[j]->jmp);
|
||||
|
||||
// Add the else block and make it current so that the next instruction flows
|
||||
// here
|
||||
ravi_set_current_block(def, else_block);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue