From f04c5febd64fce8ef55a8c4c43c2f39924d32f67 Mon Sep 17 00:00:00 2001 From: Dibyendu Majumdar Date: Mon, 9 Nov 2015 00:18:31 +0000 Subject: [PATCH] issue #60 JIT compile GETTABLE_S --- clang-output/inline_getstr.c | 38 +++++++++ clang-output/inline_getstr.ll | 75 +++++++++++++++++ clang-output/runclang.bat | 3 +- include/lopcodes.h | 8 +- include/ravi_llvmcodegen.h | 43 ++++++++-- ravi-tests/ravi_tests1.ravi | 22 +++-- src/lapi.c | 5 ++ src/lcode.c | 12 ++- src/ldebug.c | 4 +- src/ldump.c | 5 ++ src/lfunc.c | 5 ++ src/lopcodes.c | 26 ++++-- src/lparser.c | 10 ++- src/lundump.c | 4 + src/lvm.c | 13 ++- src/ravi_llvmcodegen.cpp | 146 ++++++++++++++++++++++++++++++---- src/ravi_llvmtable.cpp | 138 ++++++++++++++++++++++++++++++-- src/ravi_llvmtypes.cpp | 52 +++++++++--- 18 files changed, 537 insertions(+), 72 deletions(-) create mode 100644 clang-output/inline_getstr.c create mode 100644 clang-output/inline_getstr.ll diff --git a/clang-output/inline_getstr.c b/clang-output/inline_getstr.c new file mode 100644 index 0000000..3eac302 --- /dev/null +++ b/clang-output/inline_getstr.c @@ -0,0 +1,38 @@ +#include "lua_hdr.h" + +#define LUA_TSTRING 4 +#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) + +#define checktag(o,t) (rttype(o) == (t)) +#define ctb(t) ((t) | BIT_ISCOLLECTABLE) + +#define cast(t, exp) ((t)(exp)) +#define lmod(s,size) \ + (cast(int, (s) & ((size)-1))) + + +#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) +#define gco2ts(o) cast(struct TString *, (o)) +#define val_(o) ((o)->value_) +#define tsvalue(o) gco2ts(val_(o).gc) + +#define gnode(t,i) (&(t)->node[i]) +#define gval(n) (&(n)->i_val) +#define gkey(n) cast(const struct TValue*, (&(n)->i_key.tvk)) + +#define twoto(x) (1<<(x)) +#define sizenode(t) (twoto((t)->lsizenode)) + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) +#define hashstr(t,str) hashpow2(t, (str)->hash) +#define eqshrstr(a,b) ((a) == (b)) + +extern const struct TValue *luaH_getstr (struct Table *t, struct TString *key); + +const struct TValue *ravi_getstr (struct Table *t, struct TString *key) { + struct Node *n = hashstr(t, key); + const struct TValue *k = gkey(n); + if (ttisshrstring(k) && eqshrstr(tsvalue(k), key)) + return gval(n); /* that's it */ + return luaH_getstr(t, key); +} diff --git a/clang-output/inline_getstr.ll b/clang-output/inline_getstr.ll new file mode 100644 index 0000000..82ff657 --- /dev/null +++ b/clang-output/inline_getstr.ll @@ -0,0 +1,75 @@ +; ModuleID = 'inline_getstr.c' +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-S32" +target triple = "i686-pc-windows-gnu" + +%struct.TValue = type { %union.Value, i32 } +%union.Value = type { i64 } +%struct.Table = type { %struct.GCObject*, i8, i8, i8, i8, i32, %struct.TValue*, %struct.Node*, %struct.Node*, %struct.Table*, %struct.GCObject*, %struct.RaviArray } +%struct.Node = type { %struct.TValue, %union.TKey } +%union.TKey = type { %struct.anon.1 } +%struct.anon.1 = type { %union.Value, i32, i32 } +%struct.GCObject = type { %struct.GCObject*, i8, i8 } +%struct.RaviArray = type { i8*, i32, i32, i32 } +%struct.TString = type { %struct.GCObject*, i8, i8, i8, i8, i32, %union.anon.2 } +%union.anon.2 = type { i64 } + +; Function Attrs: nounwind +define %struct.TValue* @ravi_getstr(%struct.Table* %t, %struct.TString* %key) #0 { +entry: + %hash = getelementptr inbounds %struct.TString, %struct.TString* %key, i32 0, i32 5 + %0 = load i32, i32* %hash, align 4, !tbaa !1 + %lsizenode = getelementptr inbounds %struct.Table, %struct.Table* %t, i32 0, i32 4 + %1 = load i8, i8* %lsizenode, align 1, !tbaa !7 + %conv = zext i8 %1 to i32 + %shl = shl i32 1, %conv + %sub = add nsw i32 %shl, -1 + %and = and i32 %sub, %0 + %node = getelementptr inbounds %struct.Table, %struct.Table* %t, i32 0, i32 7 + %2 = load %struct.Node*, %struct.Node** %node, align 4, !tbaa !10 + %3 = getelementptr inbounds %struct.Node, %struct.Node* %2, i32 %and, i32 1, i32 0, i32 1 + %4 = load i32, i32* %3, align 4, !tbaa !11 + %cmp = icmp eq i32 %4, 68 + br i1 %cmp, label %land.lhs.true, label %if.end + +land.lhs.true: ; preds = %entry + %value_ = getelementptr inbounds %struct.Node, %struct.Node* %2, i32 %and, i32 1, i32 0, i32 0 + %5 = bitcast %union.Value* %value_ to %struct.TString** + %6 = load %struct.TString*, %struct.TString** %5, align 4, !tbaa !13 + %cmp2 = icmp eq %struct.TString* %6, %key + br i1 %cmp2, label %if.then, label %if.end + +if.then: ; preds = %land.lhs.true + %i_val = getelementptr inbounds %struct.Node, %struct.Node* %2, i32 %and, i32 0 + br label %cleanup + +if.end: ; preds = %land.lhs.true, %entry + %call = tail call %struct.TValue* @luaH_getstr(%struct.Table* %t, %struct.TString* %key) #2 + br label %cleanup + +cleanup: ; preds = %if.end, %if.then + %retval.0 = phi %struct.TValue* [ %i_val, %if.then ], [ %call, %if.end ] + ret %struct.TValue* %retval.0 +} + +declare %struct.TValue* @luaH_getstr(%struct.Table*, %struct.TString*) #1 + +attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind } + +!llvm.ident = !{!0} + +!0 = !{!"clang version 3.7.0 (trunk)"} +!1 = !{!2, !6, i64 8} +!2 = !{!"TString", !3, i64 0, !4, i64 4, !4, i64 5, !4, i64 6, !4, i64 7, !6, i64 8, !4, i64 16} +!3 = !{!"any pointer", !4, i64 0} +!4 = !{!"omnipotent char", !5, i64 0} +!5 = !{!"Simple C/C++ TBAA"} +!6 = !{!"int", !4, i64 0} +!7 = !{!8, !4, i64 7} +!8 = !{!"Table", !3, i64 0, !4, i64 4, !4, i64 5, !4, i64 6, !4, i64 7, !6, i64 8, !3, i64 12, !3, i64 16, !3, i64 20, !3, i64 24, !3, i64 28, !9, i64 32} +!9 = !{!"RaviArray", !3, i64 0, !4, i64 4, !6, i64 8, !6, i64 12} +!10 = !{!8, !3, i64 16} +!11 = !{!12, !6, i64 8} +!12 = !{!"TValue", !4, i64 0, !6, i64 8} +!13 = !{!3, !3, i64 0} diff --git a/clang-output/runclang.bat b/clang-output/runclang.bat index 3ec1fa9..114f665 100644 --- a/clang-output/runclang.bat +++ b/clang-output/runclang.bat @@ -1,4 +1,5 @@ setlocal set PATH=%PATH%;"c:\Program Files (x86)\LLVM\bin" -clang -cc1 -O1 -disable-llvm-optzns -S -emit-llvm %1 \ No newline at end of file +rem clang -cc1 -O1 -disable-llvm-optzns -S -emit-llvm %1 +clang -cc1 -O2 -S -emit-llvm %1 \ No newline at end of file diff --git a/include/lopcodes.h b/include/lopcodes.h index d2eae92..192d35e 100644 --- a/include/lopcodes.h +++ b/include/lopcodes.h @@ -299,10 +299,10 @@ OP_RAVI_LT_FF,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ OP_RAVI_LE_II,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ OP_RAVI_LE_FF,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ -OP_RAVI_GETTABLEI,/* A B C R(A) := R(B)[RK(C)], integer key */ -OP_RAVI_GETTABLES,/* A B C R(A) := R(B)[RK(C)], string key */ -OP_RAVI_SETTABLEI,/* A B C R(A)[RK(B)] := RK(C), integer key */ -OP_RAVI_SETTABLES,/* A B C R(A)[RK(B)] := RK(C), string key */ +OP_RAVI_GETTABLE_I,/* A B C R(A) := R(B)[RK(C)], integer key */ +OP_RAVI_GETTABLE_S,/* A B C R(A) := R(B)[RK(C)], string key */ +OP_RAVI_SETTABLE_I,/* A B C R(A)[RK(B)] := RK(C), integer key */ +OP_RAVI_SETTABLE_S,/* A B C R(A)[RK(B)] := RK(C), string key */ OP_RAVI_TOTAB, /* A R(A) := to_table(R(A)) */ OP_RAVI_MOVETAB, /* A B R(A) := R(B), check R(B) is a table */ OP_RAVI_SETUPVALT,/* A B UpValue[B] := to_table(R(A)) */ diff --git a/include/ravi_llvmcodegen.h b/include/ravi_llvmcodegen.h index 46147a5..0c3d8a5 100644 --- a/include/ravi_llvmcodegen.h +++ b/include/ravi_llvmcodegen.h @@ -69,9 +69,9 @@ extern "C" { namespace ravi { /* -** Lua typecode have certain bits that are used to +** Lua typecode have certain bits that are used to ** indicate variants or subtypes, or whether the type -** is collectible. The enumerated values below +** is collectible. The enumerated values below ** reflect the way these type codes get set within ** Lua values - these are the codes the JIT code must ** use. @@ -104,7 +104,7 @@ struct LuaLLVMTypes { // Following are standard C types // Must ensure that these types match // between JIT and the C compiler - llvm::Type *C_voidT; + llvm::Type *C_voidT; llvm::Type *C_doubleT; llvm::Type *C_intptr_t; llvm::Type *C_size_t; @@ -113,7 +113,7 @@ struct LuaLLVMTypes { llvm::Type *C_int64_t; llvm::Type *C_shortT; llvm::Type *C_intT; - llvm::PointerType *C_pintT; /* pointer to int */ + llvm::PointerType *C_pintT; /* pointer to int */ llvm::PointerType *C_pcharT; /* pointer to char */ llvm::Type *lua_NumberT; @@ -242,6 +242,9 @@ struct LuaLLVMTypes { llvm::FunctionType *luaV_executeT; llvm::FunctionType *luaV_gettableT; llvm::FunctionType *luaV_settableT; + llvm::FunctionType *luaH_getintT; + llvm::FunctionType *luaH_setintT; + llvm::FunctionType *luaH_getstrT; // Following are functions that handle specific bytecodes // We cheat for these bytecodes by calling the function that @@ -318,6 +321,10 @@ struct LuaLLVMTypes { llvm::MDNode *tbaa_RaviArray_typeT; llvm::MDNode *tbaa_RaviArray_dataT; llvm::MDNode *tbaa_RaviArray_lenT; + llvm::MDNode *tbaa_TString_hash; + llvm::MDNode *tbaa_Table_lsizenode; + llvm::MDNode *tbaa_Table_array; + llvm::MDNode *tbaa_Table_node; }; class RAVI_API RaviJITStateImpl; @@ -532,6 +539,9 @@ struct RaviFunctionDef { llvm::Function *luaV_divF; llvm::Function *luaV_objlenF; llvm::Function *luaC_upvalbarrierF; + llvm::Function *luaH_getstrF; + llvm::Function *luaH_getintF; + llvm::Function *luaH_setintF; // Some cheats - these correspond to OPCODEs that // are not inlined as of now @@ -612,7 +622,7 @@ public: std::unique_ptr create_function(llvm::IRBuilder<> &builder, RaviFunctionDef *def); - // Save proto->code[pc] into savedpc + // Save proto->code[pc] into savedpc void emit_update_savedpc(RaviFunctionDef *def, int pc); llvm::CallInst *CreateCall1(llvm::IRBuilder<> *builder, llvm::Value *func, @@ -681,6 +691,10 @@ public: 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); // emit code for &ptr[offset] llvm::Value *emit_array_get(RaviFunctionDef *def, llvm::Value *ptr, @@ -729,6 +743,22 @@ public: // emit code to load the table value from register llvm::Instruction *emit_load_reg_h(RaviFunctionDef *def, llvm::Value *ra); + // Gets the size of the hash table + llvm::Value *emit_table_get_hashsize(RaviFunctionDef *def, llvm::Value *table); + + // Gets the location of the hash node for given key and table size + llvm::Value *emit_table_get_hashstr(RaviFunctionDef *def, llvm::Value *table, TString *key); + + llvm::Value *emit_table_get_nodearray(RaviFunctionDef *def, llvm::Value *table); + + llvm::Value *emit_table_get_keytype(RaviFunctionDef *def, llvm::Value *node, llvm::Value *index); + + llvm::Value *emit_table_get_strkey(RaviFunctionDef *def, llvm::Value *node, llvm::Value *index); + + llvm::Value *emit_table_get_value(RaviFunctionDef *def, llvm::Value *node, llvm::Value *index); + + 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); @@ -932,6 +962,9 @@ public: 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_SELF(RaviFunctionDef *def, int A, int B, int C, int pc); void emit_GETUPVAL(RaviFunctionDef *def, int A, int B, int pc); diff --git a/ravi-tests/ravi_tests1.ravi b/ravi-tests/ravi_tests1.ravi index 067f917..6a65d55 100644 --- a/ravi-tests/ravi_tests1.ravi +++ b/ravi-tests/ravi_tests1.ravi @@ -947,7 +947,6 @@ function test_idiv() assert(s1 == s2) print'test 41 (IDIV) OK' end - assert(ravi.compile(test_idiv)) test_idiv() @@ -962,13 +961,17 @@ function test_tableaccess() t.data.city = 'london' return t.name, t.data.city end - check(f, 'NEWTABLE', 'SETTABLES', 'NEWTABLE', - 'SETTABLES', 'GETTABLES', 'SETTABLE', - 'GETTABLES', 'GETTABLES' , 'GETTABLE', + check(f, 'NEWTABLE', 'SETTABLE_S', 'NEWTABLE', + 'SETTABLE_S', 'GETTABLE_S', 'SETTABLE', + 'GETTABLE_S', 'GETTABLE_S' , 'GETTABLE', 'RETURN', 'RETURN') local a,b = f() assert(a == 'dibyendu') assert(b == 'london') + assert(ravi.compile(f)) + a,b = f() + assert(a == 'dibyendu') + assert(b == 'london') -- Test specialised version of GETTABLE and SETTABLE -- when local variable is known to be of table type @@ -980,16 +983,19 @@ function test_tableaccess() t[2][1] = 'london' return t[1], t[2][1] end - check(f, 'NEWTABLE', 'SETTABLEI', 'NEWTABLE', - 'SETTABLEI', 'GETTABLEI', 'SETTABLE', - 'GETTABLEI', 'GETTABLEI' , 'GETTABLE', + check(f, 'NEWTABLE', 'SETTABLE_I', 'NEWTABLE', + 'SETTABLE_I', 'GETTABLE_I', 'SETTABLE', + 'GETTABLE_I', 'GETTABLE_I' , 'GETTABLE', 'RETURN', 'RETURN') local a,b = f() assert(a == 'dibyendu') assert(b == 'london') + assert(ravi.compile(f)) + a,b = f() + assert(a == 'dibyendu') + assert(b == 'london') print 'test tableaccess OK' end - test_tableaccess() diff --git a/src/lapi.c b/src/lapi.c index 8561f85..d3f0d0a 100644 --- a/src/lapi.c +++ b/src/lapi.c @@ -4,6 +4,11 @@ ** See Copyright Notice in lua.h */ +/* +** Portions Copyright (C) 2015 Dibyendu Majumdar +*/ + + #define lapi_c #define LUA_CORE diff --git a/src/lcode.c b/src/lcode.c index de0a13b..d70cb72 100644 --- a/src/lcode.c +++ b/src/lcode.c @@ -4,6 +4,10 @@ ** See Copyright Notice in lua.h */ +/* +** Portions Copyright (C) 2015 Dibyendu Majumdar +*/ + #define lcode_c #define LUA_CORE @@ -444,9 +448,9 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { op = OP_RAVI_GETTABLE_AI; else { if (e->ravi_type == RAVI_TTABLE && e->u.ind.key_type == RAVI_TSTRING) - op = OP_RAVI_GETTABLES; + op = OP_RAVI_GETTABLE_S; else if (e->ravi_type == RAVI_TTABLE && e->u.ind.key_type == RAVI_TNUMINT) - op = OP_RAVI_GETTABLEI; + op = OP_RAVI_GETTABLE_I; else op = OP_GETTABLE; } @@ -762,10 +766,10 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { op = OP_RAVI_SETTABLE_AII; } else if (var->ravi_type == RAVI_TTABLE && var->u.ind.key_type == RAVI_TNUMINT) { /* table with integer key */ - op = OP_RAVI_SETTABLEI; + op = OP_RAVI_SETTABLE_I; } else if (var->ravi_type == RAVI_TTABLE && var->u.ind.key_type == RAVI_TSTRING) { /* table with string key */ - op = OP_RAVI_SETTABLES; + op = OP_RAVI_SETTABLE_S; } } int e = luaK_exp2RK(fs, ex); diff --git a/src/ldebug.c b/src/ldebug.c index 249e53e..f028d77 100644 --- a/src/ldebug.c +++ b/src/ldebug.c @@ -454,8 +454,8 @@ static const char *getobjname (Proto *p, int lastpc, int reg, return getobjname(p, pc, b, name); /* get name for 'b' */ break; } - case OP_RAVI_GETTABLEI: - case OP_RAVI_GETTABLES: + case OP_RAVI_GETTABLE_I: + case OP_RAVI_GETTABLE_S: case OP_RAVI_GETTABLE_AI: case OP_RAVI_GETTABLE_AF: case OP_GETTABUP: diff --git a/src/ldump.c b/src/ldump.c index 969dbde..0b5cec8 100644 --- a/src/ldump.c +++ b/src/ldump.c @@ -4,6 +4,11 @@ ** See Copyright Notice in lua.h */ +/* +** Portions Copyright (C) 2015 Dibyendu Majumdar +*/ + + #define ldump_c #define LUA_CORE diff --git a/src/lfunc.c b/src/lfunc.c index 917a5be..70fae6a 100644 --- a/src/lfunc.c +++ b/src/lfunc.c @@ -4,6 +4,11 @@ ** See Copyright Notice in lua.h */ +/* +** Portions Copyright (C) 2015 Dibyendu Majumdar +*/ + + #define lfunc_c #define LUA_CORE diff --git a/src/lopcodes.c b/src/lopcodes.c index 17e7458..994e28b 100644 --- a/src/lopcodes.c +++ b/src/lopcodes.c @@ -4,6 +4,11 @@ ** See Copyright Notice in lua.h */ +/* +** Portions Copyright (C) 2015 Dibyendu Majumdar +*/ + + #define lopcodes_c #define LUA_CORE @@ -143,10 +148,10 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { "LE_II", /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ "LE_FF", /* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ - "GETTABLEI", /* A B C R(A) := R(B)[RK(C)], integer key */ - "GETTABLES", /* A B C R(A) := R(B)[RK(C)], string key */ - "SETTABLEI", /* A B C R(A)[RK(B)] := RK(C), integer key */ - "SETTABLES", /* A B C R(A)[RK(B)] := RK(C), string key */ + "GETTABLE_I", /* A B C R(A) := R(B)[RK(C)], integer key */ + "GETTABLE_S", /* A B C R(A) := R(B)[RK(C)], string key */ + "SETTABLE_I", /* A B C R(A)[RK(B)] := RK(C), integer key */ + "SETTABLE_S", /* A B C R(A)[RK(B)] := RK(C), string key */ "TOTAB", /* A R(A) := to_table(R(A)) */ "MOVETAB", /* A B R(A) := R(B), check R(B) is a table */ "SETUPVALT", /* A B UpValue[B] := to_table(R(A)) */ @@ -274,10 +279,10 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_LE_II */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_LE_FF */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_RAVI_GETTABLEI */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_RAVI_GETTABLES */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_SETTABLEI */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_SETTABLES */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_RAVI_GETTABLE_I */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_RAVI_GETTABLE_S */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_SETTABLE_I */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_SETTABLE_S */ ,opmode(0, 1, OpArgN, OpArgN, iABC) /* OP_RAVI_TOTAB A R(A) := check_table(R(A)) */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_RAVI_MOVETAB A B R(A) := R(B), check R(B) is a table */ @@ -430,6 +435,7 @@ static void PrintCode(const Proto* f) case OP_RAVI_SETUPVALF: case OP_RAVI_SETUPVALAI: case OP_RAVI_SETUPVALAF: + case OP_RAVI_SETUPVALT: case OP_SETUPVAL: printf("\t; %s",UPVALNAME(b)); break; @@ -443,12 +449,16 @@ static void PrintCode(const Proto* f) if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } break; case OP_GETTABLE: + case OP_RAVI_GETTABLE_I: + case OP_RAVI_GETTABLE_S: case OP_RAVI_GETTABLE_AF: case OP_RAVI_GETTABLE_AI: case OP_SELF: if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } break; case OP_SETTABLE: + case OP_RAVI_SETTABLE_I: + case OP_RAVI_SETTABLE_S: case OP_RAVI_SETTABLE_AF: case OP_RAVI_SETTABLE_AFF: case OP_RAVI_SETTABLE_AI: diff --git a/src/lparser.c b/src/lparser.c index 5cc9e0e..5f50dcf 100644 --- a/src/lparser.c +++ b/src/lparser.c @@ -4,6 +4,10 @@ ** See Copyright Notice in lua.h */ +/* +** Portions Copyright (C) 2015 Dibyendu Majumdar +*/ + #define lparser_c #define LUA_CORE @@ -304,16 +308,16 @@ static TString *str_checkname (LexState *ls) { * expression kind in e->k, e->u.info may have a register * or bytecode */ -static void init_exp (expdesc *e, expkind k, int i, ravitype_t tt) { +static void init_exp (expdesc *e, expkind k, int info, ravitype_t tt) { e->f = e->t = NO_JUMP; e->k = k; - e->u.info = i; + e->u.info = info; /* RAVI change; added type */ e->ravi_type = tt; } /* create a string constant expression, constant's location stored in - * e->u.info, e->ravi_type = LUA_STRING + * e->u.info, e->ravi_type = RAVI_TSTRING */ static void codestring (LexState *ls, expdesc *e, TString *s) { init_exp(e, VK, luaK_stringK(ls->fs, s), RAVI_TSTRING); diff --git a/src/lundump.c b/src/lundump.c index df81cf0..b1cdcc1 100644 --- a/src/lundump.c +++ b/src/lundump.c @@ -4,6 +4,10 @@ ** See Copyright Notice in lua.h */ +/* +** Portions Copyright (C) 2015 Dibyendu Majumdar +*/ + #define lundump_c #define LUA_CORE diff --git a/src/lvm.c b/src/lvm.c index e32227e..97b81bf 100644 --- a/src/lvm.c +++ b/src/lvm.c @@ -4,6 +4,11 @@ ** See Copyright Notice in lua.h */ +/* +** Portions Copyright (C) 2015 Dibyendu Majumdar +*/ + + #define lvm_c #define LUA_CORE @@ -871,7 +876,7 @@ newframe: /* reentry point when frame changes (call/return) */ int b = GETARG_B(i); Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); } break; - case OP_RAVI_GETTABLEI: { + case OP_RAVI_GETTABLE_I: { TValue *rb = RB(i); TValue *rc = RKC(i); lua_Integer idx = ivalue(rc); @@ -880,7 +885,7 @@ newframe: /* reentry point when frame changes (call/return) */ setobj2s(L, ra, v); break; } - case OP_RAVI_GETTABLES: { + case OP_RAVI_GETTABLE_S: { if (ISK(GETARG_C(i))) { TValue *kv = k + INDEXK(GETARG_C(i)); TString *key = tsvalue(kv); @@ -924,8 +929,8 @@ newframe: /* reentry point when frame changes (call/return) */ setobj(L, uv->v, ra); luaC_upvalbarrier(L, uv); } break; - case OP_RAVI_SETTABLEI: - case OP_RAVI_SETTABLES: + case OP_RAVI_SETTABLE_I: + case OP_RAVI_SETTABLE_S: case OP_SETTABLE: { Protect(luaV_settable(L, ra, RKB(i), RKC(i))); } break; diff --git a/src/ravi_llvmcodegen.cpp b/src/ravi_llvmcodegen.cpp index 6fb2ea4..65d7452 100644 --- a/src/ravi_llvmcodegen.cpp +++ b/src/ravi_llvmcodegen.cpp @@ -114,6 +114,25 @@ llvm::Value *RaviCodeGenerator::emit_gep(RaviFunctionDef *def, const char *name, return def->builder->CreateInBoundsGEP(s, values, name); } +llvm::Value *RaviCodeGenerator::emit_gep(RaviFunctionDef *def, const char *name, + llvm::Value *ptr, llvm::Value *offset, + int arg1, int arg2) { + llvm::SmallVector 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 values; + values.push_back(offset); + values.push_back(def->types->kInt[arg1]); + return def->builder->CreateInBoundsGEP(ptr, values, name); +} + llvm::Value * RaviCodeGenerator::emit_gep_ci_func_value_gc_asLClosure(RaviFunctionDef *def) { // emit code for (LClosure *)ci->func->value_.gc @@ -147,21 +166,23 @@ RaviCodeGenerator::emit_load_proto_sizep(RaviFunctionDef *def) { // enables this to be updated per bytecode instruction - this is only // required if someone wishes to set a line hook. The second option // is very expensive and will inhibit optimizations, hence it is optional -// See issue #15 +// See issue #15 void RaviCodeGenerator::emit_update_savedpc(RaviFunctionDef *def, int pc) { // Get proto->code llvm::Value *proto_code_ptr = emit_gep(def, "code", def->proto_ptr, 0, 15); llvm::Instruction *code_ptr = def->builder->CreateLoad(proto_code_ptr); - code_ptr->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Proto_codeT); + 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 // what the VM does in interpreted mode - llvm::Value *code_offset_ptr = emit_array_get(def, code_ptr, pc+1); + 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); - llvm::Instruction *ins = def->builder->CreateStore(code_offset_ptr, savedpc_ptr); - ins->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_CallInfo_savedpcT); + llvm::Instruction *ins = + def->builder->CreateStore(code_offset_ptr, savedpc_ptr); + ins->setMetadata(llvm::LLVMContext::MD_tbaa, + def->types->tbaa_CallInfo_savedpcT); } - llvm::Value *RaviCodeGenerator::emit_array_get(RaviFunctionDef *def, llvm::Value *ptr, int offset) { // emit code for &ptr[offset] @@ -267,6 +288,77 @@ llvm::Instruction *RaviCodeGenerator::emit_load_reg_h(RaviFunctionDef *def, return h; } +llvm::Value *RaviCodeGenerator::emit_table_get_hashsize(RaviFunctionDef *def, + llvm::Value *t) { + // Obtain the lsizenode of the hash table + llvm::Value *lsizenode_ptr = emit_gep(def, "lsizenode", t, 0, 4); + llvm::Instruction *lsizenode = def->builder->CreateLoad(lsizenode_ptr); + lsizenode->setMetadata(llvm::LLVMContext::MD_tbaa, + def->types->tbaa_Table_lsizenode); + // convert to integer (lsizenode is a byte) + llvm::Value *intsize = + def->builder->CreateZExt(lsizenode, def->types->C_intT); + // #define twoto(x) (1<<(x)) + // #define sizenode(t) (twoto((t)->lsizenode)) + llvm::Value *size = def->builder->CreateShl(def->types->kInt[1], intsize); + return size; +} + +llvm::Value *RaviCodeGenerator::emit_table_get_hashstr(RaviFunctionDef *def, + llvm::Value *table, + TString *key) { + llvm::Value *size = emit_table_get_hashsize(def, table); + unsigned int hash = key->hash; + // #define lmod(s,size) (cast(int, (s) & ((size)-1))) + llvm::Value *sizeminusone = + def->builder->CreateNSWSub(size, def->types->kInt[1]); + llvm::Value *offset = def->builder->CreateAnd( + llvm::ConstantInt::get(def->types->C_intT, hash), sizeminusone); + return offset; +} + +llvm::Value *RaviCodeGenerator::emit_table_get_nodearray(RaviFunctionDef *def, + llvm::Value *table) { + // Get access to the node array + llvm::Value *node_ptr = emit_gep(def, "node", table, 0, 7); + llvm::Instruction *node = def->builder->CreateLoad(node_ptr); + node->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Table_node); + return node; +} + +llvm::Value *RaviCodeGenerator::emit_table_get_keytype(RaviFunctionDef *def, + llvm::Value *node, + llvm::Value *index) { + llvm::Value *ktype_ptr = emit_gep(def, "keytype", node, index, 1, 1); + llvm::Instruction *ktype = def->builder->CreateLoad(ktype_ptr); + ktype->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_ttT); + return ktype; +} + +llvm::Value *RaviCodeGenerator::emit_table_get_strkey(RaviFunctionDef *def, + llvm::Value *node, + llvm::Value *index) { + llvm::Value *value_ptr = emit_gep(def, "keyvalue", node, index, 1, 0); + llvm::Value *sptr = + def->builder->CreateBitCast(value_ptr, def->types->ppTStringT); + llvm::Instruction *keyvalue = def->builder->CreateLoad(sptr); + keyvalue->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_ppointerT); + return keyvalue; +} + +llvm::Value *RaviCodeGenerator::emit_table_get_value(RaviFunctionDef *def, llvm::Value *node, llvm::Value *index) { + return emit_gep(def, "nodeval", node, index, 0); +} + +llvm::Instruction *RaviCodeGenerator::emit_load_reg_s(RaviFunctionDef *def, + llvm::Value *rb) { + llvm::Value *rb_s = def->builder->CreateBitCast(rb, def->types->ppTStringT); + llvm::Instruction *s = def->builder->CreateLoad(rb_s); + // Following TBAA is okay as the field type is a pointer + s->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_hT); + return s; +} + llvm::Instruction * RaviCodeGenerator::emit_load_reg_h_floatarray(RaviFunctionDef *def, llvm::Instruction *h) { @@ -758,10 +850,10 @@ bool RaviCodeGenerator::canCompile(Proto *p) { case OP_RAVI_SHR_II: case OP_SHR: case OP_SHL: - case OP_RAVI_GETTABLEI: - case OP_RAVI_GETTABLES: - case OP_RAVI_SETTABLEI: - case OP_RAVI_SETTABLES: + case OP_RAVI_GETTABLE_I: + case OP_RAVI_GETTABLE_S: + case OP_RAVI_SETTABLE_I: + case OP_RAVI_SETTABLE_S: break; default: return false; @@ -914,6 +1006,16 @@ void RaviCodeGenerator::emit_extern_declarations(RaviFunctionDef *def) { def->luaV_gettableF = def->raviF->addExternFunction( def->types->luaV_gettableT, reinterpret_cast(&luaV_gettable), "luaV_gettable"); + def->luaH_getintF = def->raviF->addExternFunction( + def->types->luaH_getintT, reinterpret_cast(&luaH_getint), + "luaH_getint"); + def->luaH_setintF = def->raviF->addExternFunction( + def->types->luaH_setintT, reinterpret_cast(&luaH_setint), + "luaH_setint"); + def->luaH_getstrF = def->raviF->addExternFunction( + def->types->luaH_getstrT, reinterpret_cast(&luaH_getstr), + "luaH_getstr"); + def->raviV_op_loadnilF = def->raviF->addExternFunction( def->types->raviV_op_loadnilT, reinterpret_cast(&raviV_op_loadnil), "raviV_op_loadnil"); @@ -1101,6 +1203,8 @@ 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 = @@ -1409,15 +1513,29 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p, emit_CALL(def, A, B, C, pc); } break; - case OP_RAVI_SETTABLEI: - case OP_RAVI_SETTABLES: + case OP_RAVI_SETTABLE_I: + case OP_RAVI_SETTABLE_S: case OP_SETTABLE: { int B = GETARG_B(i); int C = GETARG_C(i); emit_SETTABLE(def, A, B, C, pc); } break; - case OP_RAVI_GETTABLEI: - case OP_RAVI_GETTABLES: + case OP_RAVI_GETTABLE_S: { + int C = GETARG_C(i); + int B = GETARG_B(i); + if (ISK(C)) { + TValue *kv = k + INDEXK(C); + TString *key = tsvalue(kv); + if (key->tt == LUA_TSHRSTR) { + emit_GETTABLE_S(def, A, B, C, pc, key); + } else { + emit_GETTABLE(def, A, B, C, pc); + } + } else { + emit_GETTABLE(def, A, B, C, pc); + } + } break; + case OP_RAVI_GETTABLE_I: case OP_GETTABLE: { int B = GETARG_B(i); int C = GETARG_C(i); diff --git a/src/ravi_llvmtable.cpp b/src/ravi_llvmtable.cpp index 955395b..ce6de56 100644 --- a/src/ravi_llvmtable.cpp +++ b/src/ravi_llvmtable.cpp @@ -32,7 +32,8 @@ void RaviCodeGenerator::emit_SELF(RaviFunctionDef *def, int A, int B, int C, // Protect(luaV_gettable(L, rb, RKC(i), ra)); bool traced = emit_debug_trace(def, OP_SELF, pc); // Below may invoke metamethod so we set savedpc - if (!traced) emit_update_savedpc(def, pc); + if (!traced) + emit_update_savedpc(def, pc); emit_load_base(def); llvm::Value *rb = emit_gep_register(def, B); llvm::Value *ra1 = emit_gep_register(def, A + 1); @@ -47,7 +48,8 @@ void RaviCodeGenerator::emit_LEN(RaviFunctionDef *def, int A, int B, int pc) { // Protect(luaV_objlen(L, ra, RB(i))); bool traced = emit_debug_trace(def, OP_LEN, pc); // Below may invoke metamethod so we set savedpc - if (!traced) emit_update_savedpc(def, pc); + if (!traced) + emit_update_savedpc(def, pc); emit_load_base(def); llvm::Value *ra = emit_gep_register(def, A); llvm::Value *rb = emit_gep_register(def, B); @@ -60,7 +62,8 @@ void RaviCodeGenerator::emit_SETTABLE(RaviFunctionDef *def, int A, int B, int C, // Protect(luaV_settable(L, ra, RKB(i), RKC(i))); bool traced = emit_debug_trace(def, OP_SETTABLE, pc); // Below may invoke metamethod so we set savedpc - if (!traced) emit_update_savedpc(def, pc); + if (!traced) + emit_update_savedpc(def, pc); emit_load_base(def); llvm::Value *ra = emit_gep_register(def, A); llvm::Value *rb = emit_gep_register_or_constant(def, B); @@ -74,7 +77,8 @@ void RaviCodeGenerator::emit_GETTABLE(RaviFunctionDef *def, int A, int B, int C, // Protect(luaV_gettable(L, RB(i), RKC(i), ra)); bool traced = emit_debug_trace(def, OP_GETTABLE, pc); // Below may invoke metamethod so we set savedpc - if (!traced) emit_update_savedpc(def, pc); + if (!traced) + emit_update_savedpc(def, pc); emit_load_base(def); llvm::Value *ra = emit_gep_register(def, A); llvm::Value *rb = emit_gep_register(def, B); @@ -82,6 +86,126 @@ void RaviCodeGenerator::emit_GETTABLE(RaviFunctionDef *def, int A, int B, int C, CreateCall4(def->builder, def->luaV_gettableF, def->L, rb, rc, ra); } +// Emit inline code for accessing a table element using a string key +// We try to access the element using the hash part but if the +// key is not in the main position then we fall back on luaH_getstr(). +// IMPORTANT - this emitter should only be called when key is known to +// to be short string +void RaviCodeGenerator::emit_GETTABLE_S(RaviFunctionDef *def, int A, int B, + int C, int pc, TString *key) { + + // The code we want to generate is this: + // struct Node *n = hashstr(t, key); + // const struct TValue *k = gkey(n); + // if (ttisshrstring(k) && eqshrstr(tsvalue(k), key)) + // return gval(n); + // return luaH_getstr(t, key); + + // A number of macros are involved above do the + // the generated code is somewhat more complex + + // we don't need to refresh base here as the lua_State is not being touched + emit_debug_trace(def, OP_RAVI_GETTABLE_S, pc); + + llvm::Value *ra = emit_gep_register(def, A); + llvm::Value *rb = emit_gep_register(def, B); + + // Fortunately as we are dealing with a string constant we already + // know the hash code of the key + //unsigned int hash = key->hash; + // Get the hash table + llvm::Instruction *t = emit_load_reg_h(def, rb); + + // Obtain the lsizenode of the hash table + //llvm::Value *lsizenode_ptr = emit_gep(def, "lsizenode", t, 0, 4); + //llvm::Instruction *lsizenode = def->builder->CreateLoad(lsizenode_ptr); + //lsizenode->setMetadata(llvm::LLVMContext::MD_tbaa, + // def->types->tbaa_Table_lsizenode); + //// convert to integer (lsizenode is a byte) + //llvm::Value *intsize = + // def->builder->CreateZExt(lsizenode, def->types->C_intT); + //// #define twoto(x) (1<<(x)) + //// #define sizenode(t) (twoto((t)->lsizenode)) + //llvm::Value *size = def->builder->CreateShl(def->types->kInt[1], intsize); + // #define lmod(s,size) (cast(int, (s) & ((size)-1))) + //llvm::Value *sizeminusone = + // def->builder->CreateNSWSub(size, def->types->kInt[1]); + //llvm::Value *offset = def->builder->CreateAnd( + // llvm::ConstantInt::get(def->types->C_intT, hash), sizeminusone); + llvm::Value *offset = emit_table_get_hashstr(def, t, key); + + // Get access to the node array + //llvm::Value *node_ptr = emit_gep(def, "node", t, 0, 7); + //llvm::Instruction *node = def->builder->CreateLoad(node_ptr); + //node->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_Table_node); + llvm::Value *node = emit_table_get_nodearray(def, t); + + // Now we need to get to the right element in the node array + // and retrieve the type information which is held there + //llvm::Value *ktype_ptr = emit_gep(def, "keytype", node, offset, 1, 1); + //llvm::Instruction *ktype = def->builder->CreateLoad(ktype_ptr); + //ktype->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_TValue_ttT); + llvm::Value *ktype = emit_table_get_keytype(def, node, offset); + + // We need to check that the key type is also short string + llvm::Value *is_shortstring = + emit_is_value_of_type(def, ktype, LUA__TSHRSTR, "is_shortstring"); + llvm::BasicBlock *testkey = + llvm::BasicBlock::Create(def->jitState->context(), "testkey"); + llvm::BasicBlock *testok = + llvm::BasicBlock::Create(def->jitState->context(), "testok"); + llvm::BasicBlock *testfail = + llvm::BasicBlock::Create(def->jitState->context(), "testfail"); + llvm::BasicBlock *testend = + llvm::BasicBlock::Create(def->jitState->context(), "testend"); + def->builder->CreateCondBr(is_shortstring, testkey, testfail); + + // Now we need to compare the keys + def->f->getBasicBlockList().push_back(testkey); + def->builder->SetInsertPoint(testkey); + + // Get the key from the node + //llvm::Value *value_ptr = emit_gep(def, "keyvalue", node, offset, 1, 0); + //llvm::Value *sptr = + // def->builder->CreateBitCast(value_ptr, def->types->ppTStringT); + //llvm::Instruction *keyvalue = def->builder->CreateLoad(sptr); + //keyvalue->setMetadata(llvm::LLVMContext::MD_tbaa, def->types->tbaa_ppointerT); + llvm::Value *keyvalue = emit_table_get_strkey(def, node, offset); + + // Cast the pointer to a intptr so we can compare + llvm::Value *intptr = + def->builder->CreatePtrToInt(keyvalue, def->types->C_intptr_t); + llvm::Value *ourptr = + llvm::ConstantInt::get(def->types->C_intptr_t, (intptr_t)key); + // Compare the two pointers + // If they match then we found the element + llvm::Value *same = def->builder->CreateICmpEQ(intptr, ourptr); + def->builder->CreateCondBr(same, testok, testfail); + + // If key found return the value + def->f->getBasicBlockList().push_back(testok); + def->builder->SetInsertPoint(testok); + //llvm::Value *value1 = emit_gep(def, "nodeval", node, offset, 0); + llvm::Value *value1 = emit_table_get_value(def, node, offset); + def->builder->CreateBr(testend); + + // Not found so call luaH_getstr + def->f->getBasicBlockList().push_back(testfail); + def->builder->SetInsertPoint(testfail); + llvm::Value *rc = emit_gep_register_or_constant(def, C); + llvm::Value *value2 = + CreateCall2(def->builder, def->luaH_getstrF, t, emit_load_reg_s(def, rc)); + def->builder->CreateBr(testend); + + // merge + def->f->getBasicBlockList().push_back(testend); + def->builder->SetInsertPoint(testend); + llvm::PHINode *phi = def->builder->CreatePHI(def->types->pTValueT, 2); + phi->addIncoming(value1, testok); + phi->addIncoming(value2, testfail); + emit_assign(def, ra, phi); +} + void RaviCodeGenerator::emit_GETTABLE_AF(RaviFunctionDef *def, int A, int B, int C, bool omitArrayGetRangeCheck, int pc) { @@ -398,7 +522,8 @@ void RaviCodeGenerator::emit_GETTABUP(RaviFunctionDef *def, int A, int B, int C, // Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); bool traced = emit_debug_trace(def, OP_GETTABUP, pc); // Below may invoke metamethod so we set savedpc - if (!traced) emit_update_savedpc(def, pc); + if (!traced) + emit_update_savedpc(def, pc); emit_load_base(def); llvm::Value *ra = emit_gep_register(def, A); llvm::Value *rc = emit_gep_register_or_constant(def, C); @@ -417,7 +542,8 @@ void RaviCodeGenerator::emit_SETTABUP(RaviFunctionDef *def, int A, int B, int C, // Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); bool traced = emit_debug_trace(def, OP_SETTABUP, pc); - if (!traced) emit_update_savedpc(def, pc); + if (!traced) + emit_update_savedpc(def, pc); emit_load_base(def); llvm::Value *rb = emit_gep_register_or_constant(def, B); llvm::Value *rc = emit_gep_register_or_constant(def, C); diff --git a/src/ravi_llvmtypes.cpp b/src/ravi_llvmtypes.cpp index f5a4d42..5472815 100644 --- a/src/ravi_llvmtypes.cpp +++ b/src/ravi_llvmtypes.cpp @@ -866,6 +866,29 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) { raviV_op_shrT = llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false); + // const TValue *luaH_getint(Table *t, lua_Integer key); + elements.clear(); + elements.push_back(pTableT); + elements.push_back(lua_IntegerT); + luaH_getintT = + llvm::FunctionType::get(pTValueT, elements, false); + + // void luaH_setint(lua_State *L, Table *t, lua_Integer key, TValue *value); + elements.clear(); + elements.push_back(plua_StateT); + elements.push_back(pTableT); + elements.push_back(lua_IntegerT); + elements.push_back(pTValueT); + luaH_setintT = + llvm::FunctionType::get(llvm::Type::getVoidTy(context), elements, false); + + // const TValue *luaH_getstr(Table *t, TString *key); + elements.clear(); + elements.push_back(pTableT); + 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 // value); elements.clear(); @@ -1161,20 +1184,20 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) { std::pair(tbaa_charT, 13)); /* modifiers */ tbaa_RaviArrayT = mdbuilder.createTBAAStructTypeNode("RaviArray", nodes); - // Table + // Table TBAA struct type nodes.clear(); - nodes.push_back(std::pair(tbaa_pointerT, 0)); - nodes.push_back(std::pair(tbaa_charT, 4)); - nodes.push_back(std::pair(tbaa_charT, 5)); - nodes.push_back(std::pair(tbaa_charT, 6)); - nodes.push_back(std::pair(tbaa_charT, 7)); - nodes.push_back(std::pair(tbaa_intT, 8)); - nodes.push_back(std::pair(tbaa_pointerT, 12)); - nodes.push_back(std::pair(tbaa_pointerT, 16)); - nodes.push_back(std::pair(tbaa_pointerT, 20)); - nodes.push_back(std::pair(tbaa_pointerT, 24)); - nodes.push_back(std::pair(tbaa_pointerT, 28)); - nodes.push_back(std::pair(tbaa_RaviArrayT, 32)); + 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_charT, 7)); /* lsizenode */ + nodes.push_back(std::pair(tbaa_intT, 8)); /* size array */ + nodes.push_back(std::pair(tbaa_pointerT, 12)); /* array */ + nodes.push_back(std::pair(tbaa_pointerT, 16)); /* node */ + nodes.push_back(std::pair(tbaa_pointerT, 20)); /* lastfree */ + nodes.push_back(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 */ tbaa_TableT = mdbuilder.createTBAAStructTypeNode("Table", nodes); tbaa_RaviArray_dataT = @@ -1183,6 +1206,9 @@ LuaLLVMTypes::LuaLLVMTypes(llvm::LLVMContext &context) : mdbuilder(context) { mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_intT, 36); tbaa_RaviArray_typeT = mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_charT, 44); + tbaa_Table_lsizenode = mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_charT, 7); + tbaa_Table_array = mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 12); + tbaa_Table_node = mdbuilder.createTBAAStructTagNode(tbaa_TableT, tbaa_pointerT, 16); } void LuaLLVMTypes::dump() {