|
|
|
@ -43,28 +43,6 @@ enum errorcode {
|
|
|
|
|
Error_array_out_of_bounds,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static const char *errortext[] = {
|
|
|
|
|
"integer expected",
|
|
|
|
|
"number expected",
|
|
|
|
|
"integer[] expected",
|
|
|
|
|
"number[] expected",
|
|
|
|
|
"table expected",
|
|
|
|
|
"upvalue of integer type, cannot be set to non integer value",
|
|
|
|
|
"upvalue of number type, cannot be set to non number value",
|
|
|
|
|
"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",
|
|
|
|
|
"array out of bounds",
|
|
|
|
|
NULL };
|
|
|
|
|
|
|
|
|
|
static void raise_error(lua_State *L, int errorcode) {
|
|
|
|
|
assert(errorcode >= 0 && errorcode <= Error_upval_needs_table);
|
|
|
|
|
luaG_runerror(L, errortext[errorcode]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char Lua_header[] = ""
|
|
|
|
|
"#define NULL ((void *)0)\n"
|
|
|
|
|
"typedef struct lua_State lua_State;\n"
|
|
|
|
@ -714,8 +692,6 @@ struct function {
|
|
|
|
|
membuff_t body;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int add_local_var(struct function *fn) { return fn->var++; }
|
|
|
|
|
|
|
|
|
|
// Identify Ravi bytecode instructions that are jump
|
|
|
|
|
// targets - we need this so that when generating code
|
|
|
|
|
// we can emit labels for gotos
|
|
|
|
@ -771,6 +747,8 @@ static void emit_gettable_ai(struct function *fn, int A, int B,
|
|
|
|
|
int C, bool omitArrayGetRangeCheck,
|
|
|
|
|
int pc)
|
|
|
|
|
{
|
|
|
|
|
(void)omitArrayGetRangeCheck;
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -789,6 +767,8 @@ static void emit_gettable_af(struct function *fn, int A, int B,
|
|
|
|
|
int C, bool omitArrayGetRangeCheck,
|
|
|
|
|
int pc)
|
|
|
|
|
{
|
|
|
|
|
(void)omitArrayGetRangeCheck;
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -806,6 +786,8 @@ static void emit_gettable_af(struct function *fn, int A, int B,
|
|
|
|
|
static void emit_settable_aii(struct function *fn, int A, int B,
|
|
|
|
|
int C, bool known_int, int pc)
|
|
|
|
|
{
|
|
|
|
|
(void)pc;
|
|
|
|
|
(void)known_int;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg_or_k(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -843,6 +825,8 @@ static void emit_settable_ai(struct function *fn, int A, int B,
|
|
|
|
|
static void emit_settable_aff(struct function *fn, int A, int B,
|
|
|
|
|
int C, bool known_int, int pc)
|
|
|
|
|
{
|
|
|
|
|
(void)pc;
|
|
|
|
|
(void)known_int;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg_or_k(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -880,6 +864,7 @@ static void emit_settable_af(struct function *fn, int A, int B,
|
|
|
|
|
static void emit_comparison(struct function *fn, int A, int B, int C, int j,
|
|
|
|
|
int jA, const char *compfunc, OpCode opCode,
|
|
|
|
|
int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
const char *oper = "==";
|
|
|
|
|
switch (opCode) {
|
|
|
|
|
case OP_RAVI_LT_II: oper = "<"; goto Lemitint;
|
|
|
|
@ -969,6 +954,7 @@ static void emit_jump_label(struct function *fn, int pc) {
|
|
|
|
|
|
|
|
|
|
static void emit_op_loadk(struct function *fn, int A, int Bx, int pc) {
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
(void)pc;
|
|
|
|
|
TValue *Konst = &fn->p->k[Bx];
|
|
|
|
|
switch (Konst->tt_) {
|
|
|
|
|
case LUA_TNUMINT:
|
|
|
|
@ -990,9 +976,9 @@ static void emit_op_loadk(struct function *fn, int A, int Bx, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_return(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "if (cl->p->sizep > 0) luaF_close(L, base);\n");
|
|
|
|
|
int var = add_local_var(fn);
|
|
|
|
|
membuff_add_fstring(&fn->body,
|
|
|
|
|
"result = (%d != 0 ? %d - 1 : cast_int(L->top - ra));\n",
|
|
|
|
|
B, B);
|
|
|
|
@ -1000,18 +986,21 @@ static void emit_op_return(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_move(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_fstring(&fn->body, "rb = R(%d);\n", B);
|
|
|
|
|
membuff_add_fstring(&fn->body, "setobj2s(L, ra, rb);\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_loadnil(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
int b = B;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
do { membuff_add_fstring(&fn->body, "setnilvalue(ra++);\n"); } while (b--);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_jmp(struct function *fn, int A, int sBx, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
if (A > 0) {
|
|
|
|
|
membuff_add_fstring(&fn->body, "ra = R(%d);\n", A - 1);
|
|
|
|
|
membuff_add_string(&fn->body, "luaF_close(L, ra);\n");
|
|
|
|
@ -1021,6 +1010,7 @@ static void emit_op_jmp(struct function *fn, int A, int sBx, int pc) {
|
|
|
|
|
|
|
|
|
|
static void emit_op_loadbool(struct function *fn, int A, int B, int C, int j,
|
|
|
|
|
int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
membuff_add_fstring(&fn->body, "ra = R(%d);\n", A);
|
|
|
|
|
membuff_add_fstring(&fn->body, "setbvalue(ra, %d);\n", B);
|
|
|
|
|
|
|
|
|
@ -1029,6 +1019,8 @@ static void emit_op_loadbool(struct function *fn, int A, int B, int C, int j,
|
|
|
|
|
|
|
|
|
|
static void emit_op_test(struct function *fn, int A, int B, int C, int j,
|
|
|
|
|
int jA, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
(void)B;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
if (C) { membuff_add_string(&fn->body, "result = l_isfalse(ra);\n"); }
|
|
|
|
|
else {
|
|
|
|
@ -1045,6 +1037,7 @@ static void emit_op_test(struct function *fn, int A, int B, int C, int j,
|
|
|
|
|
|
|
|
|
|
static void emit_op_testset(struct function *fn, int A, int B, int C, int j,
|
|
|
|
|
int jA, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
membuff_add_fstring(&fn->body, "rb = R(%d);\n", B);
|
|
|
|
|
if (C) { membuff_add_string(&fn->body, "result = l_isfalse(rb);\n"); }
|
|
|
|
|
else {
|
|
|
|
@ -1063,6 +1056,7 @@ static void emit_op_testset(struct function *fn, int A, int B, int C, int j,
|
|
|
|
|
|
|
|
|
|
static void emit_op_iforloop(struct function *fn, int A, int pc, int step_one,
|
|
|
|
|
int pc1) {
|
|
|
|
|
(void)pc1;
|
|
|
|
|
if (!step_one) { membuff_add_fstring(&fn->body, "i_%d += step_%d;\n", A, A); }
|
|
|
|
|
else {
|
|
|
|
|
membuff_add_fstring(&fn->body, "i_%d += 1;\n", A);
|
|
|
|
@ -1075,6 +1069,7 @@ static void emit_op_iforloop(struct function *fn, int A, int pc, int step_one,
|
|
|
|
|
|
|
|
|
|
static void emit_op_iforprep(struct function *fn, int A, int pc, int step_one,
|
|
|
|
|
int pc1) {
|
|
|
|
|
(void)pc1;
|
|
|
|
|
if (!fn->locals[A]) {
|
|
|
|
|
fn->locals[A] =
|
|
|
|
|
1; // Lua can reuse the same forloop vars if loop isn't nested
|
|
|
|
@ -1150,6 +1145,7 @@ static void initfn(struct function *fn, struct lua_State *L, struct Proto *p, co
|
|
|
|
|
// so we need to take care of the behaviour differences between
|
|
|
|
|
// OP_CALL and external calls
|
|
|
|
|
static void emit_op_call(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
int nresults = C - 1;
|
|
|
|
|
if (B != 0) { membuff_add_fstring(&fn->body, "L->top = R(%d);\n", A + B); }
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
@ -1168,6 +1164,7 @@ static void emit_op_call(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
|
|
|
|
|
// R(A) := UpValue[B][RK(C)]
|
|
|
|
|
static void emit_op_gettabup(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
|
membuff_add_fstring(&fn->body,
|
|
|
|
@ -1177,6 +1174,7 @@ static void emit_op_gettabup(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
|
|
|
|
|
// R(A) := UpValue[B][RK(C)]
|
|
|
|
|
static void emit_op_settabup(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg_or_k(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
|
membuff_add_fstring(&fn->body,
|
|
|
|
@ -1186,6 +1184,7 @@ static void emit_op_settabup(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
|
|
|
|
|
// R(A) := R(B)[RK(C)]
|
|
|
|
|
static void emit_op_gettable(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -1194,6 +1193,7 @@ static void emit_op_gettable(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_self(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
membuff_add_string(&fn->body, "setobjs2s(L, ra + 1, rb);\n");
|
|
|
|
@ -1203,6 +1203,7 @@ static void emit_op_self(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_len(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
membuff_add_string(&fn->body, "luaV_objlen(L, ra, rb);\n");
|
|
|
|
@ -1211,6 +1212,7 @@ static void emit_op_len(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
|
|
|
|
|
// R(A)[RK(B)] := RK(C)
|
|
|
|
|
static void emit_op_settable(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg_or_k(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -1220,22 +1222,26 @@ static void emit_op_settable(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
|
|
|
|
|
// R(A) := UpValue[B]
|
|
|
|
|
static void emit_op_getupval(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_fstring(&fn->body, "setobjs2s(L, ra, cl->upvals[%d]->v);\n", B);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_newtable(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_fstring(&fn->body, "raviV_op_newtable(L, ci, ra, %d, %d);\n", B,
|
|
|
|
|
C);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_newarrayint(struct function *fn, int A, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "raviV_op_newarrayint(L, ci, ra);\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_newarrayfloat(struct function *fn, int A, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "raviV_op_newarrayfloat(L, ci, ra);\n");
|
|
|
|
|
}
|
|
|
|
@ -1243,6 +1249,7 @@ static void emit_op_newarrayfloat(struct function *fn, int A, int pc) {
|
|
|
|
|
// Default implementation for binary ops
|
|
|
|
|
static void emit_binary_op(struct function *fn, int A, int B, int C, OpCode op,
|
|
|
|
|
int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg_or_k(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -1253,6 +1260,7 @@ static void emit_binary_op(struct function *fn, int A, int B, int C, OpCode op,
|
|
|
|
|
|
|
|
|
|
void emit_ff_op(struct function *fn, int A, int B, int C, int pc,
|
|
|
|
|
const char *op) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg_or_k(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -1262,6 +1270,7 @@ void emit_ff_op(struct function *fn, int A, int B, int C, int pc,
|
|
|
|
|
|
|
|
|
|
static void emit_fi_op(struct function *fn, int A, int B, int C, int pc,
|
|
|
|
|
const char *op) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg_or_k(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -1271,6 +1280,7 @@ static void emit_fi_op(struct function *fn, int A, int B, int C, int pc,
|
|
|
|
|
|
|
|
|
|
static void emit_if_op(struct function *fn, int A, int B, int C, int pc,
|
|
|
|
|
const char *op) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg_or_k(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -1280,6 +1290,7 @@ static void emit_if_op(struct function *fn, int A, int B, int C, int pc,
|
|
|
|
|
|
|
|
|
|
static void emit_ii_op(struct function *fn, int A, int B, int C, int pc,
|
|
|
|
|
const char *op) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg_or_k(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -1288,6 +1299,7 @@ static void emit_ii_op(struct function *fn, int A, int B, int C, int pc,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_divii(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg_or_k(fn, "rb", B);
|
|
|
|
|
emit_reg_or_k(fn, "rc", C);
|
|
|
|
@ -1297,15 +1309,18 @@ static void emit_op_divii(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_loadfz(struct function *fn, int A, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "setfltvalue(ra, 0.0);\n");
|
|
|
|
|
}
|
|
|
|
|
static void emit_op_loadiz(struct function *fn, int A, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "setivalue(ra, 0);\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_movei(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
membuff_add_string(&fn->body, "i = 0;\n");
|
|
|
|
@ -1319,6 +1334,7 @@ static void emit_op_movei(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_movef(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
membuff_add_string(&fn->body, "n = 0.0;\n");
|
|
|
|
@ -1331,6 +1347,7 @@ static void emit_op_movef(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_moveai(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
membuff_add_string(&fn->body,
|
|
|
|
@ -1343,6 +1360,7 @@ static void emit_op_moveai(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_moveaf(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
membuff_add_string(&fn->body,
|
|
|
|
@ -1355,6 +1373,7 @@ static void emit_op_moveaf(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_movetab(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
membuff_add_string(&fn->body,
|
|
|
|
@ -1366,6 +1385,7 @@ static void emit_op_movetab(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_toint(struct function *fn, int A, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "i = 0;\n");
|
|
|
|
|
membuff_add_string(&fn->body,
|
|
|
|
@ -1378,6 +1398,7 @@ static void emit_op_toint(struct function *fn, int A, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_toflt(struct function *fn, int A, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "n = 0.0;\n");
|
|
|
|
|
membuff_add_string(&fn->body,
|
|
|
|
@ -1389,6 +1410,7 @@ static void emit_op_toflt(struct function *fn, int A, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_toai(struct function *fn, int A, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "if (!ttisiarray(ra)) {\n");
|
|
|
|
|
membuff_add_fstring(&fn->body, " error_code = %d;\n",
|
|
|
|
@ -1398,6 +1420,7 @@ static void emit_op_toai(struct function *fn, int A, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_toaf(struct function *fn, int A, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "if (!ttisfarray(ra)) {\n");
|
|
|
|
|
membuff_add_fstring(&fn->body, " error_code = %d;\n",
|
|
|
|
@ -1407,6 +1430,7 @@ static void emit_op_toaf(struct function *fn, int A, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_totab(struct function *fn, int A, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "if (!ttisLtable(ra)) {\n");
|
|
|
|
|
membuff_add_fstring(&fn->body, " error_code = %d;\n", Error_table_expected);
|
|
|
|
@ -1415,26 +1439,31 @@ static void emit_op_totab(struct function *fn, int A, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_setlist(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_fstring(&fn->body, "raviV_op_setlist(L, ci, ra, %d, %d);\n", B,
|
|
|
|
|
C);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_concat(struct function *fn, int A, int B, int C, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
membuff_add_fstring(&fn->body, "raviV_op_concat(L, ci, %d, %d, %d);\n", A, B,
|
|
|
|
|
C);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_closure(struct function *fn, int A, int Bx, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
membuff_add_fstring(&fn->body, "raviV_op_closure(L, ci, cl, %d, %d);\n", A,
|
|
|
|
|
Bx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_vararg(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
membuff_add_fstring(&fn->body, "raviV_op_vararg(L, ci, cl, %d, %d);\n", A, B);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_not(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
emit_reg(fn, "rb", B);
|
|
|
|
|
membuff_add_string(&fn->body, "result = l_isfalse(rb);\n");
|
|
|
|
@ -1442,12 +1471,14 @@ static void emit_op_not(struct function *fn, int A, int B, int pc) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void emit_op_setupval(struct function *fn, int A, int B, int pc, const char *suffix) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_fstring(&fn->body, "raviV_op_setupval%s(L, cl, ra, %d);\n", suffix, B);
|
|
|
|
|
}
|
|
|
|
|
static void emit_op_forprep(struct function *fn, int A, int pc,
|
|
|
|
|
int pc1)
|
|
|
|
|
{
|
|
|
|
|
(void)pc1;
|
|
|
|
|
if (!fn->locals[A]) {
|
|
|
|
|
fn->locals[A] =
|
|
|
|
|
1; // Lua can reuse the same forloop vars if loop isn't nested
|
|
|
|
@ -1488,6 +1519,7 @@ static void emit_op_forprep(struct function *fn, int A, int pc,
|
|
|
|
|
|
|
|
|
|
static void emit_op_forloop(struct function *fn, int A, int pc,
|
|
|
|
|
int pc1) {
|
|
|
|
|
(void)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);
|
|
|
|
@ -1504,6 +1536,8 @@ static void emit_op_forloop(struct function *fn, int A, int pc,
|
|
|
|
|
|
|
|
|
|
static void emit_op_tforcall(struct function *fn, int A, int B, int C,
|
|
|
|
|
int j, int jA, int pc) {
|
|
|
|
|
(void)B;
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "rb = ra + 3 + 2;\n"); /*rb = cb*/
|
|
|
|
|
membuff_add_string(&fn->body, "rc = ra + 2;\n"); /*rb = cb*/
|
|
|
|
@ -1527,6 +1561,7 @@ static void emit_op_tforcall(struct function *fn, int A, int B, int C,
|
|
|
|
|
|
|
|
|
|
static void emit_op_tforloop(struct function *fn, int A, int j,
|
|
|
|
|
int pc) {
|
|
|
|
|
(void)pc;
|
|
|
|
|
emit_reg(fn, "ra", A);
|
|
|
|
|
membuff_add_string(&fn->body, "if (!ttisnil(ra + 1)) {\n");
|
|
|
|
|
membuff_add_string(&fn->body, " rb = ra + 1;\n");
|
|
|
|
@ -1545,7 +1580,7 @@ static void cleanup(struct function *fn) {
|
|
|
|
|
// Compile a Lua function
|
|
|
|
|
// Returns true if compilation was successful
|
|
|
|
|
bool raviJ_codegen(struct lua_State *L, struct Proto *p,
|
|
|
|
|
ravi_compile_options_t *options, const char *fname, membuff_t *buf) {
|
|
|
|
|
struct ravi_compile_options_t *options, const char *fname, membuff_t *buf) {
|
|
|
|
|
|
|
|
|
|
if (options->codegen_type == RAVI_CODEGEN_HEADER_ONLY) {
|
|
|
|
|
membuff_rewindpos(buf);
|
|
|
|
|