doc updates

pull/81/head
Dibyendu Majumdar 9 years ago
parent 852cfee3da
commit 70507a4ef6

@ -695,7 +695,7 @@ public:
const char *varname = "value.not.typeof");
// emit code for (LClosure *)ci->func->value_.gc
llvm::Value *emit_gep_ci_func_value_gc_asLClosure(RaviFunctionDef *def);
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, int arg2);

@ -36,6 +36,9 @@ RaviCodeGenerator::RaviCodeGenerator(RaviJITStateImpl *jitState)
}
const char *RaviCodeGenerator::unique_function_name() {
// Create unique name for the compiled function
// Lua functions are nameless so a compiled function has no name
// as far as Lua is concerned
snprintf(temp_, sizeof temp_, "ravif%d", id_++);
return temp_;
}
@ -115,42 +118,62 @@ llvm::Value *RaviCodeGenerator::emit_gep(RaviFunctionDef *def, const char *name,
}
llvm::Value *RaviCodeGenerator::emit_gep(RaviFunctionDef *def, const char *name,
llvm::Value *ptr, llvm::Value *offset,
int arg1, int arg2) {
llvm::SmallVector<llvm::Value *, 3> values;
llvm::Value *ptr, llvm::Value *offset,
int arg1) {
llvm::SmallVector<llvm::Value *, 2> values;
values.push_back(offset);
values.push_back(def->types->kInt[arg1]);
values.push_back(def->types->kInt[arg2]);
return def->builder->CreateInBoundsGEP(ptr, values, name);
}
llvm::Value *RaviCodeGenerator::emit_gep(RaviFunctionDef *def, const char *name,
llvm::Value *ptr, llvm::Value *offset,
int arg1) {
llvm::SmallVector<llvm::Value *, 2> values;
int arg1, int arg2) {
llvm::SmallVector<llvm::Value *, 3> values;
values.push_back(offset);
values.push_back(def->types->kInt[arg1]);
values.push_back(def->types->kInt[arg2]);
return def->builder->CreateInBoundsGEP(ptr, values, name);
}
llvm::Value *
llvm::Value *RaviCodeGenerator::emit_array_get(RaviFunctionDef *def,
llvm::Value *ptr, int offset) {
// emit code for &ptr[offset]
return def->builder->CreateInBoundsGEP(
ptr, llvm::ConstantInt::get(def->types->C_intT, offset));
}
llvm::Instruction *
RaviCodeGenerator::emit_gep_ci_func_value_gc_asLClosure(RaviFunctionDef *def) {
// emit code for (LClosure *)ci->func->value_.gc
// fortunately as func is at the beginning of the ci
// structure we can just cast ci to LClosure*
// emit code for
// LClosure *cl = clLvalue(ci->func);
// clLvalue() is a macros that expands to (LClosure *)ci->func->value_.gc
// via a complex series of macros and unions
// fortunately as func is at the beginning of the CallInfo
// structure we can just cast ci to LClosure***
// This insight is based on code generated by Clang
llvm::Value *pppLuaClosure =
def->builder->CreateBitCast(def->ci_val, def->types->pppLClosureT);
// Load pointer to LClosure**
llvm::Instruction *ppLuaClosure = def->builder->CreateLoad(pppLuaClosure);
ppLuaClosure->setMetadata(llvm::LLVMContext::MD_tbaa,
def->types->tbaa_CallInfo_funcT);
return ppLuaClosure;
// Load pointer to LClosure*
llvm::Instruction *cl_ptr = def->builder->CreateLoad(ppLuaClosure);
cl_ptr->setMetadata(llvm::LLVMContext::MD_tbaa,
def->types->tbaa_CallInfo_func_LClosureT);
return cl_ptr;
}
// Retrieve the proto->sizep
// sizep is a count of the number of closures defined
// in the function
llvm::Instruction *
RaviCodeGenerator::emit_load_proto_sizep(RaviFunctionDef *def) {
llvm::Value *psize_ptr = emit_gep(def, "sizep", def->proto_ptr, 0, 10);
// Load sizep
llvm::Instruction *psize = def->builder->CreateLoad(psize_ptr);
psize->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Proto_sizepT);
return psize;
@ -173,7 +196,7 @@ void RaviCodeGenerator::emit_update_savedpc(RaviFunctionDef *def, int pc) {
llvm::Instruction *code_ptr = def->builder->CreateLoad(proto_code_ptr);
code_ptr->setMetadata(llvm::LLVMContext::MD_tbaa,
def->types->tbaa_Proto_codeT);
// Need to set savedpc to the next instruction rather than current as that is
// Need to set savedpc to the next instruction (pc+1) rather than current as that is
// what the VM does in interpreted mode
llvm::Value *code_offset_ptr = emit_array_get(def, code_ptr, pc + 1);
llvm::Value *savedpc_ptr = emit_gep(def, "savedpc", def->ci_val, 0, 4, 1);
@ -183,13 +206,10 @@ void RaviCodeGenerator::emit_update_savedpc(RaviFunctionDef *def, int pc) {
def->types->tbaa_CallInfo_savedpcT);
}
llvm::Value *RaviCodeGenerator::emit_array_get(RaviFunctionDef *def,
llvm::Value *ptr, int offset) {
// emit code for &ptr[offset]
return def->builder->CreateInBoundsGEP(
ptr, llvm::ConstantInt::get(def->types->C_intT, offset));
}
// Generate code to reload the function's stack 'base'
// pointer - the VM needs to do this after any bytecode that
// may invoke a Lua function and thereby resize the stack; which
// would invalidate the current 'base' pointer
void RaviCodeGenerator::emit_load_base(RaviFunctionDef *def) {
// Load pointer to base
llvm::Instruction *base_ptr = def->builder->CreateLoad(def->Ci_base);
@ -211,6 +231,7 @@ llvm::Value *RaviCodeGenerator::emit_gep_register(RaviFunctionDef *def, int A) {
return dest;
}
// Emit code to obtain address of a constant
llvm::Value *RaviCodeGenerator::emit_gep_constant(RaviFunctionDef *def,
int Bx) {
// Load pointer to k
@ -226,7 +247,8 @@ llvm::Value *RaviCodeGenerator::emit_gep_constant(RaviFunctionDef *def,
return src;
}
// Loads the value at register B - if the value is an integer constant
// Loads the value at register or constant at location B -
// if the value is an integer constant
// then returns a constant literal
llvm::Value *
RaviCodeGenerator::emit_load_register_or_constant_i(RaviFunctionDef *def,
@ -1186,7 +1208,7 @@ void RaviCodeGenerator::link_block(RaviFunctionDef *def, int pc) {
idb->addDestination(def->jmp_targets[pc].jmp3);
idb->addDestination(def->jmp_targets[pc].jmp4);
// As we have terminated the block the code below will not
// add the branch insruction, but we still need to create the new
// add the branch instruction, but we still need to create the new
// block which is handled below.
}
// If the current bytecode offset pc is on a jump target
@ -1247,8 +1269,6 @@ RaviCodeGenerator::emit_gep_upval_value(RaviFunctionDef *def,
void RaviCodeGenerator::compile(lua_State *L, Proto *p,
ravi_compile_options_t *options) {
TValue *k = p->k;
bool doDump = options ? options->dump_level != 0 : 0;
bool doVerify = options ? options->verification_level != 0 : 0;
bool omitArrayGetRangeCheck =
@ -1260,12 +1280,21 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p,
llvm::LLVMContext &context = jitState_->context();
llvm::IRBuilder<> builder(context);
std::unique_ptr<RaviFunctionDef> definition =
std::unique_ptr<RaviFunctionDef>(new RaviFunctionDef());
RaviFunctionDef *def = definition.get();
// RaviFunctionDef definition = {0};
// RaviFunctionDef *def = &definition;
// std::unique_ptr<RaviFunctionDef> definition =
// std::unique_ptr<RaviFunctionDef>(new RaviFunctionDef());
// RaviFunctionDef *def = definition.get();
RaviFunctionDef definition = {0};
RaviFunctionDef *def = &definition;
// The Lua GC doesn't know about memory allocated by the JIT
// compiler; this means that if lots of functions are being compiled
// such as in the test cases, then memory usage can grow very large
// as the GC is blissfully unaware of the actual memory in use
// To workaround this issue we provide an option that can be used to
// force a GC after every n compilations where n is supplied
// by the gcstep parameter; this is not ideal as it kills performance
// but appears to work for the test cases
// A better solution is needed
int gcstep = this->jitState_->get_gcstep();
if (gcstep > 0 && (id_ % gcstep) == 0) {
lua_unlock(L);
@ -1273,12 +1302,15 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p,
lua_lock(L);
}
// printf("compiling function\n");
auto f = create_function(builder, def);
if (!f) {
p->ravi_jit.jit_status = RAVI_JIT_CANT_COMPILE; // can't compile
return;
}
// The functions constants
TValue *k = p->k;
// Add extern declarations for Lua functions we need to call
emit_extern_declarations(def);
def->p = p;
@ -1290,29 +1322,24 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p,
def->L_ci = emit_gep(def, "L_ci", def->L, 0, 6);
// Load L->ci
// This is the function's activation record / stack frame
def->ci_val = builder.CreateLoad(def->L_ci);
def->ci_val->setMetadata(llvm::LLVMContext::MD_tbaa,
def->types->tbaa_CallInfoT);
// Get pointer to base
// Get pointer to function's 'base' stack location
// 'base' is the address relative to which all the
// function registers are located
def->Ci_base = emit_gep(def, "base", def->ci_val, 0, 4, 0);
// We need to get hold of the constants table
// which is located in ci->func->value_.gc
// and is a value of type LClosure*
// fortunately as func is at the beginning of the ci
// structure we can just cast ci to LClosure*
llvm::Value *L_cl = emit_gep_ci_func_value_gc_asLClosure(def);
// Load pointer to LClosure
llvm::Instruction *cl_ptr = builder.CreateLoad(L_cl);
cl_ptr->setMetadata(llvm::LLVMContext::MD_tbaa,
def->types->tbaa_CallInfo_func_LClosureT);
def->p_LClosure = cl_ptr;
// which is located in the function definition
// This is the line in lvm.c that says:
// LClosure *cl = clLvalue(ci->func)
def->p_LClosure = emit_gep_ci_func_value_gc_asLClosure(def);
// Get pointer to the Proto* which is cl->p
def->proto = emit_gep(def, "Proto", cl_ptr, 0, 5);
def->proto = emit_gep(def, "Proto", def->p_LClosure, 0, 5);
// Load pointer to proto
def->proto_ptr = builder.CreateLoad(def->proto);

Loading…
Cancel
Save