issue #164 added support for llvm 8.0.1

pull/168/head
Dibyendu Majumdar 5 years ago
parent b607cb0447
commit 1b45bcf320

@ -1,4 +1,5 @@
mkdir buildllvm
cd buildllvm
#cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM/share/llvm/cmake ..
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..
#cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/LLVM5/lib/cmake/llvm ..
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_JIT=ON -DCMAKE_INSTALL_PREFIX=$HOME/ravi -DLLVM_DIR=$HOME/Software/llvm801/lib/cmake/llvm ..

@ -87,6 +87,10 @@
#include "llvm/Support/Error.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Transforms/Scalar/GVN.h"
#if LLVM_VERSION_MAJOR >= 7
#include "llvm/ExecutionEngine/Orc/Legacy.h"
#endif
#endif
#include <algorithm>

@ -398,26 +398,39 @@ class RaviJITState {
// all the IR in modules get released after compilation
// MCJIT is also likely to be removed at some time in
// future so we needed to migrate anyway
// We don't use ORC apis in earlier versions because
// the apis have changed over the releases so it
// We don't use ORC apis in earlier versions because
// the apis have changed over the releases so it
// is simpler to use them in 5.0 and above.
// The ORC usage here is heavily based upon the kaleidoscope
// sample, with some adjustments.
#if LLVM_VERSION_MAJOR >= 8
using ObjectLayerT = llvm::orc::LegacyRTDyldObjectLinkingLayer;
using CompileLayerT = llvm::orc::LegacyIRCompileLayer<ObjectLayerT, llvm::orc::SimpleCompiler>;
using OptimizeFunction = std::function<std::unique_ptr<llvm::Module>(std::unique_ptr<llvm::Module>)>;
using OptimizerLayerT = llvm::orc::LegacyIRTransformLayer<CompileLayerT, OptimizeFunction>;
using ModuleHandle = llvm::orc::VModuleKey;
using CODLayerT = llvm::orc::LegacyCompileOnDemandLayer<OptimizerLayerT>;
#else
using ObjectLayerT = llvm::orc::RTDyldObjectLinkingLayer;
using CompileLayerT =
llvm::orc::IRCompileLayer<ObjectLayerT, llvm::orc::SimpleCompiler>;
using OptimizeFunction = std::function<std::shared_ptr<llvm::Module>(
std::shared_ptr<llvm::Module>)>;
using OptimizerLayerT =
llvm::orc::IRTransformLayer<CompileLayerT, OptimizeFunction>;
using CompileLayerT = llvm::orc::IRCompileLayer<ObjectLayerT, llvm::orc::SimpleCompiler>;
using OptimizeFunction = std::function<std::shared_ptr<llvm::Module>(std::shared_ptr<llvm::Module>)>;
using OptimizerLayerT = llvm::orc::IRTransformLayer<CompileLayerT, OptimizeFunction>;
using ModuleHandle = OptimizerLayerT::ModuleHandleT;
#endif
std::unique_ptr<llvm::TargetMachine> TM;
std::unique_ptr<llvm::DataLayout> DL;
std::unique_ptr<ObjectLayerT> ObjectLayer;
std::unique_ptr<CompileLayerT> CompileLayer;
std::unique_ptr<OptimizerLayerT> OptimizeLayer;
#if LLVM_VERSION_MAJOR >= 8
std::map<ModuleHandle, std::shared_ptr<llvm::orc::SymbolResolver>> Resolvers;
std::shared_ptr<llvm::orc::SymbolStringPool> stringPool;
std::unique_ptr<llvm::orc::ExecutionSession> execSession;
std::unique_ptr<llvm::orc::JITCompileCallbackManager> CompileCallbackManager;
std::unique_ptr<CODLayerT> CODLayer;
#endif
#endif
@ -438,7 +451,7 @@ class RaviJITState {
// Size level (LLVM PassManagerBuilder)
unsigned int size_level_ : 2;
// Verbosity
unsigned int verbosity_ : 3;
@ -449,7 +462,7 @@ class RaviJITState {
// Enable extra validation such as IR verification
// May slow down compilation
unsigned int validation_ : 1;
// Flag to control calls to collect
int gcstep_;
@ -462,7 +475,7 @@ class RaviJITState {
// Count of modules allocated
// Used to debug module deallocation
size_t allocated_modules_;
// flag to help avoid recursion
int compiling_;
@ -471,7 +484,11 @@ class RaviJITState {
~RaviJITState();
#if USE_ORC_JIT
#if LLVM_VERSION_MAJOR >= 8
std::unique_ptr<llvm::Module> optimizeModule(std::unique_ptr<llvm::Module> M);
#else
std::shared_ptr<llvm::Module> optimizeModule(std::shared_ptr<llvm::Module> M);
#endif
llvm::TargetMachine &getTargetMachine() { return *TM; }
ModuleHandle addModule(std::unique_ptr<llvm::Module> M);
llvm::JITSymbol findSymbol(const std::string Name);
@ -490,41 +507,38 @@ class RaviJITState {
void set_enabled(bool value) { enabled_ = value; }
int get_optlevel() const { return opt_level_; }
void set_optlevel(int value) {
if (value >= 0 && value <= 3) opt_level_ = value;
if (value >= 0 && value <= 3)
opt_level_ = value;
}
int get_sizelevel() const { return size_level_; }
void set_sizelevel(int value) {
if (value >= 0 && value <= 2) size_level_ = value;
if (value >= 0 && value <= 2)
size_level_ = value;
}
int get_verbosity() const { return verbosity_; }
void set_verbosity(int value) {
if (value >= 0 && value <= 3) verbosity_ = value;
if (value >= 0 && value <= 3)
verbosity_ = value;
}
int get_mincodesize() const { return min_code_size_; }
void set_mincodesize(int value) {
min_code_size_ = value > 0 ? value : min_code_size_;
}
void set_mincodesize(int value) { min_code_size_ = value > 0 ? value : min_code_size_; }
int get_minexeccount() const { return min_exec_count_; }
void set_minexeccount(int value) {
min_exec_count_ = value > 0 ? value : min_exec_count_;
}
void set_minexeccount(int value) { min_exec_count_ = value > 0 ? value : min_exec_count_; }
int get_validation() const { return validation_; }
void set_validation(bool value) { validation_ = value; }
int get_gcstep() const { return gcstep_; }
void set_gcstep(int value) {
gcstep_ = value > 0 ? value : gcstep_;
}
void set_gcstep(int value) { gcstep_ = value > 0 ? value : gcstep_; }
bool is_tracehook_enabled() const { return tracehook_enabled_; }
void set_tracehook_enabled(bool value) { tracehook_enabled_ = value; }
void incr_allocated_modules() { allocated_modules_++; }
void decr_allocated_modules() { allocated_modules_--; }
size_t allocated_modules() const { return allocated_modules_; }
int get_compiling_flag() const { return compiling_ > 0; }
void set_compiling_flag(bool value) {
if (value)
void set_compiling_flag(bool value) {
if (value)
compiling_++;
else
compiling_--;
compiling_--;
}
};
@ -567,7 +581,7 @@ class RaviJITModule {
llvm::Module *module() const { return module_; }
llvm::ExecutionEngine *engine() const { return engine_; }
#else
// Note that this can return nullptr
// Note that this can return nullptr
llvm::Module *module() const { return module_.get(); }
#endif
RaviJITState *owner() const { return owner_; }
@ -596,8 +610,7 @@ class RaviJITModule {
// Add declaration for an extern function that is not
// loaded dynamically - i.e., is part of the the executable
// and therefore not visible at runtime by name
llvm::Function *addExternFunction(llvm::FunctionType *type, void *address,
const std::string &name);
llvm::Function *addExternFunction(llvm::FunctionType *type, void *address, const std::string &name);
};
// Represents a JITed or JITable function
@ -629,14 +642,9 @@ class RaviJITFunction {
lua_CFunction *func_ptrptr_;
public:
RaviJITFunction(lua_CFunction *p,
const std::shared_ptr<RaviJITModule> &module,
llvm::FunctionType *type,
llvm::GlobalValue::LinkageTypes linkage,
const std::string &name);
RaviJITFunction(lua_CFunction *p,
const std::shared_ptr<RaviJITModule> &module,
const std::string &name);
RaviJITFunction(lua_CFunction *p, const std::shared_ptr<RaviJITModule> &module, llvm::FunctionType *type,
llvm::GlobalValue::LinkageTypes linkage, const std::string &name);
RaviJITFunction(lua_CFunction *p, const std::shared_ptr<RaviJITModule> &module, const std::string &name);
~RaviJITFunction();
@ -658,8 +666,7 @@ class RaviJITFunction {
void dumpAssembly() { module_->dumpAssembly(); }
int getId() const { return id_; }
void setId(int id) { id_ = id; }
llvm::Function *addExternFunction(llvm::FunctionType *type, void *address,
const std::string &name) {
llvm::Function *addExternFunction(llvm::FunctionType *type, void *address, const std::string &name) {
return module_->addExternFunction(type, address, name);
}
};
@ -815,8 +822,7 @@ class RaviCodeGenerator {
// The p->ravi_jit structure will be updated
// Note that if a function fails to compile then
// a flag is set so that it doesn't get compiled again
bool compile(lua_State *L, Proto *p, std::shared_ptr<RaviJITModule> module,
ravi_compile_options_t *options);
bool compile(lua_State *L, Proto *p, std::shared_ptr<RaviJITModule> module, ravi_compile_options_t *options);
// We can only compile a subset of op codes
// and not all features are supported
@ -830,30 +836,22 @@ class RaviCodeGenerator {
// Argument will be named L
// Initial BasicBlock will be created
// int func(lua_State *L) {
std::unique_ptr<RaviJITFunction> create_function(
Proto *p, std::shared_ptr<RaviJITModule> module,
llvm::IRBuilder<> &builder, RaviFunctionDef *def);
std::unique_ptr<RaviJITFunction> create_function(Proto *p, std::shared_ptr<RaviJITModule> module,
llvm::IRBuilder<> &builder, RaviFunctionDef *def);
// Save proto->code[pc] into savedpc
void emit_update_savedpc(RaviFunctionDef *def, int pc);
llvm::CallInst *CreateCall1(llvm::IRBuilder<> *builder, llvm::Value *func,
llvm::Value *arg1);
llvm::CallInst *CreateCall2(llvm::IRBuilder<> *builder, llvm::Value *func,
llvm::Value *arg1, llvm::Value *arg2);
llvm::CallInst *CreateCall3(llvm::IRBuilder<> *builder, llvm::Value *func,
llvm::Value *arg1, llvm::Value *arg2,
llvm::CallInst *CreateCall1(llvm::IRBuilder<> *builder, llvm::Value *func, llvm::Value *arg1);
llvm::CallInst *CreateCall2(llvm::IRBuilder<> *builder, llvm::Value *func, llvm::Value *arg1, llvm::Value *arg2);
llvm::CallInst *CreateCall3(llvm::IRBuilder<> *builder, llvm::Value *func, llvm::Value *arg1, llvm::Value *arg2,
llvm::Value *arg3);
llvm::CallInst *CreateCall4(llvm::IRBuilder<> *builder, llvm::Value *func,
llvm::Value *arg1, llvm::Value *arg2,
llvm::CallInst *CreateCall4(llvm::IRBuilder<> *builder, llvm::Value *func, llvm::Value *arg1, llvm::Value *arg2,
llvm::Value *arg3, llvm::Value *arg4);
llvm::CallInst *CreateCall5(llvm::IRBuilder<> *builder, llvm::Value *func,
llvm::Value *arg1, llvm::Value *arg2,
llvm::Value *arg3, llvm::Value *arg4,
llvm::Value *arg5);
llvm::CallInst *CreateCall5(llvm::IRBuilder<> *builder, llvm::Value *func, llvm::Value *arg1, llvm::Value *arg2,
llvm::Value *arg3, llvm::Value *arg4, llvm::Value *arg5);
void attach_branch_weights(RaviFunctionDef *def, llvm::Instruction *ins,
uint32_t true_branch, uint32_t false_branch);
void attach_branch_weights(RaviFunctionDef *def, llvm::Instruction *ins, uint32_t true_branch, uint32_t false_branch);
void emit_raise_lua_error(RaviFunctionDef *def, const char *str);
@ -864,28 +862,23 @@ class RaviCodeGenerator {
llvm::Instruction *emit_load_proto_sizep(RaviFunctionDef *def);
// Store lua_Number or lua_Integer
llvm::Instruction *emit_store_local_n(RaviFunctionDef *def, llvm::Value *src,
llvm::Value *dest);
llvm::Instruction *emit_store_local_n(RaviFunctionDef *def, llvm::Value *src, llvm::Value *dest);
// Load lua_Number or lua_Integer
llvm::Instruction *emit_load_local_n(RaviFunctionDef *def, llvm::Value *src);
// Store int
llvm::Instruction *emit_store_local_int(RaviFunctionDef *def,
llvm::Value *src, llvm::Value *dest);
llvm::Instruction *emit_store_local_int(RaviFunctionDef *def, llvm::Value *src, llvm::Value *dest);
// Load int
llvm::Instruction *emit_load_local_int(RaviFunctionDef *def,
llvm::Value *src);
llvm::Instruction *emit_load_local_int(RaviFunctionDef *def, llvm::Value *src);
// Test if value type is of specific Lua type
// Value_type should have been obtained by emit_load_type()
// The Lua typecode to check must be in lua_typecode
// The return value is a boolean type as a result of
// integer comparison result which is i1 in LLVM
llvm::Value *emit_is_value_of_type(RaviFunctionDef *def,
llvm::Value *value_type,
LuaTypeCode lua_typecode,
llvm::Value *emit_is_value_of_type(RaviFunctionDef *def, llvm::Value *value_type, LuaTypeCode lua_typecode,
const char *varname = "value.typeof");
// Test if value type is NOT of specific Lua type
@ -893,9 +886,8 @@ class RaviCodeGenerator {
// The Lua typecode to check must be in lua_typecode
// The return value is a boolean type as a result of
// integer comparison result which is i1 in LLVM
llvm::Value *emit_is_not_value_of_type(
RaviFunctionDef *def, llvm::Value *value_type, LuaTypeCode lua_typecode,
const char *varname = "value.not.typeof");
llvm::Value *emit_is_not_value_of_type(RaviFunctionDef *def, llvm::Value *value_type, LuaTypeCode lua_typecode,
const char *varname = "value.not.typeof");
// Test if value type is NOT of specific Lua type class
// i.e. variants are ignore
@ -903,30 +895,23 @@ class RaviCodeGenerator {
// The Lua typecode to check must be in lua_typecode
// The return value is a boolean type as a result of
// integer comparison result which is i1 in LLVM
llvm::Value *emit_is_not_value_of_type_class(
RaviFunctionDef *def, llvm::Value *value_type, int lua_typecode,
const char *varname = "value.not.typeof");
llvm::Value *emit_is_not_value_of_type_class(RaviFunctionDef *def, llvm::Value *value_type, int lua_typecode,
const char *varname = "value.not.typeof");
// emit code for LClosure *cl = clLvalue(ci->func)
// this is same as:
// emit code for (LClosure *)ci->func->value_.gc
llvm::Instruction *emit_gep_ci_func_value_gc_asLClosure(RaviFunctionDef *def);
llvm::Value *emit_gep(RaviFunctionDef *def, const char *name, llvm::Value *s,
int arg1);
llvm::Value *emit_gep(RaviFunctionDef *def, const char *name, llvm::Value *s,
int arg1, int arg2);
llvm::Value *emit_gep(RaviFunctionDef *def, const char *name, llvm::Value *s,
int arg1, int arg2, int arg3);
llvm::Value *emit_gep(RaviFunctionDef *def, const char *name,
llvm::Value *ptr, llvm::Value *arg1, int arg2,
llvm::Value *emit_gep(RaviFunctionDef *def, const char *name, llvm::Value *s, int arg1);
llvm::Value *emit_gep(RaviFunctionDef *def, const char *name, llvm::Value *s, int arg1, int arg2);
llvm::Value *emit_gep(RaviFunctionDef *def, const char *name, llvm::Value *s, int arg1, int arg2, int arg3);
llvm::Value *emit_gep(RaviFunctionDef *def, const char *name, llvm::Value *ptr, llvm::Value *arg1, int arg2,
int arg3);
llvm::Value *emit_gep(RaviFunctionDef *def, const char *name,
llvm::Value *ptr, llvm::Value *arg1, int arg2);
llvm::Value *emit_gep(RaviFunctionDef *def, const char *name, llvm::Value *ptr, llvm::Value *arg1, int arg2);
// emit code for &ptr[offset]
llvm::Value *emit_array_get(RaviFunctionDef *def, llvm::Value *ptr,
int offset);
llvm::Value *emit_array_get(RaviFunctionDef *def, llvm::Value *ptr, int offset);
// emit code to load pointer L->ci->u.l.base
void emit_load_base(RaviFunctionDef *def);
@ -975,73 +960,57 @@ class RaviCodeGenerator {
// Gets the size of the hash table
// This is the sizenode() macro in lobject.h
llvm::Value *emit_table_get_hashsize(RaviFunctionDef *def,
llvm::Value *table);
llvm::Value *emit_table_get_hashsize(RaviFunctionDef *def, llvm::Value *table);
// Gets the location of the hash node for given string key
// return value is the offset into the node array
llvm::Value *emit_table_get_hashstr(RaviFunctionDef *def, llvm::Value *table,
TString *key);
llvm::Value *emit_table_get_hashstr(RaviFunctionDef *def, llvm::Value *table, TString *key);
// Gets access to the Table's node array (t->node)
llvm::Value *emit_table_get_nodearray(RaviFunctionDef *def,
llvm::Value *table);
llvm::Value *emit_table_get_nodearray(RaviFunctionDef *def, llvm::Value *table);
// Given a pointer to table's node array (node = t->node) and
// the location of the hashed key (index), this method retrieves the
// type of the value stored at the node - return value is of type int
// and is the type information stored in TValue->tt field.
llvm::Value *emit_table_get_keytype(RaviFunctionDef *def, llvm::Value *node,
llvm::Value *index);
llvm::Value *emit_table_get_keytype(RaviFunctionDef *def, llvm::Value *node, llvm::Value *index);
// Given a pointer to table's node array (node = t->node) and
// the location of the hashed key (index), this method retrieves the
// the string value stored at the node - return value is of type TString*
llvm::Value *emit_table_get_strkey(RaviFunctionDef *def, llvm::Value *node,
llvm::Value *index);
llvm::Value *emit_table_get_strkey(RaviFunctionDef *def, llvm::Value *node, llvm::Value *index);
// Given a pointer to table's node array (node = t->node) and
// the location of the hashed key (index), this method retrieves the
// the pointer to value stored at the node - return value is of type TValue*
llvm::Value *emit_table_get_value(RaviFunctionDef *def, llvm::Value *node,
llvm::Value *index);
llvm::Value *emit_table_get_value(RaviFunctionDef *def, llvm::Value *node, llvm::Value *index);
// Gets the size of the table's array part
llvm::Value *emit_table_get_arraysize(RaviFunctionDef *def,
llvm::Value *table);
llvm::Value *emit_table_get_arraysize(RaviFunctionDef *def, llvm::Value *table);
llvm::Value *emit_table_get_array(RaviFunctionDef *def, llvm::Value *table);
llvm::Value *emit_table_no_metamethod(RaviFunctionDef *def,
llvm::Value *table, TMS event);
llvm::Value *emit_table_no_metamethod(RaviFunctionDef *def, llvm::Value *table, TMS event);
llvm::Instruction *emit_load_reg_s(RaviFunctionDef *def, llvm::Value *rb);
// emit code to load pointer to int array
llvm::Instruction *emit_load_reg_h_intarray(RaviFunctionDef *def,
llvm::Instruction *ra);
llvm::Instruction *emit_load_reg_h_intarray(RaviFunctionDef *def, llvm::Instruction *ra);
// emit code to load pointer to double array
llvm::Instruction *emit_load_reg_h_floatarray(RaviFunctionDef *def,
llvm::Instruction *ra);
llvm::Instruction *emit_load_reg_h_floatarray(RaviFunctionDef *def, llvm::Instruction *ra);
// emit code to store lua_Number value into register
void emit_store_reg_n(RaviFunctionDef *def, llvm::Value *value,
llvm::Value *dest_ptr);
void emit_store_reg_n_withtype(RaviFunctionDef *def, llvm::Value *value,
llvm::Value *dest_ptr);
void emit_store_reg_n(RaviFunctionDef *def, llvm::Value *value, llvm::Value *dest_ptr);
void emit_store_reg_n_withtype(RaviFunctionDef *def, llvm::Value *value, llvm::Value *dest_ptr);
// emit code to store lua_Integer value into register
void emit_store_reg_i(RaviFunctionDef *def, llvm::Value *value,
llvm::Value *dest_ptr);
void emit_store_reg_i_withtype(RaviFunctionDef *def, llvm::Value *value,
llvm::Value *dest_ptr);
void emit_store_reg_i(RaviFunctionDef *def, llvm::Value *value, llvm::Value *dest_ptr);
void emit_store_reg_i_withtype(RaviFunctionDef *def, llvm::Value *value, llvm::Value *dest_ptr);
// emit code to store bool value into register
void emit_store_reg_b(RaviFunctionDef *def, llvm::Value *value,
llvm::Value *dest_ptr);
void emit_store_reg_b_withtype(RaviFunctionDef *def, llvm::Value *value,
llvm::Value *dest_ptr);
void emit_store_reg_b(RaviFunctionDef *def, llvm::Value *value, llvm::Value *dest_ptr);
void emit_store_reg_b_withtype(RaviFunctionDef *def, llvm::Value *value, llvm::Value *dest_ptr);
// emit code to set the type in the register
void emit_store_type_(RaviFunctionDef *def, llvm::Value *value, int type);
@ -1050,12 +1019,10 @@ class RaviCodeGenerator {
llvm::Instruction *emit_load_type(RaviFunctionDef *def, llvm::Value *value);
// emit code to load the array type
llvm::Instruction *emit_load_ravi_arraytype(RaviFunctionDef *def,
llvm::Value *value);
llvm::Instruction *emit_load_ravi_arraytype(RaviFunctionDef *def, llvm::Value *value);
// emit code to load the array length
llvm::Instruction *emit_load_ravi_arraylength(RaviFunctionDef *def,
llvm::Value *value);
llvm::Instruction *emit_load_ravi_arraylength(RaviFunctionDef *def, llvm::Value *value);
// TValue assign
void emit_assign(RaviFunctionDef *def, llvm::Value *ra, llvm::Value *rb);
@ -1064,25 +1031,20 @@ class RaviCodeGenerator {
llvm::Value *emit_gep_upvals(RaviFunctionDef *def, int offset);
// Load the &upvals[offset] -> result is UpVal*
llvm::Instruction *emit_load_pupval(RaviFunctionDef *def,
llvm::Value *ppupval);
llvm::Instruction *emit_load_pupval(RaviFunctionDef *def, llvm::Value *ppupval);
// Get &upval->v
llvm::Value *emit_gep_upval_v(RaviFunctionDef *def,
llvm::Instruction *pupval);
llvm::Value *emit_gep_upval_v(RaviFunctionDef *def, llvm::Instruction *pupval);
// Load upval->v
llvm::Instruction *emit_load_upval_v(RaviFunctionDef *def,
llvm::Instruction *pupval);
llvm::Instruction *emit_load_upval_v(RaviFunctionDef *def, llvm::Instruction *pupval);
// Get &upval->value -> result is TValue *
llvm::Value *emit_gep_upval_value(RaviFunctionDef *def,
llvm::Instruction *pupval);
llvm::Value *emit_gep_upval_value(RaviFunctionDef *def, llvm::Instruction *pupval);
// isnil(reg) || isboolean(reg) && reg.value == 0
// !(isnil(reg) || isboolean(reg) && reg.value == 0)
llvm::Value *emit_boolean_testfalse(RaviFunctionDef *def, llvm::Value *reg,
bool donot);
llvm::Value *emit_boolean_testfalse(RaviFunctionDef *def, llvm::Value *reg, bool donot);
llvm::Instruction *emit_tointeger(RaviFunctionDef *def, llvm::Value *reg);
@ -1099,14 +1061,12 @@ class RaviCodeGenerator {
void debug_printf1(RaviFunctionDef *def, const char *str, llvm::Value *arg1);
void debug_printf2(RaviFunctionDef *def, const char *str, llvm::Value *arg1,
llvm::Value *arg2);
void debug_printf2(RaviFunctionDef *def, const char *str, llvm::Value *arg1, llvm::Value *arg2);
void debug_printf3(RaviFunctionDef *def, const char *str, llvm::Value *arg1,
llvm::Value *arg2, llvm::Value *arg3);
void debug_printf3(RaviFunctionDef *def, const char *str, llvm::Value *arg1, llvm::Value *arg2, llvm::Value *arg3);
void debug_printf4(RaviFunctionDef *def, const char *str, llvm::Value *arg1,
llvm::Value *arg2, llvm::Value *arg3, llvm::Value *arg4);
void debug_printf4(RaviFunctionDef *def, const char *str, llvm::Value *arg1, llvm::Value *arg2, llvm::Value *arg3,
llvm::Value *arg4);
void emit_dump_stack(RaviFunctionDef *def, const char *str);
void emit_dump_stacktop(RaviFunctionDef *def, const char *str);
@ -1139,19 +1099,15 @@ class RaviCodeGenerator {
void emit_LOADBOOL(RaviFunctionDef *def, int A, int B, int C, int j, int pc);
// Code size priority so go via function calls
void emit_ARITH_calls(RaviFunctionDef *def, int A, int B, int C, OpCode op,
TMS tms, int pc);
void emit_ARITH_calls(RaviFunctionDef *def, int A, int B, int C, OpCode op, TMS tms, int pc);
// integer arith priority over floating
void emit_ARITH_intpriority(RaviFunctionDef *def, int A, int B, int C,
OpCode op, TMS tms, int pc);
void emit_ARITH_intpriority(RaviFunctionDef *def, int A, int B, int C, OpCode op, TMS tms, int pc);
// floating arith priority over integer
void emit_ARITH_floatpriority(RaviFunctionDef *def, int A, int B, int C,
OpCode op, TMS tms, int pc);
void emit_ARITH_floatpriority(RaviFunctionDef *def, int A, int B, int C, OpCode op, TMS tms, int pc);
inline void emit_ARITH(RaviFunctionDef *def, int A, int B, int C, OpCode op,
TMS tms, int pc) {
inline void emit_ARITH(RaviFunctionDef *def, int A, int B, int C, OpCode op, TMS tms, int pc) {
#if RAVI_USE_LLVM_ARITH_FLOATPRIORITY
emit_ARITH_floatpriority(def, A, B, C, op, tms, pc);
#else
@ -1207,11 +1163,9 @@ class RaviCodeGenerator {
void emit_JMP(RaviFunctionDef *def, int A, int j, int pc);
void emit_iFORPREP(RaviFunctionDef *def, int A, int sBx, int step_one,
int pc);
void emit_iFORPREP(RaviFunctionDef *def, int A, int sBx, int step_one, int pc);
void emit_iFORLOOP(RaviFunctionDef *def, int A, int sBx, RaviBranchDef &b,
int step_one, int pc);
void emit_iFORLOOP(RaviFunctionDef *def, int A, int sBx, RaviBranchDef &b, int step_one, int pc);
void emit_FORPREP(RaviFunctionDef *def, int A, int sBx, int pc);
@ -1219,8 +1173,7 @@ class RaviCodeGenerator {
void emit_FORPREP2(RaviFunctionDef *def, int A, int sBx, int pc);
void emit_FORLOOP2(RaviFunctionDef *def, int A, int sBx, RaviBranchDef &b,
int pc);
void emit_FORLOOP2(RaviFunctionDef *def, int A, int sBx, RaviBranchDef &b, int pc);
void emit_MOVE(RaviFunctionDef *def, int A, int B, int pc);
@ -1248,36 +1201,29 @@ class RaviCodeGenerator {
void emit_GETTABLE(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_GETTABLE_S(RaviFunctionDef *def, int A, int B, int C, int pc,
TString *key);
void emit_GETTABLE_S(RaviFunctionDef *def, int A, int B, int C, int pc, TString *key);
void emit_GETFIELD(RaviFunctionDef *def, int A, int B, int C, int pc,
TString *key);
void emit_GETFIELD(RaviFunctionDef *def, int A, int B, int C, int pc, TString *key);
void emit_GETI(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_finish_GETTABLE(RaviFunctionDef *def, llvm::Value *phi,
llvm::Value *t, llvm::Value *ra, llvm::Value *rb,
void emit_finish_GETTABLE(RaviFunctionDef *def, llvm::Value *phi, llvm::Value *t, llvm::Value *ra, llvm::Value *rb,
llvm::Value *rc);
void emit_SELF(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_TABLE_SELF_SK(RaviFunctionDef *def, int A, int B, int C, int pc,
TString *key);
void emit_TABLE_SELF_SK(RaviFunctionDef *def, int A, int B, int C, int pc, TString *key);
void emit_SELF_SK(RaviFunctionDef *def, int A, int B, int C, int pc);
void emit_common_GETTABLE_S(RaviFunctionDef *def, int A, int B, int C,
TString *key);
void emit_common_GETTABLE_S(RaviFunctionDef *def, int A, int B, int C, TString *key);
void emit_common_GETTABLE_S_(RaviFunctionDef *def, int A, llvm::Value *rb,
int C, TString *key);
void emit_common_GETTABLE_S_(RaviFunctionDef *def, int A, llvm::Value *rb, int C, TString *key);
void emit_GETUPVAL(RaviFunctionDef *def, int A, int B, int pc);
void emit_SETUPVAL(RaviFunctionDef *def, int A, int B, int pc);
void emit_SETUPVAL_Specific(RaviFunctionDef *def, int A, int B, int pc,
OpCode op, llvm::Function *f);
void emit_SETUPVAL_Specific(RaviFunctionDef *def, int A, int B, int pc, OpCode op, llvm::Function *f);
void emit_GETTABUP(RaviFunctionDef *def, int A, int B, int C, int pc);
@ -1304,41 +1250,33 @@ class RaviCodeGenerator {
// A, B, C must be operands of the OP_EQ/OP_LT/OP_LE instructions
// j must be the jump target (offset of the code to which we need to jump to)
// jA must be the A operand of the jump instruction
void emit_EQ(RaviFunctionDef *def, int A, int B, int C, int j, int jA,
llvm::Constant *callee, OpCode opCode, int pc);
void emit_EQ(RaviFunctionDef *def, int A, int B, int C, int j, int jA, llvm::Constant *callee, OpCode opCode, int pc);
// OP_TEST is followed by a OP_JMP instruction - both are handled
// together
// A, B, C must be operands of the OP_TEST instruction
// j must be the jump target (offset of the code to which we need to jump to)
// jA must be the A operand of the jump instruction
void emit_TEST(RaviFunctionDef *def, int A, int B, int C, int j, int jA,
int pc);
void emit_TEST(RaviFunctionDef *def, int A, int B, int C, int j, int jA, int pc);
// OP_TESTSET is followed by a OP_JMP instruction - both are handled
// together
// A, B, C must be operands of the OP_TESTSET instruction
// j must be the jump target (offset of the code to which we need to jump to)
// jA must be the A operand of the jump instruction
void emit_TESTSET(RaviFunctionDef *def, int A, int B, int C, int j, int jA,
int pc);
void emit_TESTSET(RaviFunctionDef *def, int A, int B, int C, int j, int jA, int pc);
void emit_TFORCALL(RaviFunctionDef *def, int A, int B, int C, int j, int jA,
int pc);
void emit_TFORCALL(RaviFunctionDef *def, int A, int B, int C, int j, int jA, int pc);
void emit_TFORLOOP(RaviFunctionDef *def, int A, int j, int pc);
void emit_FARRAY_GET(RaviFunctionDef *def, int A, int B, int C,
bool omitArrayGetRangeCheck, int pc);
void emit_FARRAY_GET(RaviFunctionDef *def, int A, int B, int C, bool omitArrayGetRangeCheck, int pc);
void emit_IARRAY_GET(RaviFunctionDef *def, int A, int B, int C,
bool omitArrayGetRangeCheck, int pc);
void emit_IARRAY_GET(RaviFunctionDef *def, int A, int B, int C, bool omitArrayGetRangeCheck, int pc);
void emit_FARRAY_SET(RaviFunctionDef *def, int A, int B, int C,
bool known_int, int pc);
void emit_FARRAY_SET(RaviFunctionDef *def, int A, int B, int C, bool known_int, int pc);
void emit_IARRAY_SET(RaviFunctionDef *def, int A, int B, int C,
bool known_float, int pc);
void emit_IARRAY_SET(RaviFunctionDef *def, int A, int B, int C, bool known_float, int pc);
void emit_MOVEIARRAY(RaviFunctionDef *def, int A, int B, int pc);
@ -1346,24 +1284,19 @@ class RaviCodeGenerator {
void emit_MOVETAB(RaviFunctionDef *def, int A, int B, int pc);
void emit_TOARRAY(RaviFunctionDef *def, int A, int array_type_expected,
const char *errmsg, int pc);
void emit_TOARRAY(RaviFunctionDef *def, int A, int array_type_expected, const char *errmsg, int pc);
void emit_BITWISE_BINARY_OP(RaviFunctionDef *def, OpCode op, int A, int B,
int C, int pc);
void emit_BITWISE_BINARY_OP(RaviFunctionDef *def, OpCode op, int A, int B, int C, int pc);
void emit_BITWISE_SHIFT_OP(RaviFunctionDef *def, OpCode op, int A, int B,
int C, int pc);
void emit_BITWISE_SHIFT_OP(RaviFunctionDef *def, OpCode op, int A, int B, int C, int pc);
void emit_BNOT_I(RaviFunctionDef *def, int A, int B, int pc);
void emit_BOR_BXOR_BAND(RaviFunctionDef *def, OpCode op, int A, int B, int C,
int pc);
void emit_BOR_BXOR_BAND(RaviFunctionDef *def, OpCode op, int A, int B, int C, int pc);
void emit_BNOT(RaviFunctionDef *def, int A, int B, int pc);
void emit_bitwise_shiftl(RaviFunctionDef *def, llvm::Value *ra, int B,
lua_Integer y);
void emit_bitwise_shiftl(RaviFunctionDef *def, llvm::Value *ra, int B, lua_Integer y);
private:
RaviJITState *jitState_;

@ -42,75 +42,74 @@ static std::atomic_int init;
static struct {
const char *name;
void *address;
} global_syms[] = {
{"lua_absindex", reinterpret_cast<void *>(lua_absindex)},
{"lua_gettop", reinterpret_cast<void *>(lua_gettop)},
{"lua_settop", reinterpret_cast<void *>(lua_settop)},
{"lua_pushvalue", reinterpret_cast<void *>(lua_pushvalue)},
{"lua_rotate", reinterpret_cast<void *>(lua_rotate)},
{"lua_copy", reinterpret_cast<void *>(lua_copy)},
{"lua_checkstack", reinterpret_cast<void *>(lua_checkstack)},
{"lua_xmove", reinterpret_cast<void *>(lua_xmove)},
{"lua_isnumber", reinterpret_cast<void *>(lua_isnumber)},
{"lua_isstring", reinterpret_cast<void *>(lua_isstring)},
{"lua_iscfunction", reinterpret_cast<void *>(lua_iscfunction)},
{"lua_isinteger", reinterpret_cast<void *>(lua_isinteger)},
{"lua_isuserdata", reinterpret_cast<void *>(lua_isuserdata)},
{"lua_type", reinterpret_cast<void *>(lua_type)},
{"lua_typename", reinterpret_cast<void *>(lua_typename)},
{"lua_tonumberx", reinterpret_cast<void *>(lua_tonumberx)},
{"lua_tointegerx", reinterpret_cast<void *>(lua_tointegerx)},
{"lua_toboolean", reinterpret_cast<void *>(lua_toboolean)},
{"lua_tolstring", reinterpret_cast<void *>(lua_tolstring)},
{"lua_rawlen", reinterpret_cast<void *>(lua_rawlen)},
{"lua_tocfunction", reinterpret_cast<void *>(lua_tocfunction)},
{"lua_touserdata", reinterpret_cast<void *>(lua_touserdata)},
{"lua_tothread", reinterpret_cast<void *>(lua_tothread)},
{"lua_topointer", reinterpret_cast<void *>(lua_topointer)},
{"lua_arith", reinterpret_cast<void *>(lua_arith)},
{"lua_rawequal", reinterpret_cast<void *>(lua_rawequal)},
{"lua_compare", reinterpret_cast<void *>(lua_compare)},
{"lua_pushnil", reinterpret_cast<void *>(lua_pushnil)},
{"lua_pushnumber", reinterpret_cast<void *>(lua_pushnumber)},
{"lua_pushinteger", reinterpret_cast<void *>(lua_pushinteger)},
{"lua_pushlstring", reinterpret_cast<void *>(lua_pushlstring)},
{"lua_pushstring", reinterpret_cast<void *>(lua_pushstring)},
{"lua_pushvfstring", reinterpret_cast<void *>(lua_pushvfstring)},
{"lua_pushfstring", reinterpret_cast<void *>(lua_pushfstring)},
{"lua_pushcclosure", reinterpret_cast<void *>(lua_pushcclosure)},
{"lua_pushboolean", reinterpret_cast<void *>(lua_pushboolean)},
{"lua_pushlightuserdata", reinterpret_cast<void *>(lua_pushlightuserdata)},
{"lua_pushthread", reinterpret_cast<void *>(lua_pushthread)},
{"lua_getglobal", reinterpret_cast<void *>(lua_getglobal)},
{"lua_gettable", reinterpret_cast<void *>(lua_gettable)},
{"lua_getfield", reinterpret_cast<void *>(lua_getfield)},
{"lua_geti", reinterpret_cast<void *>(lua_geti)},
{"lua_rawget", reinterpret_cast<void *>(lua_rawget)},
{"lua_rawgeti", reinterpret_cast<void *>(lua_rawgeti)},
{"lua_rawgetp", reinterpret_cast<void *>(lua_rawgetp)},
{"lua_createtable", reinterpret_cast<void *>(lua_createtable)},
{"lua_newuserdata", reinterpret_cast<void *>(lua_newuserdata)},
{"lua_getmetatable", reinterpret_cast<void *>(lua_getmetatable)},
{"lua_getuservalue", reinterpret_cast<void *>(lua_getuservalue)},
{"lua_setglobal", reinterpret_cast<void *>(lua_setglobal)},
{"lua_settable", reinterpret_cast<void *>(lua_settable)},
{"lua_setfield", reinterpret_cast<void *>(lua_setfield)},
{"lua_seti", reinterpret_cast<void *>(lua_seti)},
{"lua_rawset", reinterpret_cast<void *>(lua_rawset)},
{"lua_rawseti", reinterpret_cast<void *>(lua_rawseti)},
{"lua_rawsetp", reinterpret_cast<void *>(lua_rawsetp)},
{"lua_setmetatable", reinterpret_cast<void *>(lua_setmetatable)},
{"lua_setuservalue", reinterpret_cast<void *>(lua_setuservalue)},
{"lua_gc", reinterpret_cast<void *>(lua_gc)},
{"lua_error", reinterpret_cast<void *>(lua_error)},
{"lua_next", reinterpret_cast<void *>(lua_next)},
{"lua_concat", reinterpret_cast<void *>(lua_concat)},
{"lua_len", reinterpret_cast<void *>(lua_len)},
{"lua_stringtonumber", reinterpret_cast<void *>(lua_stringtonumber)},
{"printf", reinterpret_cast<void *>(printf)},
{"puts", reinterpret_cast<void *>(puts)},
{nullptr, nullptr}};
} global_syms[] = {{"lua_absindex", reinterpret_cast<void *>(lua_absindex)},
{"lua_gettop", reinterpret_cast<void *>(lua_gettop)},
{"lua_settop", reinterpret_cast<void *>(lua_settop)},
{"lua_pushvalue", reinterpret_cast<void *>(lua_pushvalue)},
{"lua_rotate", reinterpret_cast<void *>(lua_rotate)},
{"lua_copy", reinterpret_cast<void *>(lua_copy)},
{"lua_checkstack", reinterpret_cast<void *>(lua_checkstack)},
{"lua_xmove", reinterpret_cast<void *>(lua_xmove)},
{"lua_isnumber", reinterpret_cast<void *>(lua_isnumber)},
{"lua_isstring", reinterpret_cast<void *>(lua_isstring)},
{"lua_iscfunction", reinterpret_cast<void *>(lua_iscfunction)},
{"lua_isinteger", reinterpret_cast<void *>(lua_isinteger)},
{"lua_isuserdata", reinterpret_cast<void *>(lua_isuserdata)},
{"lua_type", reinterpret_cast<void *>(lua_type)},
{"lua_typename", reinterpret_cast<void *>(lua_typename)},
{"lua_tonumberx", reinterpret_cast<void *>(lua_tonumberx)},
{"lua_tointegerx", reinterpret_cast<void *>(lua_tointegerx)},
{"lua_toboolean", reinterpret_cast<void *>(lua_toboolean)},
{"lua_tolstring", reinterpret_cast<void *>(lua_tolstring)},
{"lua_rawlen", reinterpret_cast<void *>(lua_rawlen)},
{"lua_tocfunction", reinterpret_cast<void *>(lua_tocfunction)},
{"lua_touserdata", reinterpret_cast<void *>(lua_touserdata)},
{"lua_tothread", reinterpret_cast<void *>(lua_tothread)},
{"lua_topointer", reinterpret_cast<void *>(lua_topointer)},
{"lua_arith", reinterpret_cast<void *>(lua_arith)},
{"lua_rawequal", reinterpret_cast<void *>(lua_rawequal)},
{"lua_compare", reinterpret_cast<void *>(lua_compare)},
{"lua_pushnil", reinterpret_cast<void *>(lua_pushnil)},
{"lua_pushnumber", reinterpret_cast<void *>(lua_pushnumber)},
{"lua_pushinteger", reinterpret_cast<void *>(lua_pushinteger)},
{"lua_pushlstring", reinterpret_cast<void *>(lua_pushlstring)},
{"lua_pushstring", reinterpret_cast<void *>(lua_pushstring)},
{"lua_pushvfstring", reinterpret_cast<void *>(lua_pushvfstring)},
{"lua_pushfstring", reinterpret_cast<void *>(lua_pushfstring)},
{"lua_pushcclosure", reinterpret_cast<void *>(lua_pushcclosure)},
{"lua_pushboolean", reinterpret_cast<void *>(lua_pushboolean)},
{"lua_pushlightuserdata", reinterpret_cast<void *>(lua_pushlightuserdata)},
{"lua_pushthread", reinterpret_cast<void *>(lua_pushthread)},
{"lua_getglobal", reinterpret_cast<void *>(lua_getglobal)},
{"lua_gettable", reinterpret_cast<void *>(lua_gettable)},
{"lua_getfield", reinterpret_cast<void *>(lua_getfield)},
{"lua_geti", reinterpret_cast<void *>(lua_geti)},
{"lua_rawget", reinterpret_cast<void *>(lua_rawget)},
{"lua_rawgeti", reinterpret_cast<void *>(lua_rawgeti)},
{"lua_rawgetp", reinterpret_cast<void *>(lua_rawgetp)},
{"lua_createtable", reinterpret_cast<void *>(lua_createtable)},
{"lua_newuserdata", reinterpret_cast<void *>(lua_newuserdata)},
{"lua_getmetatable", reinterpret_cast<void *>(lua_getmetatable)},
{"lua_getuservalue", reinterpret_cast<void *>(lua_getuservalue)},
{"lua_setglobal", reinterpret_cast<void *>(lua_setglobal)},
{"lua_settable", reinterpret_cast<void *>(lua_settable)},
{"lua_setfield", reinterpret_cast<void *>(lua_setfield)},
{"lua_seti", reinterpret_cast<void *>(lua_seti)},
{"lua_rawset", reinterpret_cast<void *>(lua_rawset)},
{"lua_rawseti", reinterpret_cast<void *>(lua_rawseti)},
{"lua_rawsetp", reinterpret_cast<void *>(lua_rawsetp)},
{"lua_setmetatable", reinterpret_cast<void *>(lua_setmetatable)},
{"lua_setuservalue", reinterpret_cast<void *>(lua_setuservalue)},
{"lua_gc", reinterpret_cast<void *>(lua_gc)},
{"lua_error", reinterpret_cast<void *>(lua_error)},
{"lua_next", reinterpret_cast<void *>(lua_next)},
{"lua_concat", reinterpret_cast<void *>(lua_concat)},
{"lua_len", reinterpret_cast<void *>(lua_len)},
{"lua_stringtonumber", reinterpret_cast<void *>(lua_stringtonumber)},
{"printf", reinterpret_cast<void *>(printf)},
{"puts", reinterpret_cast<void *>(puts)},
{nullptr, nullptr}};
// Construct the JIT compiler state
// The JIT compiler state will be attached to the
@ -142,8 +141,7 @@ RaviJITState::RaviJITState()
init++;
}
triple_ = llvm::sys::getProcessTriple();
#if defined(_WIN32) && \
(!defined(_WIN64) || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7)
#if defined(_WIN32) && (!defined(_WIN64) || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7)
// On Windows we get compilation error saying incompatible object format
// Reading posts on mailing lists I found that the issue is that COEFF
// format is not supported and therefore we need to set -elf as the object
@ -156,25 +154,36 @@ RaviJITState::RaviJITState()
llvm::EngineBuilder eengineBuilder;
auto target = eengineBuilder.selectTarget();
TM = std::unique_ptr<llvm::TargetMachine>(target);
TM->setO0WantsFastISel(true); // enable FastISel when -O0 is used
TM->setO0WantsFastISel(true); // enable FastISel when -O0 is used
DL = std::unique_ptr<llvm::DataLayout>(new llvm::DataLayout(TM->createDataLayout()));
ObjectLayer = std::unique_ptr<ObjectLayerT>(new ObjectLayerT(
[]() { return std::make_shared<llvm::SectionMemoryManager>(); }));
CompileLayer = std::unique_ptr<CompileLayerT>(new CompileLayerT(
*ObjectLayer, llvm::orc::SimpleCompiler(*TM)));
#if LLVM_VERSION_MAJOR >= 8
stringPool = std::make_shared<llvm::orc::SymbolStringPool>();
execSession = std::unique_ptr<llvm::orc::ExecutionSession>(new llvm::orc::ExecutionSession(stringPool));
ObjectLayer = std::unique_ptr<ObjectLayerT>(new ObjectLayerT(*execSession, [this](llvm::orc::VModuleKey K) {
return ObjectLayerT::Resources{std::make_shared<llvm::SectionMemoryManager>(), Resolvers[K]};
}));
#else
ObjectLayer =
std::unique_ptr<ObjectLayerT>(new ObjectLayerT([]() { return std::make_shared<llvm::SectionMemoryManager>(); }));
#endif
CompileLayer = std::unique_ptr<CompileLayerT>(new CompileLayerT(*ObjectLayer, llvm::orc::SimpleCompiler(*TM)));
OptimizeLayer = std::unique_ptr<OptimizerLayerT>(new OptimizerLayerT(
*CompileLayer,
[this](std::shared_ptr<llvm::Module> M) {
return optimizeModule(std::move(M));
})),
*CompileLayer, [this](std::unique_ptr<llvm::Module> M) { return optimizeModule(std::move(M)); }));
CompileCallbackManager =
cantFail(llvm::orc::createLocalCompileCallbackManager(TM->getTargetTriple(), *execSession, 0));
CODLayer = std::unique_ptr<CODLayerT>(new CODLayerT(
*execSession, *OptimizeLayer, [&](llvm::orc::VModuleKey K) { return Resolvers[K]; },
[&](llvm::orc::VModuleKey K, std::shared_ptr<llvm::orc::SymbolResolver> R) { Resolvers[K] = std::move(R); },
[](llvm::Function &F) { return std::set<llvm::Function *>({&F}); }, *CompileCallbackManager,
llvm::orc::createLocalIndirectStubsManagerBuilder(TM->getTargetTriple())));
llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
#endif
types_ = new LuaLLVMTypes(*context_);
for (int i = 0; global_syms[i].name != nullptr; i++) {
llvm::sys::DynamicLibrary::AddSymbol(global_syms[i].name,
global_syms[i].address);
llvm::sys::DynamicLibrary::AddSymbol(global_syms[i].name, global_syms[i].address);
}
}
@ -187,8 +196,11 @@ RaviJITState::~RaviJITState() {
}
#if USE_ORC_JIT
std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(
std::shared_ptr<llvm::Module> M) {
#if LLVM_VERSION_MAJOR >= 8
std::unique_ptr<llvm::Module> RaviJITState::optimizeModule(std::unique_ptr<llvm::Module> M) {
#else
std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(std::shared_ptr<llvm::Module> M) {
#endif
#if LLVM_VERSION_MAJOR > 3 || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7
using llvm::legacy::FunctionPassManager;
using llvm::legacy::PassManager;
@ -196,7 +208,7 @@ std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(
using llvm::FunctionPassManager;
using llvm::PassManager;
#endif
if (get_verbosity() >= 1)
M->print(llvm::errs(), NULL, false, true);
if (get_verbosity() >= 3)
@ -233,9 +245,8 @@ std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(
auto target_layout = engine_->getTargetMachine()->getDataLayout();
module_->setDataLayout(target_layout);
FPM->add(new llvm::DataLayoutPass(*engine_->getDataLayout()));
#elif LLVM_VERSION_MAJOR > 3 || \
LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7
// Apparently no need to set DataLayout
#elif LLVM_VERSION_MAJOR > 3 || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7
// Apparently no need to set DataLayout
#else
#error Unsupported LLVM version
#endif
@ -243,7 +254,8 @@ std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(
FPM->doInitialization();
// Run the optimizations over all functions in the module being added to
// the JIT.
for (auto &F : *M) FPM->run(F);
for (auto &F : *M)
FPM->run(F);
}
std::string codestr;
@ -275,6 +287,9 @@ std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(
break;
}
if (TM->addPassesToEmitFile(*MPM, formatted_stream,
#if LLVM_VERSION_MAJOR >= 7
nullptr, // DWO output file
#endif
llvm::TargetMachine::CGFT_AssemblyFile)) {
llvm::errs() << "unable to add passes for generating assemblyfile\n";
break;
@ -287,8 +302,9 @@ std::shared_ptr<llvm::Module> RaviJITState::optimizeModule(
formatted_stream.flush();
#endif
}
if (get_verbosity() == 2 && codestr.length() > 0) llvm::errs() << codestr << "\n";
if (get_verbosity() == 2 && codestr.length() > 0)
llvm::errs() << codestr << "\n";
return M;
}
@ -299,41 +315,68 @@ void RaviJITState::addGlobalSymbol(const std::string &name, void *address) {
}
#if USE_ORC_JIT
RaviJITState::ModuleHandle RaviJITState::addModule(
std::unique_ptr<llvm::Module> M) {
RaviJITState::ModuleHandle RaviJITState::addModule(std::unique_ptr<llvm::Module> M) {
#if LLVM_VERSION_MAJOR >= 8
// Create a new VModuleKey.
llvm::orc::VModuleKey K = execSession->allocateVModule();
// Build a resolver and associate it with the new key.
Resolvers[K] =
createLegacyLookupResolver(*execSession,
[this](const std::string &Name) -> llvm::JITSymbol {
if (auto Sym = CompileLayer->findSymbol(Name, false))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
if (auto SymAddr = llvm::RTDyldMemoryManager::getSymbolAddressInProcess(Name))
return llvm::JITSymbol(SymAddr, llvm::JITSymbolFlags::Exported);
return nullptr;
},
[](llvm::Error Err) { cantFail(std::move(Err), "lookupFlags failed"); });
// Add the module to the JIT with the new key.
llvm::cantFail(CODLayer->addModule(K, std::move(M)));
return K;
#else
// Build our symbol resolver:
// Lambda 1: Look back into the JIT itself to find symbols that are part of
// the same "logical dylib".
// Lambda 2: Search for external symbols in the host process.
auto Resolver = llvm::orc::createLambdaResolver(
[&](const std::string &Name) {
if (auto Sym = OptimizeLayer->findSymbol(Name, false)) return Sym;
if (auto Sym = OptimizeLayer->findSymbol(Name, false))
return Sym;
return llvm::JITSymbol(nullptr);
},
[](const std::string &Name) {
if (auto SymAddr =
llvm::RTDyldMemoryManager::getSymbolAddressInProcess(Name))
if (auto SymAddr = llvm::RTDyldMemoryManager::getSymbolAddressInProcess(Name))
return llvm::JITSymbol(SymAddr, llvm::JITSymbolFlags::Exported);
return llvm::JITSymbol(nullptr);
});
// Add the set to the JIT with the resolver we created above and a newly
// created SectionMemoryManager.
return llvm::cantFail(
OptimizeLayer->addModule(std::move(M), std::move(Resolver)));
return llvm::cantFail(OptimizeLayer->addModule(std::move(M), std::move(Resolver)));
#endif
}
llvm::JITSymbol RaviJITState::findSymbol(const std::string Name) {
std::string MangledName;
llvm::raw_string_ostream MangledNameStream(MangledName);
llvm::Mangler::getNameWithPrefix(MangledNameStream, Name, *DL);
#if LLVM_VERSION_MAJOR >= 8
return CODLayer->findSymbol(MangledNameStream.str(), false);
#else
// Note that the LLVM tutorial uses true below but that appears to
// cause a failure in lookup
return OptimizeLayer->findSymbol(MangledNameStream.str(), false);
#endif
}
void RaviJITState::removeModule(ModuleHandle H) {
#if LLVM_VERSION_MAJOR >= 8
llvm::cantFail(CODLayer->removeModule(H));
#else
llvm::cantFail(OptimizeLayer->removeModule(H));
#endif
}
#endif
@ -344,8 +387,9 @@ static std::atomic_int module_id;
RaviJITModule::RaviJITModule(RaviJITState *owner)
: owner_(owner)
#if !USE_ORC_JIT
,module_(nullptr)
,engine_(nullptr)
,
module_(nullptr),
engine_(nullptr)
#endif
{
int myid = module_id++;
@ -369,18 +413,14 @@ RaviJITModule::RaviJITModule(RaviJITState *owner)
// (int)TvalueSize, (int)TvalueSizeOf);
assert(sizeof(Value) == layout->getTypeAllocSize(owner->types()->ValueT));
assert(sizeof(TValue) == layout->getTypeAllocSize(owner->types()->TValueT));
assert(sizeof(UTString) ==
layout->getTypeAllocSize(owner->types()->TStringT));
assert(sizeof(UTString) == layout->getTypeAllocSize(owner->types()->TStringT));
assert(sizeof(Udata) == layout->getTypeAllocSize(owner->types()->UdataT));
assert(sizeof(CallInfo) ==
layout->getTypeAllocSize(owner->types()->CallInfoT));
assert(sizeof(lua_State) ==
layout->getTypeAllocSize(owner->types()->lua_StateT));
assert(sizeof(CallInfo) == layout->getTypeAllocSize(owner->types()->CallInfoT));
assert(sizeof(lua_State) == layout->getTypeAllocSize(owner->types()->lua_StateT));
delete layout;
}
#if !USE_ORC_JIT
#if defined(_WIN32) && \
(!defined(_WIN64) || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7)
#if defined(_WIN32) && (!defined(_WIN64) || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 7)
// On Windows we get error saying incompatible object format
// Reading posts on mailing lists I found that the issue is that COEFF
// format is not supported and therefore we need to set
@ -400,8 +440,7 @@ RaviJITModule::RaviJITModule(RaviJITState *owner)
builder.setErrorStr(&errStr);
engine_ = builder.create();
if (!engine_) {
fprintf(stderr, "FATAL ERROR: could not create ExecutionEngine: %s\n",
errStr.c_str());
fprintf(stderr, "FATAL ERROR: could not create ExecutionEngine: %s\n", errStr.c_str());
abort();
return;
}
@ -437,24 +476,17 @@ void RaviJITModule::removeFunction(RaviJITFunction *f) {
functions_[f->getId()] = nullptr;
}
RaviJITFunction::RaviJITFunction(lua_CFunction *p,
const std::shared_ptr<RaviJITModule> &module,
llvm::FunctionType *type,
llvm::GlobalValue::LinkageTypes linkage,
RaviJITFunction::RaviJITFunction(lua_CFunction *p, const std::shared_ptr<RaviJITModule> &module,
llvm::FunctionType *type, llvm::GlobalValue::LinkageTypes linkage,
const std::string &name)
: module_(module),
name_(name),
function_(nullptr),
ptr_(nullptr),
func_ptrptr_(p) {
: module_(module), name_(name), function_(nullptr), ptr_(nullptr), func_ptrptr_(p) {
auto M = module_->module();
lua_assert(M);
function_ = llvm::Function::Create(type, linkage, name, M);
id_ = module_->addFunction(this);
}
RaviJITFunction::RaviJITFunction(lua_CFunction *p,
const std::shared_ptr<RaviJITModule> &module,
RaviJITFunction::RaviJITFunction(lua_CFunction *p, const std::shared_ptr<RaviJITModule> &module,
const std::string &name)
: module_(module), name_(name), ptr_(nullptr), func_ptrptr_(p) {
auto M = module_->module();
@ -470,7 +502,8 @@ RaviJITFunction::~RaviJITFunction() {
}
void RaviJITModule::runpasses(bool dumpAsm) {
if (!module_) return;
if (!module_)
return;
#if !USE_ORC_JIT
#if LLVM_VERSION_MAJOR > 3 || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7
using llvm::legacy::FunctionPassManager;
@ -505,8 +538,7 @@ void RaviJITModule::runpasses(bool dumpAsm) {
auto target_layout = engine_->getTargetMachine()->getDataLayout();
module_->setDataLayout(target_layout);
FPM->add(new llvm::DataLayoutPass(*engine_->getDataLayout()));
#elif LLVM_VERSION_MAJOR > 3 || \
LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7
#elif LLVM_VERSION_MAJOR > 3 || LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7
// Apparently no need to set DataLayout
#else
#error Unsupported LLVM version
@ -514,7 +546,8 @@ void RaviJITModule::runpasses(bool dumpAsm) {
pmb.populateFunctionPassManager(*FPM);
FPM->doInitialization();
for (int i = 0; i < functions_.size(); i++) {
if (functions_[i] == nullptr) continue;
if (functions_[i] == nullptr)
continue;
FPM->run(*functions_[i]->function());
}
}
@ -548,8 +581,7 @@ void RaviJITModule::runpasses(bool dumpAsm) {
llvm::errs() << "unable to dump assembly\n";
break;
}
if (TM->addPassesToEmitFile(*MPM, formatted_stream,
llvm::TargetMachine::CGFT_AssemblyFile)) {
if (TM->addPassesToEmitFile(*MPM, formatted_stream, llvm::TargetMachine::CGFT_AssemblyFile)) {
llvm::errs() << "unable to add passes for generating assemblyfile\n";
break;
}
@ -561,19 +593,23 @@ void RaviJITModule::runpasses(bool dumpAsm) {
formatted_stream.flush();
#endif
}
if (dumpAsm && codestr.length() > 0) llvm::errs() << codestr << "\n";
if (dumpAsm && codestr.length() > 0)
llvm::errs() << codestr << "\n";
#endif
}
void RaviJITModule::finalize(bool doDump) {
lua_assert(module_);
if (!module_) return;
if (!module_)
return;
#if !USE_ORC_JIT
// Following will generate very verbose dump when machine code is
// produced below
llvm::TargetMachine *TM = engine_->getTargetMachine();
// TM->setOptLevel(llvm::CodeGenOpt::None);
if (doDump) { TM->Options.PrintMachineCode = 1; }
if (doDump) {
TM->Options.PrintMachineCode = 1;
}
// Upon creation, MCJIT holds a pointer to the Module object
// that it received from EngineBuilder but it does not immediately
@ -588,7 +624,8 @@ void RaviJITModule::finalize(bool doDump) {
module_handle_ = owner()->addModule(std::move(module_));
#endif
for (int i = 0; i < functions_.size(); i++) {
if (functions_[i] == nullptr) continue;
if (functions_[i] == nullptr)
continue;
functions_[i]->setFunctionPtr();
}
}
@ -617,13 +654,11 @@ void RaviJITFunction::setFunctionPtr() {
#endif
}
llvm::Function *RaviJITModule::addExternFunction(llvm::FunctionType *type,
void *address,
const std::string &name) {
llvm::Function *RaviJITModule::addExternFunction(llvm::FunctionType *type, void *address, const std::string &name) {
auto fn = external_symbols_.find(name);
if (fn != external_symbols_.end()) return fn->second;
llvm::Function *f = llvm::Function::Create(
type, llvm::Function::ExternalLinkage, name, module());
if (fn != external_symbols_.end())
return fn->second;
llvm::Function *f = llvm::Function::Create(type, llvm::Function::ExternalLinkage, name, module());
f->setDoesNotThrow();
// We should have been able to call
// engine_->addGlobalMapping() but this doesn't work
@ -637,7 +672,8 @@ llvm::Function *RaviJITModule::addExternFunction(llvm::FunctionType *type,
void RaviJITModule::dump() {
#if LLVM_VERSION_MAJOR < 5
if (module_) module_->dump();
if (module_)
module_->dump();
#endif
}
@ -659,11 +695,11 @@ std::unique_ptr<RaviJITState> RaviJITStateFactory::newJITState() {
// will return -1
int raviV_initjit(struct lua_State *L) {
global_State *G = G(L);
if (G->ravi_state != NULL) return -1;
if (G->ravi_state != NULL)
return -1;
ravi_State *jit = (ravi_State *)calloc(1, sizeof(ravi_State));
jit->jit = new ravi::RaviJITState();
jit->code_generator =
new ravi::RaviCodeGenerator((ravi::RaviJITState *)jit->jit);
jit->code_generator = new ravi::RaviCodeGenerator((ravi::RaviJITState *)jit->jit);
G->ravi_state = jit;
return 0;
}
@ -671,7 +707,8 @@ int raviV_initjit(struct lua_State *L) {
// Free up the JIT State
void raviV_close(struct lua_State *L) {
global_State *G = G(L);
if (G->ravi_state == NULL) return;
if (G->ravi_state == NULL)
return;
delete G->ravi_state->code_generator;
delete G->ravi_state->jit;
free(G->ravi_state);
@ -683,27 +720,27 @@ void raviV_close(struct lua_State *L) {
// thresholds)
// or if a manual compilation request was made
// Returns true if compilation was successful
int raviV_compile(struct lua_State *L, struct Proto *p,
ravi_compile_options_t *options) {
if (p->ravi_jit.jit_function) return 1;
int raviV_compile(struct lua_State *L, struct Proto *p, ravi_compile_options_t *options) {
if (p->ravi_jit.jit_function)
return 1;
global_State *G = G(L);
if (G->ravi_state == NULL) return 0;
if (!G->ravi_state->jit->is_enabled()) { return 0; }
if (G->ravi_state->jit->get_compiling_flag()) { return 0; }
if (G->ravi_state == NULL)
return 0;
if (!G->ravi_state->jit->is_enabled()) {
return 0;
}
if (G->ravi_state->jit->get_compiling_flag()) {
return 0;
}
bool doCompile = (bool)(options && options->manual_request != 0);
if (!doCompile && G->ravi_state->jit->is_auto()) {
if (p->ravi_jit.jit_flags ==
RAVI_JIT_FLAG_HASFORLOOP) /* function has fornum loop, so compile */
if (p->ravi_jit.jit_flags == RAVI_JIT_FLAG_HASFORLOOP) /* function has fornum loop, so compile */
doCompile = true;
else if (p->sizecode >
G->ravi_state->jit
->get_mincodesize()) /* function is long so compile */
else if (p->sizecode > G->ravi_state->jit->get_mincodesize()) /* function is long so compile */
doCompile = true;
else {
if (p->ravi_jit.execution_count <
G->ravi_state->jit
->get_minexeccount()) /* function has been executed many
times so compile */
if (p->ravi_jit.execution_count < G->ravi_state->jit->get_minexeccount()) /* function has been executed many
times so compile */
p->ravi_jit.execution_count++;
else
doCompile = true;
@ -722,8 +759,7 @@ int raviV_compile(struct lua_State *L, struct Proto *p,
// Compile a bunch of Lua functions
// And put them all in one module
// Returns true if compilation was successful
int raviV_compile_n(struct lua_State *L, struct Proto *p[], int n,
ravi_compile_options_t *options) {
int raviV_compile_n(struct lua_State *L, struct Proto *p[], int n, ravi_compile_options_t *options) {
global_State *G = G(L);
int count = 0;
if (G->ravi_state->jit->get_compiling_flag())
@ -743,9 +779,9 @@ int raviV_compile_n(struct lua_State *L, struct Proto *p[], int n,
// Free the JIT compiled function
// Note that this is called by the garbage collector
void raviV_freeproto(struct lua_State *L, struct Proto *p) {
ravi::RaviJITFunction *f =
reinterpret_cast<ravi::RaviJITFunction *>(p->ravi_jit.jit_data);
if (f) delete f;
ravi::RaviJITFunction *f = reinterpret_cast<ravi::RaviJITFunction *>(p->ravi_jit.jit_data);
if (f)
delete f;
p->ravi_jit.jit_status = RAVI_JIT_NOT_COMPILED;
p->ravi_jit.jit_function = NULL;
p->ravi_jit.jit_data = NULL;
@ -755,133 +791,151 @@ void raviV_freeproto(struct lua_State *L, struct Proto *p) {
// Dump the LLVM IR
void raviV_dumpIR(struct lua_State *L, struct Proto *p) {
if (p->ravi_jit.jit_status == RAVI_JIT_COMPILED) /* compiled */ {
ravi::RaviJITFunction *f =
reinterpret_cast<ravi::RaviJITFunction *>(p->ravi_jit.jit_data);
if (f) f->dump();
ravi::RaviJITFunction *f = reinterpret_cast<ravi::RaviJITFunction *>(p->ravi_jit.jit_data);
if (f)
f->dump();
}
}
// Dump the LLVM ASM
void raviV_dumpASM(struct lua_State *L, struct Proto *p) {
if (p->ravi_jit.jit_status == RAVI_JIT_COMPILED) /* compiled */ {
ravi::RaviJITFunction *f =
reinterpret_cast<ravi::RaviJITFunction *>(p->ravi_jit.jit_data);
if (f) f->dumpAssembly();
ravi::RaviJITFunction *f = reinterpret_cast<ravi::RaviJITFunction *>(p->ravi_jit.jit_data);
if (f)
f->dumpAssembly();
}
}
void raviV_setminexeccount(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
if (!G->ravi_state)
return;
G->ravi_state->jit->set_minexeccount(value);
}
int raviV_getminexeccount(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->get_minexeccount();
}
void raviV_setmincodesize(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
if (!G->ravi_state)
return;
G->ravi_state->jit->set_mincodesize(value);
}
int raviV_getmincodesize(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->get_mincodesize();
}
void raviV_setauto(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
if (!G->ravi_state)
return;
G->ravi_state->jit->set_auto(value != 0);
}
int raviV_getauto(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->is_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;
if (!G->ravi_state)
return;
G->ravi_state->jit->set_enabled(value != 0);
}
int raviV_getjitenabled(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->is_enabled();
}
void raviV_setoptlevel(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
if (!G->ravi_state)
return;
G->ravi_state->jit->set_optlevel(value);
}
int raviV_getoptlevel(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->get_optlevel();
}
void raviV_setsizelevel(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
if (!G->ravi_state)
return;
G->ravi_state->jit->set_sizelevel(value);
}
int raviV_getsizelevel(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->get_sizelevel();
}
void raviV_setverbosity(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
if (!G->ravi_state)
return;
G->ravi_state->jit->set_verbosity(value);
}
int raviV_getverbosity(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->get_verbosity();
}
void raviV_setvalidation(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
if (!G->ravi_state)
return;
G->ravi_state->jit->set_validation(value != 0);
}
int raviV_getvalidation(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->get_validation();
}
void raviV_setgcstep(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
if (!G->ravi_state)
return;
G->ravi_state->jit->set_gcstep(value);
}
int raviV_getgcstep(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->get_gcstep();
}
// Turn on/off the JIT compiler
void raviV_settraceenabled(lua_State *L, int value) {
global_State *G = G(L);
if (!G->ravi_state) return;
if (!G->ravi_state)
return;
G->ravi_state->jit->set_tracehook_enabled(value != 0);
}
int raviV_gettraceenabled(lua_State *L) {
global_State *G = G(L);
if (!G->ravi_state) return 0;
if (!G->ravi_state)
return 0;
return G->ravi_state->jit->is_tracehook_enabled();
}
extern "C" int ravi_compile_C(lua_State *L) {
return 0;
}
extern "C" int ravi_compile_C(lua_State *L) { return 0; }
Loading…
Cancel
Save