From a8ee5a60e1e8c5718d1178be0748f617159544d9 Mon Sep 17 00:00:00 2001 From: Dibyendu Majumdar Date: Mon, 25 May 2020 10:44:51 +0100 Subject: [PATCH] issue #99 LLVM JIT updates to support RaviArray breakout from Table structure --- include/ltable.h | 5 +-- include/ravi_llvmcodegen.h | 8 +++- src/ltable.c | 20 +-------- src/ravi_llvmcodegen.cpp | 37 ++++++++++++----- src/ravi_llvmtable.cpp | 24 +++++------ src/ravi_llvmtypes.cpp | 84 +++++++++++++++++++++----------------- 6 files changed, 94 insertions(+), 84 deletions(-) diff --git a/include/ltable.h b/include/ltable.h index 4ced943..4552881 100644 --- a/include/ltable.h +++ b/include/ltable.h @@ -137,7 +137,7 @@ LUAI_FUNC RaviArray *raviH_new_number_array(lua_State *L, unsigned int len, /* Returns the array length - note that this function will * ignore any elements outside of the Ravi Array structure */ -LUAI_FUNC int raviH_getn(RaviArray *t); +#define raviH_getn(t) ((t)->len - 1) /* Type specific array set operation */ LUAI_FUNC void raviH_set_int(lua_State *L, RaviArray *t, lua_Unsigned key, @@ -161,9 +161,6 @@ LUAI_FUNC void raviH_set_float(lua_State *L, RaviArray *t, lua_Unsigned key, LUAI_FUNC RaviArray *raviH_new_slice(lua_State *L, TValue *parent, unsigned int start, unsigned int len); -/* Obtain parent array of the slice */ -LUAI_FUNC const RaviArray *raviH_slice_parent(lua_State *L, TValue *slice); - /* Type specific array get operation */ #define raviH_get_int_inline(L, t, key, v) \ { \ diff --git a/include/ravi_llvmcodegen.h b/include/ravi_llvmcodegen.h index ba204fd..6ea5fe3 100644 --- a/include/ravi_llvmcodegen.h +++ b/include/ravi_llvmcodegen.h @@ -179,6 +179,8 @@ struct LuaLLVMTypes { llvm::StructType *UdataT; llvm::StructType *RaviArrayT; + llvm::PointerType* pRaviArrayT; + llvm::PointerType* ppRaviArrayT; llvm::StructType *TableT; llvm::PointerType *pTableT; llvm::PointerType *ppTableT; @@ -1036,6 +1038,9 @@ class RaviCodeGenerator { // emit code to load the table value from register llvm::Instruction *emit_load_reg_h(RaviFunctionDef *def, llvm::Value *ra); + // emit code to load the RaviArray value from register + llvm::Instruction* emit_load_reg_arr(RaviFunctionDef* def, llvm::Value* ra); + // 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); @@ -1097,7 +1102,8 @@ 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); + // Disabled as it is now broken + //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); diff --git a/src/ltable.c b/src/ltable.c index 08b116b..85cb00c 100644 --- a/src/ltable.c +++ b/src/ltable.c @@ -767,11 +767,6 @@ int luaH_getn (Table *t) { else return unbound_search(t, j); } -/* RAVI array specialization */ -int raviH_getn(RaviArray *t) { - return t->len - 1; -} - /* resize array and initialize new elements if requested */ static int ravi_resize_array(lua_State *L, RaviArray *t, unsigned int new_size, int initialize) { if (t->flags & RAVI_ARRAY_FIXEDSIZE || t->flags & RAVI_ARRAY_SLICE) { @@ -920,7 +915,8 @@ RaviArray *raviH_new_slice(lua_State *L, TValue *parent, unsigned int start, L, "cannot create slice from dynamic integer[] or number[] array"); /* Create the slice table */ RaviArray *t = raviH_new(L, (orig->flags & RAVI_ARRAY_ISFLOAT) ? RAVI_TARRAYFLT : RAVI_TARRAYINT, 1); - /* Add a reference to the parent table */ + /* Add a reference to the parent table. From GC perspective the slice is a white object + so we do not need a write barrier */ t->parent = orig; /* Initialize */ if (orig->flags & RAVI_ARRAY_ISFLOAT) { @@ -936,18 +932,6 @@ RaviArray *raviH_new_slice(lua_State *L, TValue *parent, unsigned int start, return t; } -/* Obtain parent array of the slice */ -const RaviArray *raviH_slice_parent(lua_State *L, TValue *slice) { - if (!ttisarray(slice)) - luaG_runerror(L, "slice of integer[] or number[] expected"); - RaviArray *orig = arrvalue(slice); - if ((orig->flags & RAVI_ARRAY_SLICE) == 0) - luaG_runerror(L, "slice of integer[] or number[] expected"); - /* Get reference to the parent table */ - //TODO do a liveness check here - return orig->parent; -} - #if defined(LUA_DEBUG) Node *luaH_mainposition (const Table *t, const TValue *key) { diff --git a/src/ravi_llvmcodegen.cpp b/src/ravi_llvmcodegen.cpp index eae7d02..e8e35b6 100644 --- a/src/ravi_llvmcodegen.cpp +++ b/src/ravi_llvmcodegen.cpp @@ -345,6 +345,15 @@ llvm::Instruction *RaviCodeGenerator::emit_load_reg_h(RaviFunctionDef *def, return h; } +// emit code to load the RaviArray value from register (TValue) +llvm::Instruction* RaviCodeGenerator::emit_load_reg_arr(RaviFunctionDef* def, + llvm::Value* rb) { + llvm::Value* rb_h = def->builder->CreateBitCast(rb, def->types->ppRaviArrayT); + llvm::Instruction* h = def->builder->CreateLoad(rb_h); + h->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_hT); + return h; +} + // Gets the size of the hash table // This is the sizenode() macro in lobject.h llvm::Value *RaviCodeGenerator::emit_table_get_hashsize(RaviFunctionDef *def, @@ -370,7 +379,7 @@ llvm::Value *RaviCodeGenerator::emit_table_get_hashstr(RaviFunctionDef *def, TString *key) { #if RAVI_USE_NEWHASH unsigned int hash = key->hash; - llvm::Value *hmask_ptr = emit_gep(def, "hmask", table, 0, 12); + llvm::Value *hmask_ptr = emit_gep(def, "hmask", table, 0, 11); llvm::Instruction *hmask = def->builder->CreateLoad(hmask_ptr); hmask->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Table_hmask); llvm::Value *offset = def->builder->CreateAnd( @@ -462,9 +471,10 @@ llvm::Instruction *RaviCodeGenerator::emit_load_reg_s(RaviFunctionDef *def, return s; } +/* Loads the data pointer as lua_Number[] from a RaviArray object */ llvm::Instruction *RaviCodeGenerator::emit_load_reg_h_floatarray( RaviFunctionDef *def, llvm::Instruction *h) { - llvm::Value *data_ptr = emit_gep(def, "data_ptr", h, 0, 11, 0); + llvm::Value *data_ptr = emit_gep(def, "data_ptr", h, 0, 7); llvm::Value *darray_ptr = def->builder->CreateBitCast(data_ptr, def->types->pplua_NumberT); llvm::Instruction *darray = def->builder->CreateLoad(darray_ptr); @@ -473,9 +483,10 @@ llvm::Instruction *RaviCodeGenerator::emit_load_reg_h_floatarray( return darray; } +/* Loads the data pointer as lua_Integer[] from a RaviArray object */ llvm::Instruction *RaviCodeGenerator::emit_load_reg_h_intarray( RaviFunctionDef *def, llvm::Instruction *h) { - llvm::Value *data_ptr = emit_gep(def, "data_ptr", h, 0, 11, 0); + llvm::Value *data_ptr = emit_gep(def, "data_ptr", h, 0, 7); llvm::Value *darray_ptr = def->builder->CreateBitCast(data_ptr, def->types->pplua_IntegerT); llvm::Instruction *darray = def->builder->CreateLoad(darray_ptr); @@ -580,17 +591,21 @@ llvm::Value *RaviCodeGenerator::emit_is_not_value_of_type_class( llvm::ConstantInt::get(def->types->lua_LuaTypeT, lua_type), varname); } -llvm::Instruction *RaviCodeGenerator::emit_load_ravi_arraytype( - RaviFunctionDef *def, llvm::Value *value) { - llvm::Value *tt_ptr = emit_gep(def, "raviarray.type_ptr", value, 0, 11, 3); - llvm::Instruction *tt = def->builder->CreateLoad(tt_ptr, "raviarray.type"); - tt->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_RaviArray_typeT); - return tt; -} +/* This loads the RaviArray type value from the tt field maintained in the + GC part. However this tt is 8-bit value and needs to be converted to + the 16-bit value used in TValue objects */ +//llvm::Instruction *RaviCodeGenerator::emit_load_ravi_arraytype( +// RaviFunctionDef *def, llvm::Value *value) { +// llvm::Value *tt_ptr = emit_gep(def, "raviarray.type_ptr", value, 0, 1); +// llvm::Instruction *tt = def->builder->CreateLoad(tt_ptr, "raviarray.type"); +// // FIXME promote to 16 bit and set collectible bit +// tt->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_RaviArray_typeT); +// return tt; +//} llvm::Instruction *RaviCodeGenerator::emit_load_ravi_arraylength( RaviFunctionDef *def, llvm::Value *value) { - llvm::Value *tt_ptr = emit_gep(def, "raviarray.len_ptr", value, 0, 11, 1); + llvm::Value *tt_ptr = emit_gep(def, "raviarray.len_ptr", value, 0, 4); llvm::Instruction *tt = def->builder->CreateLoad(tt_ptr, "raviarray.len"); tt->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_RaviArray_lenT); return tt; diff --git a/src/ravi_llvmtable.cpp b/src/ravi_llvmtable.cpp index 67b453c..87625ed 100644 --- a/src/ravi_llvmtable.cpp +++ b/src/ravi_llvmtable.cpp @@ -477,8 +477,8 @@ void RaviCodeGenerator::emit_FARRAY_GET(RaviFunctionDef *def, int A, int B, int pc) { //#define raviH_get_float_inline(L, t, key, v) //{ unsigned ukey = (unsigned)((key)); - // lua_Number *data = (lua_Number *)t->ravi_array.data; - // if (ukey < t->ravi_array.len) { + // lua_Number *data = (lua_Number *)t->data; + // if (ukey < t->len) { // setfltvalue(v, data[ukey]); // }else // luaG_runerror(L, "array out of bounds"); @@ -496,7 +496,7 @@ void RaviCodeGenerator::emit_FARRAY_GET(RaviFunctionDef *def, int A, int B, llvm::Value *rb = emit_gep_register(def, B); llvm::Value *rc = emit_gep_register_or_constant(def, C); llvm::Instruction *key = emit_load_reg_i(def, rc); - llvm::Instruction *t = emit_load_reg_h(def, rb); + llvm::Instruction *t = emit_load_reg_arr(def, rb); llvm::Instruction *data = emit_load_reg_h_floatarray(def, t); llvm::BasicBlock *then_block = nullptr; llvm::BasicBlock *else_block = nullptr; @@ -541,8 +541,8 @@ void RaviCodeGenerator::emit_IARRAY_GET(RaviFunctionDef *def, int A, int B, int pc) { //#define raviH_get_int_inline(L, t, key, v) //{ unsigned ukey = (unsigned)((key)); - // lua_Integer *data = (lua_Integer *)t->ravi_array.data; - // if (ukey < t->ravi_array.len) { + // lua_Integer *data = (lua_Integer *)t->data; + // if (ukey < t->len) { // setivalue(v, data[ukey]); // } else // luaG_runerror(L, "array out of bounds"); @@ -560,7 +560,7 @@ void RaviCodeGenerator::emit_IARRAY_GET(RaviFunctionDef *def, int A, int B, llvm::Value *rb = emit_gep_register(def, B); llvm::Value *rc = emit_gep_register_or_constant(def, C); llvm::Instruction *key = emit_load_reg_i(def, rc); - llvm::Instruction *t = emit_load_reg_h(def, rb); + llvm::Instruction *t = emit_load_reg_arr(def, rb); llvm::Instruction *data = emit_load_reg_h_intarray(def, t); llvm::BasicBlock *then_block = nullptr; @@ -605,8 +605,8 @@ void RaviCodeGenerator::emit_IARRAY_SET(RaviFunctionDef *def, int A, int B, int C, bool known_int, int pc) { //#define raviH_set_int_inline(L, t, key, value) //{ unsigned ukey = (unsigned)((key)); - // lua_Integer *data = (lua_Integer *)t->ravi_array.data; - // if (ukey < t->ravi_array.len) { + // lua_Integer *data = (lua_Integer *)t->data; + // if (ukey < t->len) { // data[ukey] = value; // } else // raviH_set_int(L, t, ukey, value); @@ -628,7 +628,7 @@ void RaviCodeGenerator::emit_IARRAY_SET(RaviFunctionDef *def, int A, int B, llvm::Instruction *key = emit_load_reg_i(def, rb); llvm::Instruction *value = known_int ? emit_load_reg_i(def, rc) : emit_tointeger(def, rc); - llvm::Instruction *t = emit_load_reg_h(def, ra); + llvm::Instruction *t = emit_load_reg_arr(def, ra); llvm::Instruction *data = emit_load_reg_h_intarray(def, t); llvm::Instruction *len = emit_load_ravi_arraylength(def, t); llvm::Value *ulen = @@ -665,8 +665,8 @@ void RaviCodeGenerator::emit_FARRAY_SET(RaviFunctionDef *def, int A, int B, int C, bool known_float, int pc) { //#define raviH_set_float_inline(L, t, key, value) //{ unsigned ukey = (unsigned)((key)); - // lua_Number *data = (lua_Number *)t->ravi_array.data; - // if (ukey < t->ravi_array.len) { + // lua_Number *data = (lua_Number *)t->data; + // if (ukey < t->len) { // data[ukey] = value; // } else // raviH_set_float(L, t, ukey, value); @@ -692,7 +692,7 @@ void RaviCodeGenerator::emit_FARRAY_SET(RaviFunctionDef *def, int A, int B, llvm::Instruction *key = emit_load_reg_i(def, rb); llvm::Instruction *value = known_float ? emit_load_reg_n(def, rc) : emit_tofloat(def, rc); - llvm::Instruction *t = emit_load_reg_h(def, ra); + llvm::Instruction *t = emit_load_reg_arr(def, ra); llvm::Instruction *data = emit_load_reg_h_floatarray(def, t); llvm::Instruction *len = emit_load_ravi_arraylength(def, t); llvm::Value *ulen = diff --git a/src/ravi_llvmtypes.cpp b/src/ravi_llvmtypes.cpp index e6ffc8b..b0f9797 100644 --- a/src/ravi_llvmtypes.cpp +++ b/src/ravi_llvmtypes.cpp @@ -446,22 +446,32 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) { NodeT->setBody(elements); pNodeT = llvm::PointerType::get(NodeT, 0); - // typedef struct RaviArray { - // char *data; - // unsigned int len; /* RAVI len specialization */ - // unsigned int size; /* amount of memory allocated */ - // lu_byte array_type; /* RAVI specialization */ - // lu_byte array_modifier; /* Flags that affect how the array is handled */ - //} RaviArray; - + //struct RaviArray { + // CommonHeader; + // lu_byte flags; + // unsigned int len; /* array length, holds real length which is 1+Lua length */ + // unsigned int size; /* size of data, in arrays (not slices) if == RAVI_ARRAY_MAX_INLINE then it means we are using inline storage */ + // union { + // lua_Number numarray[RAVI_ARRAY_MAX_INLINE]; + // lua_Integer intarray[RAVI_ARRAY_MAX_INLINE]; + // struct RaviArray* parent; /* Only set if this is a slice, parent must be a slice or a fixed length array */ + // }; + // char* data; /* Pointer to data. In case of slices points in parent->data. In case of arrays this may point to heap or internal data */ + // struct Table* metatable; + //} RaviArrayT = llvm::StructType::create(context, "struct.RaviArray"); elements.clear(); - elements.push_back(C_pcharT); - elements.push_back(C_intT); - elements.push_back(C_intT); - elements.push_back(lu_byteT); - elements.push_back(lu_byteT); + addCommonGCHeader(elements); + elements.push_back(lu_byteT); /* flags */ + elements.push_back(C_intT); /* len - 4 */ + elements.push_back(C_intT); /* size */ + elements.push_back(llvm::ArrayType::get(lua_NumberT, RAVI_ARRAY_MAX_INLINE)); /* numarray: Assumption: lua_Number and lua_Integer have same size */ + elements.push_back(C_pcharT); /* data - 7 */ + elements.push_back(pTableT); /* metatable*/ RaviArrayT->setBody(elements); + pRaviArrayT = llvm::PointerType::get(RaviArrayT, 0); + ppRaviArrayT = llvm::PointerType::get(pRaviArrayT, 0); + // typedef struct Table { // CommonHeader; @@ -473,7 +483,6 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) { // Node *lastfree; /* any free position is before this position */ // struct Table *metatable; // GCObject *gclist; - // RaviArray ravi_array; // unsigned int hmask; /* Hash part mask (size of hash part - 1) */ //} Table; elements.clear(); @@ -486,7 +495,6 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) { elements.push_back(pNodeT); /* lastfree */ elements.push_back(pTableT); /* metatable */ elements.push_back(pGCObjectT); /* gclist */ - elements.push_back(RaviArrayT); /* RaviArray */ #if RAVI_USE_NEWHASH elements.push_back(C_intT); /* hmask */ #endif @@ -999,21 +1007,21 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) { elements.push_back(pTStringT); luaH_getstrT = llvm::FunctionType::get(pTValueT, elements, false); - // void raviH_set_int(lua_State *L, Table *t, lua_Unsigned key, lua_Integer + // void raviH_set_int(lua_State *L, RaviArray *t, lua_Unsigned key, lua_Integer // value); elements.clear(); elements.push_back(plua_StateT); - elements.push_back(pTableT); + elements.push_back(pRaviArrayT); elements.push_back(lua_UnsignedT); elements.push_back(lua_IntegerT); raviH_set_intT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false); - // void raviH_set_float(lua_State *L, Table *t, lua_Unsigned key, lua_Number + // void raviH_set_float(lua_State *L, RaviArray *t, lua_Unsigned key, lua_Number // value); elements.clear(); elements.push_back(plua_StateT); - elements.push_back(pTableT); + elements.push_back(pRaviArrayT); elements.push_back(lua_UnsignedT); elements.push_back(lua_NumberT); raviH_set_floatT = @@ -1295,16 +1303,17 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) { mdbuilder.createTBAAStructTagNode(tbaa_UpValT, tbaa_pointerT, 0); - // RaviArray + // !{!"RaviArray", !5, i64 0, !6, i64 4, !6, i64 5, !6, i64 6, !11, i64 8, !11, i64 12, !6, i64 16, !5, i64 40, !5, i64 44} nodes.clear(); - nodes.push_back( - std::pair(tbaa_pointerT, 0)); /* data */ - nodes.push_back(std::pair(tbaa_intT, 4)); /* len */ - nodes.push_back(std::pair(tbaa_intT, 8)); /* size */ - nodes.push_back( - std::pair(tbaa_charT, 12)); /* type */ - nodes.push_back( - std::pair(tbaa_charT, 13)); /* modifiers */ + nodes.push_back(std::pair(tbaa_pointerT, 0)); /* next */ + nodes.push_back(std::pair(tbaa_charT, 4)); /* tt */ + nodes.push_back(std::pair(tbaa_charT, 5)); /* marked */ + nodes.push_back(std::pair(tbaa_charT, 6)); /* flags */ + nodes.push_back(std::pair(tbaa_intT, 8)); /* len */ + nodes.push_back(std::pair(tbaa_intT, 12)); /* size */ + nodes.push_back(std::pair(tbaa_charT, 16)); /* numarray */ + nodes.push_back(std::pair(tbaa_pointerT, 40)); /* data */ + nodes.push_back(std::pair(tbaa_pointerT, 44)); /* metatable */ tbaa_RaviArrayT = mdbuilder.createTBAAStructTypeNode("RaviArray", nodes); // Table TBAA struct type @@ -1330,11 +1339,9 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) { std::pair(tbaa_pointerT, 24)); /* metatable */ nodes.push_back( std::pair(tbaa_pointerT, 28)); /* gclist */ - nodes.push_back(std::pair(tbaa_RaviArrayT, - 32)); /* ravi_array */ #if RAVI_USE_NEWHASH nodes.push_back( - std::pair(tbaa_intT, 48)); /* hmask */ + std::pair(tbaa_intT, 32)); /* hmask */ #endif tbaa_TableT = mdbuilder.createTBAAStructTypeNode("Table", nodes); @@ -1350,16 +1357,17 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) { mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 16); tbaa_Table_metatable = mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 24); - tbaa_RaviArray_dataT = - mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 32); - tbaa_RaviArray_lenT = - mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_intT, 36); - tbaa_RaviArray_typeT = - mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_charT, 44); #if RAVI_USE_NEWHASH tbaa_Table_hmask = - mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_intT, 48); + mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_intT, 32); #endif + + tbaa_RaviArray_dataT = + mdbuilder.createTBAAStructTagNode(tbaa_RaviArrayT, tbaa_pointerT, 40); + tbaa_RaviArray_lenT = + mdbuilder.createTBAAStructTagNode(tbaa_RaviArrayT, tbaa_intT, 8); + tbaa_RaviArray_typeT = + mdbuilder.createTBAAStructTagNode(tbaa_RaviArrayT, tbaa_charT, 4); } void LuaLLVMTypes::dump() {