pull/81/head
Dibyendu Majumdar 8 years ago
parent 3d6204856c
commit 5472c25f2c

@ -122,8 +122,8 @@ if (LLVM_JIT)
src/ravi_llvmcodegen.cpp src/ravi_llvmforprep.cpp src/ravi_llvmcomp.cpp
src/ravi_llvmreturn.cpp src/ravi_llvmload.cpp src/ravi_llvmforloop.cpp
src/ravi_llvmarith1.cpp src/ravi_llvmcall.cpp src/ravi_llvmtable.cpp
src/ravi_llvmarith2.cpp src/ravi_llvmtforcall.cpp src/ravi_llvmrest.cpp)
# src/ravi_llvmluaapi.cpp)
src/ravi_llvmarith2.cpp src/ravi_llvmtforcall.cpp src/ravi_llvmrest.cpp
src/ravi_llvmluaapi.cpp)
endif ()
if (GCC_JIT)
set(GCC_JIT_SRCS src/ravi_gccjit.c src/ravi_gcctypes.c

@ -424,9 +424,6 @@ typedef struct LocVar {
typedef enum {
RAVI_JIT_NOT_COMPILED = 0,
RAVI_JIT_CANT_COMPILE = 1,
RAVI_JIT_IR_GENERATED = 2,
RAVI_JIT_COMPILED = 3,
RAVI_JIT_FREED = 4
} ravi_jit_status_t;
typedef enum {
@ -435,7 +432,7 @@ typedef enum {
} ravi_jit_flag_t;
typedef struct RaviJITProto {
lu_byte jit_status; /* 0=not compiled, 1=can't compile, 2=IR generated, 3=compiled, 4=freed */
lu_byte jit_status; /* 0=not compiled, 1=can't compile */
lu_byte jit_flags;
unsigned short execution_count; /* how many times has function been executed */
void *jit_data;

@ -342,7 +342,7 @@ struct LuaLLVMTypes {
// The hierarchy of objects
// used to represent LLVM artifacts is as
// follows
// RaviJITState - Root, held in Lua state; wraps llvm::Context
// +- RaviJITModule - wraps llvm::Module
// +- RaviJITFunction - wraps llvm::Function
@ -353,13 +353,13 @@ struct LuaLLVMTypes {
// holds a reference to the owning RaviJITModule
// via a shared_ptr. This ensures that RaviJITModule gets
// released when no longer referenced.
class RAVI_API RaviJITState;
class RAVI_API RaviJITModule;
class RAVI_API RaviJITFunction;
class RAVI_API RaviJITStateFactory {
public:
public:
static std::unique_ptr<RaviJITState> newJITState();
};
@ -400,7 +400,7 @@ class RAVI_API RaviJITModule {
// This calls f->getId() to get the
// functions location in the array
void removeFunction(RaviJITFunction *f);
// Runs LLVM code generation and optimization passes
// The reason for separting this from the
// finalization is that this method is also
@ -414,7 +414,7 @@ class RAVI_API RaviJITModule {
// 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);
const std::string &name);
};
// Represents a JITed or JITable function
@ -441,17 +441,21 @@ class RAVI_API RaviJITFunction {
// Pointer to compiled function
void *ptr_;
// The Lua Proto associated with this function
Proto *proto_;
// A location provided by the caller where the
// compiled function will be saved
lua_CFunction *func_ptrptr_;
public:
RaviJITFunction(Proto *prototype, std::shared_ptr<RaviJITModule> module,
llvm::FunctionType *type,llvm::GlobalValue::LinkageTypes linkage, const std::string &name);
RaviJITFunction(lua_CFunction *p, std::shared_ptr<RaviJITModule> module,
llvm::FunctionType *type,
llvm::GlobalValue::LinkageTypes linkage,
const std::string &name);
~RaviJITFunction();
const std::string &name() const { return name_; }
llvm::Function *function() const { return function_; }
llvm::Module *module() const { return module_->module(); }
RaviJITModule *raviModule() const { return module_.get(); }
llvm::ExecutionEngine *engine() const { return module_->engine(); }
RaviJITState *owner() const { return module_->owner(); }
// This method retrieves the JITed function from the
@ -464,10 +468,9 @@ class RAVI_API RaviJITFunction {
int getId() const { return id_; }
void setId(int id) { id_ = id; }
llvm::Function *addExternFunction(llvm::FunctionType *type, void *address,
const std::string &name) {
const std::string &name) {
return module_->addExternFunction(type, address, name);
}
};
// Ravi's LLVM JIT State
@ -681,7 +684,8 @@ 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
@ -695,8 +699,9 @@ 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);

@ -392,9 +392,8 @@ int luaD_precall (lua_State *L, StkId func, int nresults, int op_call) {
/* not compiled */
raviV_compile(L, p, NULL);
}
if (L == G(L)->mainthread && p->ravi_jit.jit_status == RAVI_JIT_COMPILED) {
if (L == G(L)->mainthread && p->ravi_jit.jit_function) {
/* compiled */
lua_assert(p->ravi_jit.jit_function != NULL);
ci->jitstatus = 1;
/* Since the JITed function does not update savedpc
* other than for calls by default - the stack trace error

@ -52,7 +52,7 @@ static const luaL_Reg loadedlibs[] = {
{LUA_DBLIBNAME, luaopen_debug},
{LUA_RAVILIBNAME, raviopen_llvmjit},
#ifdef USE_LLVM
//{LUA_LLVMLIBNAME, raviopen_llvmluaapi},
{LUA_LLVMLIBNAME, raviopen_llvmluaapi},
#endif
#if defined(LUA_COMPAT_BITLIB)
{LUA_BITLIBNAME, luaopen_bit32},

File diff suppressed because it is too large Load Diff

@ -41,9 +41,14 @@ static std::atomic_int init;
// lua_State - all compilation activity happens
// in the context of the JIT State
RaviJITState::RaviJITState()
: auto_(false), enabled_(true),
opt_level_(2), size_level_(0), min_code_size_(150), min_exec_count_(50),
gc_step_(200), tracehook_enabled_(false) {
: auto_(false),
enabled_(true),
opt_level_(2),
size_level_(0),
min_code_size_(150),
min_exec_count_(50),
gc_step_(200),
tracehook_enabled_(false) {
// LLVM needs to be initialized else
// ExecutionEngine cannot be created
// This needs to be an atomic check although LLVM docs
@ -77,13 +82,12 @@ void RaviJITState::addGlobalSymbol(const std::string &name, void *address) {
llvm::sys::DynamicLibrary::AddSymbol(name, address);
}
void RaviJITState::dump() {
types_->dump();
}
void RaviJITState::dump() { types_->dump(); }
static std::atomic_int module_id;
RaviJITModule::RaviJITModule(RaviJITState *owner) : owner_(owner), engine_(nullptr), module_(nullptr) {
RaviJITModule::RaviJITModule(RaviJITState *owner)
: owner_(owner), engine_(nullptr), module_(nullptr) {
int myid = module_id++;
char buf[40];
snprintf(buf, sizeof buf, "ravi_module_%d", myid);
@ -124,23 +128,27 @@ RaviJITModule::~RaviJITModule() {
delete module_;
}
int
RaviJITModule::addFunction(RaviJITFunction *f) {
int RaviJITModule::addFunction(RaviJITFunction *f) {
int id = functions_.size();
functions_.push_back(f);
return id;
}
void
RaviJITModule::removeFunction(RaviJITFunction *f) {
void RaviJITModule::removeFunction(RaviJITFunction *f) {
lua_assert(functions_[f->getId()] == f);
functions_[f->getId()] = nullptr;
}
RaviJITFunction::RaviJITFunction(
Proto *p, std::shared_ptr<RaviJITModule> module, llvm::FunctionType *type,
llvm::GlobalValue::LinkageTypes linkage, const std::string &name)
: module_(module), name_(name), function_(nullptr), ptr_(nullptr), proto_(p) {
RaviJITFunction::RaviJITFunction(lua_CFunction *p,
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) {
function_ = llvm::Function::Create(type, linkage, name, module_->module());
id_ = module_->addFunction(this);
}
@ -151,7 +159,6 @@ RaviJITFunction::~RaviJITFunction() {
}
void RaviJITModule::runpasses(bool dumpAsm) {
#if LLVM_VERSION_MINOR >= 7
using llvm::legacy::FunctionPassManager;
using llvm::legacy::PassManager;
@ -193,8 +200,7 @@ 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());
}
}
@ -239,8 +245,7 @@ void RaviJITModule::runpasses(bool dumpAsm) {
// Note that in 3.7 this flus appears to have no effect
formatted_stream.flush();
}
if (dumpAsm && codestr.length() > 0)
llvm::errs() << codestr << "\n";
if (dumpAsm && codestr.length() > 0) llvm::errs() << codestr << "\n";
}
void RaviJITModule::finalize(bool doDump) {
@ -248,9 +253,7 @@ void RaviJITModule::finalize(bool doDump) {
// 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
@ -260,8 +263,7 @@ void RaviJITModule::finalize(bool doDump) {
// is called which requires the code to have been generated.
engine_->finalizeObject();
for (int i = 0; i < functions_.size(); i++) {
if (functions_[i] == nullptr)
continue;
if (functions_[i] == nullptr) continue;
functions_[i]->setFunctionPtr();
}
}
@ -270,25 +272,16 @@ void RaviJITModule::finalize(bool doDump) {
// execution engine and store it in ptr_
// Also associate the JITed function with the
// Lua Proto structure
void
RaviJITFunction::setFunctionPtr() {
void RaviJITFunction::setFunctionPtr() {
lua_assert(ptr_ == nullptr);
lua_assert(proto_ != nullptr);
lua_assert(proto_->ravi_jit.jit_data == (void*) this);
ptr_ = engine()->getPointerToFunction(function_);
proto_->ravi_jit.jit_function = (lua_CFunction)ptr_;
*func_ptrptr_ = (lua_CFunction)ptr_;
lua_assert(proto_->ravi_jit.jit_function);
if (proto_->ravi_jit.jit_function == nullptr) {
proto_->ravi_jit.jit_status = RAVI_JIT_CANT_COMPILE; // can't compile
}
else {
proto_->ravi_jit.jit_status = RAVI_JIT_COMPILED;
}
}
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) {
llvm::Function *f = llvm::Function::Create(
type, llvm::Function::ExternalLinkage, name, module_);
f->setDoesNotThrow();
@ -321,8 +314,7 @@ 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 =
@ -334,8 +326,7 @@ 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);
@ -349,14 +340,10 @@ void raviV_close(struct lua_State *L) {
// 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_status == RAVI_JIT_COMPILED)
return true;
if (p->ravi_jit.jit_function) return true;
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 == NULL) return 0;
if (!G->ravi_state->jit->is_enabled()) { return 0; }
bool doCompile = (bool)(options && options->manual_request != 0);
if (!doCompile && G->ravi_state->jit->is_auto()) {
if (p->ravi_jit.jit_flags ==
@ -383,17 +370,16 @@ int raviV_compile(struct lua_State *L, struct Proto *p,
module->finalize(options ? options->dump_level != 0 : 0);
}
}
return p->ravi_jit.jit_status == RAVI_JIT_COMPILED;
return p->ravi_jit.jit_function != nullptr;
}
// 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;
p->ravi_jit.jit_status = RAVI_JIT_FREED;
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;
p->ravi_jit.execution_count = 0;
@ -401,126 +387,108 @@ 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 */ {
if (p->ravi_jit.jit_function) /* compiled */ {
ravi::RaviJITFunction *f =
reinterpret_cast<ravi::RaviJITFunction *>(p->ravi_jit.jit_data);
if (f)
f->dump();
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 */ {
if (p->ravi_jit.jit_function) /* compiled */ {
ravi::RaviJITFunction *f =
reinterpret_cast<ravi::RaviJITFunction *>(p->ravi_jit.jit_data);
if (f)
f->dumpAssembly();
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_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();
}

@ -66,71 +66,74 @@ static const char *LLVM_constant = "LLVMconstant";
static const char *LLVM_instruction = "LLVMinstruction";
static const char *LLVM_phinode = "LLVMphinode";
#define test_LLVM_irbuilder(L, idx) \
#define test_LLVM_irbuilder(L, idx) \
((IRBuilderHolder *)raviU_testudata(L, idx, LLVM_irbuilder))
#define check_LLVM_irbuilder(L, idx) \
#define check_LLVM_irbuilder(L, idx) \
((IRBuilderHolder *)raviU_checkudata(L, idx, LLVM_irbuilder))
#define test_LLVM_type(L, idx) ((TypeHolder *)raviU_testudata(L, idx, LLVM_type))
#define check_LLVM_type(L, idx) ((TypeHolder *)raviU_checkudata(L, idx, LLVM_type))
#define test_LLVM_type(L, idx) \
((TypeHolder *)raviU_testudata(L, idx, LLVM_type))
#define check_LLVM_type(L, idx) \
((TypeHolder *)raviU_checkudata(L, idx, LLVM_type))
#define test_LLVM_context(L, idx) \
#define test_LLVM_context(L, idx) \
((ContextHolder *)raviU_testudata(L, idx, LLVM_context))
#define check_LLVM_context(L, idx) \
#define check_LLVM_context(L, idx) \
((ContextHolder *)raviU_checkudata(L, idx, LLVM_context))
#define test_LLVM_structtype(L, idx) \
#define test_LLVM_structtype(L, idx) \
((StructTypeHolder *)raviU_testudata(L, idx, LLVM_structtype))
#define check_LLVM_structtype(L, idx) \
#define check_LLVM_structtype(L, idx) \
((StructTypeHolder *)raviU_checkudata(L, idx, LLVM_structtype))
#define test_LLVM_pointertype(L, idx) \
#define test_LLVM_pointertype(L, idx) \
((PointerTypeHolder *)raviU_testudata(L, idx, LLVM_pointertype))
#define check_LLVM_pointertype(L, idx) \
#define check_LLVM_pointertype(L, idx) \
((PointerTypeHolder *)raviU_checkudata(L, idx, LLVM_pointertype))
#define test_LLVM_functiontype(L, idx) \
#define test_LLVM_functiontype(L, idx) \
((FunctionTypeHolder *)raviU_testudata(L, idx, LLVM_functiontype))
#define check_LLVM_functiontype(L, idx) \
#define check_LLVM_functiontype(L, idx) \
((FunctionTypeHolder *)raviU_checkudata(L, idx, LLVM_functiontype))
#define test_LLVM_mainfunction(L, idx) \
#define test_LLVM_mainfunction(L, idx) \
((MainFunctionHolder *)raviU_testudata(L, idx, LLVM_mainfunction))
#define check_LLVM_mainfunction(L, idx) \
#define check_LLVM_mainfunction(L, idx) \
((MainFunctionHolder *)raviU_checkudata(L, idx, LLVM_mainfunction))
#define test_LLVM_function(L, idx) \
#define test_LLVM_function(L, idx) \
((FunctionHolder *)raviU_testudata(L, idx, LLVM_function))
#define check_LLVM_function(L, idx) \
#define check_LLVM_function(L, idx) \
((FunctionHolder *)raviU_checkudata(L, idx, LLVM_function))
#define test_LLVM_basicblock(L, idx) \
#define test_LLVM_basicblock(L, idx) \
((BasicBlockHolder *)raviU_testudata(L, idx, LLVM_basicblock))
#define check_LLVM_basicblock(L, idx) \
#define check_LLVM_basicblock(L, idx) \
((BasicBlockHolder *)raviU_checkudata(L, idx, LLVM_basicblock))
#define test_LLVM_value(L, idx) ((ValueHolder *)raviU_testudata(L, idx, LLVM_value))
#define check_LLVM_value(L, idx) \
#define test_LLVM_value(L, idx) \
((ValueHolder *)raviU_testudata(L, idx, LLVM_value))
#define check_LLVM_value(L, idx) \
((ValueHolder *)raviU_checkudata(L, idx, LLVM_value))
#define test_LLVM_constant(L, idx) \
#define test_LLVM_constant(L, idx) \
((ConstantHolder *)raviU_testudata(L, idx, LLVM_constant))
#define check_LLVM_constant(L, idx) \
#define check_LLVM_constant(L, idx) \
((ConstantHolder *)raviU_checkudata(L, idx, LLVM_constant))
#define test_LLVM_instruction(L, idx) \
#define test_LLVM_instruction(L, idx) \
((InstructionHolder *)raviU_testudata(L, idx, LLVM_instruction))
#define check_LLVM_instruction(L, idx) \
#define check_LLVM_instruction(L, idx) \
((InstructionHolder *)raviU_checkudata(L, idx, LLVM_instruction))
#define test_LLVM_module(L, idx) \
#define test_LLVM_module(L, idx) \
((ModuleHolder *)raviU_testudata(L, idx, LLVM_module))
#define check_LLVM_module(L, idx) \
#define check_LLVM_module(L, idx) \
((ModuleHolder *)raviU_checkudata(L, idx, LLVM_module))
#define test_LLVM_phinode(L, idx) \
#define test_LLVM_phinode(L, idx) \
((PhiNodeHolder *)raviU_testudata(L, idx, LLVM_phinode))
#define check_LLVM_phinode(L, idx) \
#define check_LLVM_phinode(L, idx) \
((PhiNodeHolder *)raviU_checkudata(L, idx, LLVM_phinode))
struct ContextHolder {
@ -312,8 +315,9 @@ static MainFunctionHolder *alloc_LLVM_mainfunction(lua_State *L,
h->arg1 = nullptr;
raviU_getmetatable(L, LLVM_mainfunction);
lua_setmetatable(L, -2);
h->func = (ravi::RaviJITFunction *)jit->createFunction(
type, llvm::Function::ExternalLinkage, name);
auto module = std::make_shared<ravi::RaviJITModule>(G(L)->ravi_state->jit);
h->func = new ravi::RaviJITFunction(&h->compiled_func, module, type,
llvm::Function::ExternalLinkage, name);
return h;
}
@ -436,29 +440,17 @@ static int get_llvm_context(lua_State *L) {
static llvm::Value *get_value(lua_State *L, int idx) {
InstructionHolder *ii = test_LLVM_instruction(L, idx);
if (ii) {
return ii->i;
}
if (ii) { return ii->i; }
ValueHolder *v = test_LLVM_value(L, idx);
if (v) {
return v->value;
}
if (v) { return v->value; }
ConstantHolder *c = test_LLVM_constant(L, idx);
if (c) {
return c->constant;
}
if (c) { return c->constant; }
MainFunctionHolder *m = test_LLVM_mainfunction(L, idx);
if (m) {
return m->func->function();
}
if (m) { return m->func->function(); }
FunctionHolder *f = test_LLVM_function(L, idx);
if (f) {
return f->function;
}
if (f) { return f->function; }
PhiNodeHolder *phi = test_LLVM_phinode(L, idx);
if (phi) {
return phi->phi;
}
if (phi) { return phi->phi; }
luaL_argerror(L, idx, "Value expected");
return nullptr;
}
@ -557,26 +549,18 @@ static int struct_add_members(lua_State *L) {
static llvm::Type *return_type(lua_State *L, int idx) {
TypeHolder *th = test_LLVM_type(L, idx);
if (th) {
return th->type;
}
if (th) { return th->type; }
PointerTypeHolder *ph = test_LLVM_pointertype(L, idx);
if (ph) {
return ph->type;
}
if (ph) { return ph->type; }
luaL_argerror(L, idx, "unsupported function return type");
return nullptr;
}
static llvm::Type *arg_type(lua_State *L, int idx) {
TypeHolder *th = test_LLVM_type(L, idx);
if (th) {
return th->type;
}
if (th) { return th->type; }
PointerTypeHolder *ph = test_LLVM_pointertype(L, idx);
if (ph) {
return ph->type;
}
if (ph) { return ph->type; }
luaL_argerror(L, idx, "unsupported function argument type");
return nullptr;
}
@ -592,13 +576,11 @@ static int context_new_function_type(lua_State *L) {
for (int i = 1; i <= len; i++) {
lua_rawgeti(L, 3, i);
llvm::Type *t = arg_type(L, -1);
if (t)
elements.push_back(t);
if (t) elements.push_back(t);
lua_pop(L, 1);
}
bool vararg = false;
if (lua_istable(L, 4))
l_table_get_bool(L, 4, "vararg", &vararg, false);
if (lua_istable(L, 4)) l_table_get_bool(L, 4, "vararg", &vararg, false);
alloc_LLVM_functiontype(L,
llvm::FunctionType::get(typeret, elements, vararg));
return 1;
@ -712,10 +694,10 @@ static int irbuilder_condbranch(lua_State *L) {
static int func_compile(lua_State *L) {
MainFunctionHolder *f = check_LLVM_mainfunction(L, 1);
if (!f->compiled_func) {
f->compiled_func = (lua_CFunction)f->func->compile();
f->func->raviModule()->runpasses();
f->func->raviModule()->finalize();
}
if (!f->compiled_func)
return 0;
if (!f->compiled_func) return 0;
lua_pushvalue(L, 1);
lua_pushcclosure(L, f->compiled_func, 1);
return 1;
@ -730,74 +712,74 @@ typedef struct {
#define str(s) #s
#define decl_func1_(name, ret, arg1, vararg) \
static int name##_decl(lua_State *L, ravi::RaviJITStateImpl *jit, \
ravi::RaviJITFunctionImpl *f) { \
llvm::Type *args[] = { \
jit->types()->arg1, \
}; \
llvm::FunctionType *type = \
llvm::FunctionType::get(jit->types()->ret, args, vararg); \
llvm::Function *extfunc = f->addExternFunction( \
type, reinterpret_cast<void *>(&name), str(name)); \
alloc_LLVM_constant(L, extfunc); \
return 1; \
#define decl_func1_(name, ret, arg1, vararg) \
static int name##_decl(lua_State *L, ravi::RaviJITState *jit, \
ravi::RaviJITFunction *f) { \
llvm::Type *args[] = { \
jit->types()->arg1, \
}; \
llvm::FunctionType *type = \
llvm::FunctionType::get(jit->types()->ret, args, vararg); \
llvm::Function *extfunc = f->addExternFunction( \
type, reinterpret_cast<void *>(&name), str(name)); \
alloc_LLVM_constant(L, extfunc); \
return 1; \
}
#define decl_func1v(name, ret, arg1) decl_func1_(name, ret, arg1, true)
#define decl_func1(name, ret, arg1) decl_func1_(name, ret, arg1, false)
#define decl_func2_(name, ret, arg1, arg2, vararg) \
static int name##_decl(lua_State *L, ravi::RaviJITStateImpl *jit, \
ravi::RaviJITFunctionImpl *f) { \
llvm::Type *args[] = { \
jit->types()->arg1, jit->types()->arg2, \
}; \
llvm::FunctionType *type = \
llvm::FunctionType::get(jit->types()->ret, args, vararg); \
llvm::Function *extfunc = f->addExternFunction( \
type, reinterpret_cast<void *>(&name), str(name)); \
alloc_LLVM_constant(L, extfunc); \
return 1; \
#define decl_func2_(name, ret, arg1, arg2, vararg) \
static int name##_decl(lua_State *L, ravi::RaviJITState *jit, \
ravi::RaviJITFunction *f) { \
llvm::Type *args[] = { \
jit->types()->arg1, jit->types()->arg2, \
}; \
llvm::FunctionType *type = \
llvm::FunctionType::get(jit->types()->ret, args, vararg); \
llvm::Function *extfunc = f->addExternFunction( \
type, reinterpret_cast<void *>(&name), str(name)); \
alloc_LLVM_constant(L, extfunc); \
return 1; \
}
#define decl_func2v(name, ret, arg1, arg2) \
#define decl_func2v(name, ret, arg1, arg2) \
decl_func2_(name, ret, arg1, arg2, true)
#define decl_func2(name, ret, arg1, arg2) \
#define decl_func2(name, ret, arg1, arg2) \
decl_func2_(name, ret, arg1, arg2, false)
#define decl_func3(name, ret, arg1, arg2, arg3) \
static int name##_decl(lua_State *L, ravi::RaviJITStateImpl *jit, \
ravi::RaviJITFunctionImpl *f) { \
llvm::Type *args[] = { \
jit->types()->arg1, jit->types()->arg2, jit->types()->arg3, \
}; \
llvm::FunctionType *type = \
llvm::FunctionType::get(jit->types()->ret, args, false); \
llvm::Function *extfunc = f->addExternFunction( \
type, reinterpret_cast<void *>(&name), str(name)); \
alloc_LLVM_constant(L, extfunc); \
return 1; \
#define decl_func3(name, ret, arg1, arg2, arg3) \
static int name##_decl(lua_State *L, ravi::RaviJITState *jit, \
ravi::RaviJITFunction *f) { \
llvm::Type *args[] = { \
jit->types()->arg1, jit->types()->arg2, jit->types()->arg3, \
}; \
llvm::FunctionType *type = \
llvm::FunctionType::get(jit->types()->ret, args, false); \
llvm::Function *extfunc = f->addExternFunction( \
type, reinterpret_cast<void *>(&name), str(name)); \
alloc_LLVM_constant(L, extfunc); \
return 1; \
}
#define decl_func4(name, ret, arg1, arg2, arg3, arg4) \
static int name##_decl(lua_State *L, ravi::RaviJITStateImpl *jit, \
ravi::RaviJITFunctionImpl *f) { \
llvm::Type *args[] = { \
jit->types()->arg1, jit->types()->arg2, jit->types()->arg3, \
jit->types()->arg4, \
}; \
llvm::FunctionType *type = \
llvm::FunctionType::get(jit->types()->ret, args, false); \
llvm::Function *extfunc = f->addExternFunction( \
type, reinterpret_cast<void *>(&name), str(name)); \
alloc_LLVM_constant(L, extfunc); \
return 1; \
#define decl_func4(name, ret, arg1, arg2, arg3, arg4) \
static int name##_decl(lua_State *L, ravi::RaviJITState *jit, \
ravi::RaviJITFunction *f) { \
llvm::Type *args[] = { \
jit->types()->arg1, jit->types()->arg2, jit->types()->arg3, \
jit->types()->arg4, \
}; \
llvm::FunctionType *type = \
llvm::FunctionType::get(jit->types()->ret, args, false); \
llvm::Function *extfunc = f->addExternFunction( \
type, reinterpret_cast<void *>(&name), str(name)); \
alloc_LLVM_constant(L, extfunc); \
return 1; \
}
#define decl_voidfunc1(name, arg1) decl_func1(name, C_voidT, arg1)
#define decl_voidfunc2(name, arg1, arg2) decl_func2(name, C_voidT, arg1, arg2)
#define decl_voidfunc3(name, arg1, arg2, arg3) \
#define decl_voidfunc3(name, arg1, arg2, arg3) \
decl_func3(name, C_voidT, arg1, arg2, arg3)
decl_func1v(printf, C_intT, C_pcharT);
@ -956,7 +938,8 @@ static int func_addextern(lua_State *L) {
llvm::Constant *c = f->func->module()->getOrInsertFunction(name, tt->type);
alloc_LLVM_constant(L, c);
return 1;
} else {
}
else {
/* TODO binary search */
for (int i = 0; builtin_functions[i].name != nullptr; i++) {
if (strcmp(name, builtin_functions[i].name) == 0) {
@ -996,7 +979,8 @@ static int func_getarg(lua_State *L) {
break;
}
}
} else {
}
else {
results = 0;
}
return results;
@ -1021,28 +1005,22 @@ static int irbuilder_call(lua_State *L) {
lua_pop(L, 1);
}
bool tailcall = false;
if (lua_istable(L, 4))
l_table_get_bool(L, 4, "tailcall", &tailcall, false);
if (lua_istable(L, 4)) l_table_get_bool(L, 4, "tailcall", &tailcall, false);
llvm::CallInst *inst = builder->builder->CreateCall(func, elements);
if (tailcall)
inst->setTailCall();
if (tailcall) inst->setTailCall();
alloc_LLVM_instruction(L, inst);
return 1;
}
static llvm::Type *get_type(lua_State *L, int idx) {
TypeHolder *th = test_LLVM_type(L, idx);
if (th)
return th->type;
if (th) return th->type;
PointerTypeHolder *ph = test_LLVM_pointertype(L, idx);
if (ph)
return ph->type;
if (ph) return ph->type;
StructTypeHolder *sh = test_LLVM_structtype(L, idx);
if (sh)
return sh->type;
if (sh) return sh->type;
FunctionTypeHolder *fh = test_LLVM_functiontype(L, idx);
if (fh)
return fh->type;
if (fh) return fh->type;
luaL_argerror(L, idx, "unrecognized type");
return nullptr;
}
@ -1052,10 +1030,8 @@ static int func_alloca(lua_State *L) {
llvm::Type *ty = get_type(L, 2);
llvm::Value *arraysize = nullptr;
const char *name = nullptr;
if (lua_gettop(L) >= 3)
name = luaL_checkstring(L, 3);
if (lua_gettop(L) >= 4)
arraysize = get_value(L, 4);
if (lua_gettop(L) >= 3) name = luaL_checkstring(L, 3);
if (lua_gettop(L) >= 4) arraysize = get_value(L, 4);
llvm::BasicBlock *block = func->getBasicBlockList().begin();
luaL_argcheck(L, block != nullptr, 1, "No basic block in function");
llvm::IRBuilder<> builder(block, block->begin());
@ -1086,9 +1062,7 @@ static int irbuilder_phi(lua_State *L) {
llvm::Type *ty = get_type(L, 2);
unsigned int num_values = (unsigned int)luaL_checkinteger(L, 3);
const char *name = nullptr;
if (lua_gettop(L) >= 4) {
name = luaL_checkstring(L, 4);
}
if (lua_gettop(L) >= 4) { name = luaL_checkstring(L, 4); }
llvm::PHINode *phi = builder->builder->CreatePHI(ty, num_values, name);
alloc_LLVM_phinode(L, phi);
return 1;
@ -1104,51 +1078,51 @@ static int phi_addincoming(lua_State *L) {
}
/* ops that take a value and value array as arguments */
#define irbuilder_vva(op) \
static int irbuilder_##op(lua_State *L) { \
IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \
llvm::Value *c = get_value(L, 2); \
luaL_argcheck(L, lua_istable(L, 3), 3, "table expected"); \
int len = luaL_len(L, 3); \
std::vector<llvm::Value *> elements; \
for (int i = 1; i <= len; i++) { \
lua_rawgeti(L, 3, i); \
llvm::Value *v = get_value(L, -1); \
elements.push_back(v); \
lua_pop(L, 1); \
} \
llvm::Value *result = builder->builder->Create##op(c, elements); \
alloc_LLVM_value(L, result); \
return 1; \
#define irbuilder_vva(op) \
static int irbuilder_##op(lua_State *L) { \
IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \
llvm::Value *c = get_value(L, 2); \
luaL_argcheck(L, lua_istable(L, 3), 3, "table expected"); \
int len = luaL_len(L, 3); \
std::vector<llvm::Value *> elements; \
for (int i = 1; i <= len; i++) { \
lua_rawgeti(L, 3, i); \
llvm::Value *v = get_value(L, -1); \
elements.push_back(v); \
lua_pop(L, 1); \
} \
llvm::Value *result = builder->builder->Create##op(c, elements); \
alloc_LLVM_value(L, result); \
return 1; \
}
#define irbuilder_binop(op) \
static int irbuilder_##op(lua_State *L) { \
IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \
llvm::Value *lhs = get_value(L, 2); \
llvm::Value *rhs = get_value(L, 3); \
llvm::Value *result = builder->builder->Create##op(lhs, rhs); \
alloc_LLVM_value(L, result); \
return 1; \
#define irbuilder_binop(op) \
static int irbuilder_##op(lua_State *L) { \
IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \
llvm::Value *lhs = get_value(L, 2); \
llvm::Value *rhs = get_value(L, 3); \
llvm::Value *result = builder->builder->Create##op(lhs, rhs); \
alloc_LLVM_value(L, result); \
return 1; \
}
#define irbuilder_unop(op) \
static int irbuilder_##op(lua_State *L) { \
IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \
llvm::Value *lhs = get_value(L, 2); \
llvm::Value *result = builder->builder->Create##op(lhs); \
alloc_LLVM_value(L, result); \
return 1; \
#define irbuilder_unop(op) \
static int irbuilder_##op(lua_State *L) { \
IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \
llvm::Value *lhs = get_value(L, 2); \
llvm::Value *result = builder->builder->Create##op(lhs); \
alloc_LLVM_value(L, result); \
return 1; \
}
#define irbuilder_convert(op) \
static int irbuilder_##op(lua_State *L) { \
IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \
llvm::Value *lhs = get_value(L, 2); \
llvm::Type *rhs = get_type(L, 3); \
llvm::Value *result = builder->builder->Create##op(lhs, rhs); \
alloc_LLVM_value(L, result); \
return 1; \
#define irbuilder_convert(op) \
static int irbuilder_##op(lua_State *L) { \
IRBuilderHolder *builder = check_LLVM_irbuilder(L, 1); \
llvm::Value *lhs = get_value(L, 2); \
llvm::Type *rhs = get_type(L, 3); \
llvm::Value *result = builder->builder->Create##op(lhs, rhs); \
alloc_LLVM_value(L, result); \
return 1; \
}
irbuilder_vva(InBoundsGEP);

Loading…
Cancel
Save