issue #128 added generic forprep/forloop

gccjit-ravi534
Dibyendu Majumdar 7 years ago
parent 0ae309ee1e
commit 35ae4cc567

@ -82,4 +82,25 @@ x = function()
compile(x)
assert(x() == 5)
x = function()
local j = -99
for i = 10,1,-1 do
j = i
end
return j
end
ravi.compile(x)
assert(x() == 1)
x = function()
local j = -9.9
for i = 10.5,1.5,-1.0 do
j = i
end
return j
end
ravi.compile(x)
assert(x() == 1.5)
print'Ok'

@ -37,6 +37,9 @@ enum errorcode {
Error_upval_needs_integer_array,
Error_upval_needs_number_array,
Error_upval_needs_table,
Error_for_limit_must_be_number,
Error_for_step_must_be_number,
Error_for_initial_value_must_be_number,
};
static const char *errortext[] = {
@ -50,6 +53,9 @@ static const char *errortext[] = {
"upvalue of integer[] type, cannot be set to non integer[] value",
"upvalue of number[] type, cannot be set to non number[] value",
"upvalue of table type, cannot be set to non table value",
"'for' limit must be a number",
"'for' step must be a number",
"'for' initial value must be a number",
NULL };
static void raise_error(lua_State *L, int errorcode) {
@ -553,6 +559,7 @@ static const char Lua_header[] = ""
"extern void raviV_op_closure(lua_State *L, CallInfo *ci, LClosure *cl, int a, int Bx);\n"
"extern void raviV_op_vararg(lua_State *L, CallInfo *ci, LClosure *cl, int a, int b);\n"
"extern void luaV_objlen (lua_State *L, StkId ra, const TValue *rb);\n"
"extern int luaV_forlimit(const TValue *obj, lua_Integer *p, lua_Integer step, int *stopnow);\n"
"extern void raise_error(lua_State *L, int errorcode);\n"
"#define R(i) (base + i)\n"
"#define K(i) (k + i)\n"
@ -574,8 +581,10 @@ bool raviJ_cancompile(Proto *p) {
case OP_LOADK:
case OP_RAVI_FORLOOP_IP:
case OP_RAVI_FORLOOP_I1:
case OP_FORLOOP:
case OP_RAVI_FORPREP_IP:
case OP_RAVI_FORPREP_I1:
case OP_FORPREP:
case OP_MOVE:
case OP_LOADNIL:
case OP_JMP:
@ -666,8 +675,6 @@ bool raviJ_cancompile(Proto *p) {
case OP_TFORCALL:
case OP_TFORLOOP:
case OP_SETUPVAL:
case OP_FORPREP:
case OP_FORLOOP:
case OP_UNM:
#endif
default: {
@ -1297,6 +1304,63 @@ static void emit_op_vararg(struct function *fn, int A, int B, int pc) {
membuff_add_fstring(&fn->body, "raviV_op_vararg(L, ci, cl, %d, %d);\n", A, B);
}
static void emit_op_forprep(struct function *fn, int A, int pc,
int pc1)
{
if (!fn->locals[A]) {
fn->locals[A] =
1; // Lua can reuse the same forloop vars if loop isn't nested
membuff_add_fstring(&fn->prologue, "lua_Integer init_%d = 0;\n", A);
membuff_add_fstring(&fn->prologue, "lua_Integer limit_%d = 0;\n", A);
membuff_add_fstring(&fn->prologue, "lua_Integer step_%d = 0;\n", A);
membuff_add_fstring(&fn->prologue, "lua_Number ninit_%d = 0.0;\n", A);
membuff_add_fstring(&fn->prologue, "lua_Number nlimit_%d = 0.0;\n", A);
membuff_add_fstring(&fn->prologue, "lua_Number nstep_%d = 0.0;\n", A);
membuff_add_fstring(&fn->prologue, "int intloop_%d = 0;\n", A);
}
emit_reg(fn, "ra", A); // init
membuff_add_string(&fn->body, "rb = ra+1; /*limit*/\n");
membuff_add_string(&fn->body, "rc = ra+2; /*step*/\n");
membuff_add_fstring(&fn->body, "if (ttisinteger(ra) && ttisinteger(rc) && luaV_forlimit(rb, &limit_%d, ivalue(rc), &result)) {\n", A);
membuff_add_fstring(&fn->body, " init_%d = (result ? 0 : ivalue(ra));\n", A);
membuff_add_fstring(&fn->body, " step_%d = ivalue(rc);\n", A);
membuff_add_fstring(&fn->body, " init_%d -= step_%d;\n", A, A);
membuff_add_fstring(&fn->body, " intloop_%d = 1;\n", A);
membuff_add_string(&fn->body, "}\n");
membuff_add_string(&fn->body, "else {\n");
membuff_add_fstring(&fn->body, " if (!tonumber(rb, &nlimit_%d)) {\n", A);
membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_for_limit_must_be_number);
membuff_add_string(&fn->body, " goto Lraise_error;\n");
membuff_add_string(&fn->body, " }\n");
membuff_add_fstring(&fn->body, " if (!tonumber(rc, &nstep_%d)) {\n", A);
membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_for_step_must_be_number);
membuff_add_string(&fn->body, " goto Lraise_error;\n");
membuff_add_string(&fn->body, " }\n");
membuff_add_fstring(&fn->body, " if (!tonumber(ra, &ninit_%d)) {\n", A);
membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_for_initial_value_must_be_number);
membuff_add_string(&fn->body, " goto Lraise_error;\n");
membuff_add_string(&fn->body, " }\n");
membuff_add_fstring(&fn->body, " ninit_%d -= nstep_%d;\n", A, A);
membuff_add_string(&fn->body, "}\n");
membuff_add_fstring(&fn->body, "goto Lbc_%d;\n", pc);
}
static void emit_op_forloop(struct function *fn, int A, int pc,
int pc1) {
membuff_add_fstring(&fn->body, "if (intloop_%d) {\n", A);
membuff_add_fstring(&fn->body, " init_%d += step_%d;\n", A, A);
membuff_add_fstring(&fn->body, " if ((0 < step_%d) ? (init_%d <= limit_%d) : (limit_%d <= init_%d)) {\n", A, A, A, A, A);
membuff_add_fstring(&fn->body, " ra = R(%d);\n setivalue(ra, init_%d);\n goto Lbc_%d;\n", A + 3, A, pc);
membuff_add_string(&fn->body, " }\n");
membuff_add_string(&fn->body, "}\n");
membuff_add_string(&fn->body, "else {\n");
membuff_add_fstring(&fn->body, " ninit_%d += nstep_%d;\n", A, A);
membuff_add_fstring(&fn->body, " if ((0.0 < nstep_%d) ? (ninit_%d <= nlimit_%d) : (nlimit_%d <= ninit_%d)) {\n", A, A, A, A, A);
membuff_add_fstring(&fn->body, " ra = R(%d);\n setfltvalue(ra, ninit_%d);\n goto Lbc_%d;\n", A + 3, A, pc);
membuff_add_string(&fn->body, " }\n");
membuff_add_string(&fn->body, "}\n");
}
static void cleanup(struct function *fn) {
free(fn->jmps);
if (fn->locals) free(fn->locals);
@ -1354,6 +1418,16 @@ bool raviJ_codegen(struct lua_State *L, struct Proto *p,
int j = sbx + pc + 1;
emit_op_iforloop(&fn, A, j, op == OP_RAVI_FORLOOP_I1, pc);
} break;
case OP_FORPREP: {
int sbx = GETARG_sBx(i);
int j = sbx + pc + 1;
emit_op_forprep(&fn, A, j, pc);
} break;
case OP_FORLOOP: {
int sbx = GETARG_sBx(i);
int j = sbx + pc + 1;
emit_op_forloop(&fn, A, j, pc);
} break;
case OP_MOVE: {
int B = GETARG_B(i);
emit_op_move(&fn, A, B, pc);

@ -174,6 +174,8 @@ int raviV_initjit(struct lua_State *L) {
register_builtin_arg5(jit->jit, "raviV_op_vararg", raviV_op_vararg, NJXValueKind_V, NJXValueKind_P, NJXValueKind_P, NJXValueKind_P, NJXValueKind_I, NJXValueKind_I);
// void luaV_objlen (lua_State *L, StkId ra, const TValue *rb)
register_builtin_arg3(jit->jit, "luaV_objlen", luaV_objlen, NJXValueKind_V, NJXValueKind_P, NJXValueKind_P, NJXValueKind_P);
//int luaV_forlimit(const TValue *obj, lua_Integer *p, lua_Integer step, int *stopnow);
register_builtin_arg4(jit->jit, "luaV_forlimit", luaV_forlimit, NJXValueKind_I, NJXValueKind_P, NJXValueKind_P, NJXValueKind_Q, NJXValueKind_P);
G->ravi_state = jit;
return 0;

Loading…
Cancel
Save