move some more codegen into proper place

master
Daniel Kolesa 2021-04-10 00:40:57 +02:00
parent 295c905c32
commit 1bc94bf5af
4 changed files with 130 additions and 67 deletions

View File

@ -135,10 +135,10 @@ enum {
*/ */
BC_INST_LOOKUP_U, BC_INST_LOOKUP_U,
/* concatenate D values on top of the stack together, with topmost value /* concatenate D values on top of the stack together, with topmost value
* being last; push the result according to M * being last; delimit with spaces; push the result according to M
*/ */
BC_INST_CONC, BC_INST_CONC,
/* like above but delimit with spaces */ /* like above but without delimiter */
BC_INST_CONC_W, BC_INST_CONC_W,
/* push the value of svar with index D on the stack according to M */ /* push the value of svar with index D on the stack according to M */
BC_INST_SVAR, BC_INST_SVAR,

View File

@ -9,6 +9,17 @@
namespace cubescript { namespace cubescript {
static inline int ret_code(int type, int def = 0) {
if (type >= VAL_ANY) {
return def;
}
return type << BC_INST_RET;
}
std::size_t gen_state::count() const {
return code.size();
}
bcode_ref gen_state::steal_ref() { bcode_ref gen_state::steal_ref() {
auto *cp = bcode_alloc(ts.istate, code.size()); auto *cp = bcode_alloc(ts.istate, code.size());
std::memcpy(cp, code.data(), code.size() * sizeof(std::uint32_t)); std::memcpy(cp, code.data(), code.size() * sizeof(std::uint32_t));
@ -19,10 +30,34 @@ void gen_state::gen_pop() {
code.push_back(BC_INST_POP); code.push_back(BC_INST_POP);
} }
void gen_state::gen_dup(int ltype) {
code.push_back(BC_INST_DUP | ret_code(ltype));
}
void gen_state::gen_push_result(int ltype) {
code.push_back(BC_INST_RESULT_ARG | ret_code(ltype));
}
void gen_state::gen_force(int ltype) {
code.push_back(BC_INST_FORCE | ret_code(ltype, BC_RET_STRING));
}
void gen_state::gen_val_null() { void gen_state::gen_val_null() {
code.push_back(BC_INST_VAL_INT | BC_RET_NULL); code.push_back(BC_INST_VAL_INT | BC_RET_NULL);
} }
void gen_state::gen_result_null(int ltype) {
code.push_back(BC_INST_NULL | ret_code(ltype));
}
void gen_state::gen_result_true(int ltype) {
code.push_back(BC_INST_TRUE | ret_code(ltype));
}
void gen_state::gen_result_false(int ltype) {
code.push_back(BC_INST_FALSE | ret_code(ltype));
}
void gen_state::gen_val_integer(integer_type v) { void gen_state::gen_val_integer(integer_type v) {
if (v >= -0x800000 && v <= 0x7FFFFF) { if (v >= -0x800000 && v <= 0x7FFFFF) {
code.push_back(BC_INST_VAL_INT | BC_RET_INT | (v << 8)); code.push_back(BC_INST_VAL_INT | BC_RET_INT | (v << 8));
@ -218,13 +253,6 @@ void gen_state::gen_val(
} }
} }
static inline int ret_code(int type, int def = 0) {
if (type >= VAL_ANY) {
return def;
}
return type << BC_INST_RET;
}
void gen_state::gen_lookup_ivar(ident &id, int ltype) { void gen_state::gen_lookup_ivar(ident &id, int ltype) {
code.push_back( code.push_back(
BC_INST_IVAR | ret_code(ltype, BC_RET_INT) | (id.get_index() << 8) BC_INST_IVAR | ret_code(ltype, BC_RET_INT) | (id.get_index() << 8)
@ -245,7 +273,7 @@ void gen_state::gen_lookup_svar(ident &id, int ltype) {
void gen_state::gen_lookup_alias(ident &id, int ltype, int dtype) { void gen_state::gen_lookup_alias(ident &id, int ltype, int dtype) {
code.push_back( code.push_back(
BC_INST_LOOKUP | ret_code(ltype, dtype) | (id.get_index() << 8) BC_INST_LOOKUP | ret_code(ltype, ret_code(dtype)) | (id.get_index() << 8)
); );
} }
@ -265,6 +293,39 @@ void gen_state::gen_ident_lookup() {
code.push_back(BC_INST_IDENT_U); code.push_back(BC_INST_IDENT_U);
} }
void gen_state::gen_concat(std::size_t concs, bool space, int ltype) {
if (!concs) {
return;
}
if (space) {
code.push_back(BC_INST_CONC | ret_code(ltype) | (concs << 8));
} else {
code.push_back(BC_INST_CONC_W | ret_code(ltype) | (concs << 8));
}
}
void gen_state::gen_command_call(
ident &id, int comt, int ltype, std::uint32_t nargs
) {
code.push_back(comt | ret_code(ltype) | (id.get_index() << 8));
if (comt != BC_INST_COM) {
code.push_back(nargs);
}
}
void gen_state::gen_alias_call(ident &id, std::uint32_t nargs) {
code.push_back(BC_INST_CALL | (id.get_index() << 8));
code.push_back(nargs);
}
void gen_state::gen_call(std::uint32_t nargs) {
code.push_back(BC_INST_CALL_U | (nargs << 8));
}
void gen_state::gen_local(std::uint32_t nargs) {
code.push_back(BC_INST_LOCAL | (nargs << 8));
}
void gen_state::gen_main_null() { void gen_state::gen_main_null() {
code.reserve(code.size() + 4); code.reserve(code.size() + 4);
code.push_back(BC_INST_START); code.push_back(BC_INST_START);

View File

@ -22,11 +22,19 @@ struct gen_state {
ts{tsr}, code{tsr.istate} ts{tsr}, code{tsr.istate}
{} {}
std::size_t count() const;
bcode_ref steal_ref(); bcode_ref steal_ref();
void gen_pop(); void gen_pop();
void gen_dup(int ltype = 0);
void gen_push_result(int ltype = 0);
void gen_force(int ltype);
void gen_val_null(); void gen_val_null();
void gen_result_null(int ltype = 0);
void gen_result_true(int ltype = 0);
void gen_result_false(int ltype = 0);
void gen_val_integer(integer_type v = 0); void gen_val_integer(integer_type v = 0);
void gen_val_integer(std::string_view v); void gen_val_integer(std::string_view v);
@ -57,6 +65,16 @@ struct gen_state {
void gen_compile(bool cond = false); void gen_compile(bool cond = false);
void gen_ident_lookup(); void gen_ident_lookup();
void gen_concat(std::size_t concs, bool space, int ltype = 0);
void gen_command_call(
ident &id, int comt, int ltype = 0, std::uint32_t nargs = 0
);
void gen_alias_call(ident &id, std::uint32_t nargs = 0);
void gen_call(std::uint32_t nargs = 0);
void gen_local(std::uint32_t nargs);
void gen_main_null(); void gen_main_null();
void gen_main_integer(integer_type v); void gen_main_integer(integer_type v);
void gen_main_float(float_type v); void gen_main_float(float_type v);

View File

@ -479,7 +479,7 @@ lookupid:
gs.gs.gen_lookup_alias(id); gs.gs.gen_lookup_alias(id);
break; break;
default: default:
gs.gs.gen_lookup_alias(id, ltype, BC_RET_STRING); gs.gs.gen_lookup_alias(id, ltype, VAL_STRING);
break; break;
} }
goto done; goto done;
@ -505,7 +505,7 @@ lookupid:
numargs++; numargs++;
break; break;
case 'F': case 'F':
gs.gs.code.push_back(BC_INST_DUP | BC_RET_FLOAT); gs.gs.gen_dup(VAL_FLOAT);
numargs++; numargs++;
break; break;
case 'E': case 'E':
@ -531,10 +531,10 @@ lookupid:
break; break;
case 'C': case 'C':
comtype = BC_INST_COM_C; comtype = BC_INST_COM_C;
goto compilecomv; break;
case 'V': case 'V':
comtype = BC_INST_COM_V; comtype = BC_INST_COM_V;
goto compilecomv; break;
case '1': case '1':
case '2': case '2':
case '3': case '3':
@ -542,21 +542,8 @@ lookupid:
break; break;
} }
} }
gs.gs.code.push_back( gs.gs.gen_command_call(id, comtype, ltype, numargs);
comtype | ret_code(ltype) | (id.get_index() << 8) gs.gs.gen_push_result(ltype);
);
gs.gs.code.push_back(
BC_INST_RESULT_ARG | ret_code(ltype)
);
goto done;
compilecomv:
gs.gs.code.push_back(
comtype | ret_code(ltype) | (id.get_index() << 8)
);
gs.gs.code.push_back(numargs);
gs.gs.code.push_back(
BC_INST_RESULT_ARG | ret_code(ltype)
);
goto done; goto done;
} }
default: default:
@ -741,9 +728,7 @@ static void compileblockmain(parser_state &gs, int wordtype) {
concs++; concs++;
} }
} }
if (concs) { gs.gs.gen_concat(concs, false, wordtype);
gs.gs.code.push_back(BC_INST_CONC_W | ret_code(wordtype) | (concs << 8));
}
switch (wordtype) { switch (wordtype) {
case VAL_POP: case VAL_POP:
if (concs || gs.source - 1 > start) { if (concs || gs.source - 1 > start) {
@ -784,7 +769,7 @@ static void compileblockmain(parser_state &gs, int wordtype) {
if (gs.source - 1 <= start) { if (gs.source - 1 <= start) {
gs.gs.gen_val(wordtype); gs.gs.gen_val(wordtype);
} else { } else {
gs.gs.code.push_back(BC_INST_FORCE | (wordtype << BC_INST_RET)); gs.gs.gen_force(wordtype);
} }
} }
break; break;
@ -841,10 +826,10 @@ static bool compilearg(
return true; return true;
case '(': { case '(': {
gs.next_char(); gs.next_char();
std::size_t start = gs.gs.code.size(); auto start = gs.gs.count();
gs.parse_block(VAL_ANY, ')'); gs.parse_block(VAL_ANY, ')');
if (gs.gs.code.size() > start) { if (gs.gs.count() > start) {
gs.gs.code.push_back(BC_INST_RESULT_ARG | ret_code(wordtype)); gs.gs.gen_push_result(wordtype);
} else { } else {
gs.gs.gen_val(wordtype); gs.gs.gen_val(wordtype);
return true; return true;
@ -942,7 +927,7 @@ static void compile_cmd(
numconc++; numconc++;
} }
if (numconc > 1) { if (numconc > 1) {
gs.gs.code.push_back(BC_INST_CONC | BC_RET_STRING | (numconc << 8)); gs.gs.gen_concat(numconc, true, VAL_STRING);
} }
} }
numargs++; numargs++;
@ -998,7 +983,7 @@ static void compile_cmd(
if (rep) { if (rep) {
break; break;
} }
gs.gs.code.push_back(BC_INST_DUP | BC_RET_FLOAT); gs.gs.gen_dup(VAL_FLOAT);
fakeargs++; fakeargs++;
} }
numargs++; numargs++;
@ -1080,7 +1065,7 @@ static void compile_cmd(
numcargs++; numcargs++;
} }
} }
goto compilecomv; break;
case 'V': /* varargs */ case 'V': /* varargs */
comtype = BC_INST_COM_V; comtype = BC_INST_COM_V;
if (more && (!limit || (numcargs < limit))) { if (more && (!limit || (numcargs < limit))) {
@ -1093,7 +1078,7 @@ static void compile_cmd(
numcargs++; numcargs++;
} }
} }
goto compilecomv; break;
case '1': /* vararg repetition */ case '1': /* vararg repetition */
case '2': case '2':
case '3': case '3':
@ -1106,13 +1091,7 @@ static void compile_cmd(
break; break;
} }
} }
gs.gs.code.push_back(comtype | ret_code(rettype) | (id->get_index() << 8)); gs.gs.gen_command_call(*id, comtype, rettype, numargs);
return;
compilecomv:
gs.gs.code.push_back(
comtype | ret_code(rettype) | (id->get_index() << 8)
);
gs.gs.code.push_back(numargs);
} }
static void compile_alias(parser_state &gs, alias *id, bool &more) { static void compile_alias(parser_state &gs, alias *id, bool &more) {
@ -1124,10 +1103,7 @@ static void compile_alias(parser_state &gs, alias *id, bool &more) {
} }
++numargs; ++numargs;
} }
gs.gs.code.push_back( gs.gs.gen_alias_call(*id, numargs);
BC_INST_CALL | (id->get_index() << 8)
);
gs.gs.code.push_back(numargs);
} }
static void compile_local(parser_state &gs, bool &more) { static void compile_local(parser_state &gs, bool &more) {
@ -1141,7 +1117,7 @@ static void compile_local(parser_state &gs, bool &more) {
numargs++; numargs++;
} }
} }
gs.gs.code.push_back(BC_INST_LOCAL | (numargs << 8)); gs.gs.gen_local(numargs);
} }
static void compile_do( static void compile_do(
@ -1150,7 +1126,11 @@ static void compile_do(
if (more) { if (more) {
more = compilearg(gs, VAL_CODE); more = compilearg(gs, VAL_CODE);
} }
gs.gs.code.push_back((more ? opcode : BC_INST_NULL) | ret_code(rettype)); if (!more) {
gs.gs.gen_result_null(rettype);
} else {
gs.gs.code.push_back(opcode | ret_code(rettype));
}
} }
static void compile_if( static void compile_if(
@ -1160,13 +1140,13 @@ static void compile_if(
more = compilearg(gs, VAL_ANY); more = compilearg(gs, VAL_ANY);
} }
if (!more) { if (!more) {
gs.gs.code.push_back(BC_INST_NULL | ret_code(rettype)); gs.gs.gen_result_null(rettype);
} else { } else {
std::size_t start1 = gs.gs.code.size(); std::size_t start1 = gs.gs.code.size();
more = compilearg(gs, VAL_CODE); more = compilearg(gs, VAL_CODE);
if (!more) { if (!more) {
gs.gs.gen_pop(); gs.gs.gen_pop();
gs.gs.code.push_back(BC_INST_NULL | ret_code(rettype)); gs.gs.gen_result_null(rettype);
} else { } else {
std::size_t start2 = gs.gs.code.size(); std::size_t start2 = gs.gs.code.size();
more = compilearg(gs, VAL_CODE); more = compilearg(gs, VAL_CODE);
@ -1225,10 +1205,11 @@ static void compile_and_or(
more = compilearg(gs, VAL_COND); more = compilearg(gs, VAL_COND);
} }
if (!more) { if (!more) {
gs.gs.code.push_back( if (ident_p{*id}.impl().p_type == ID_AND) {
((ident_p{*id}.impl().p_type == ID_AND) gs.gs.gen_result_true(rettype);
? BC_INST_TRUE : BC_INST_FALSE) | ret_code(rettype) } else {
); gs.gs.gen_result_false(rettype);
}
} else { } else {
numargs++; numargs++;
std::size_t start = gs.gs.code.size(), end = start; std::size_t start = gs.gs.code.size(), end = start;
@ -1363,7 +1344,7 @@ noid:
} }
++numargs; ++numargs;
} }
gs.code.push_back(BC_INST_CALL_U | (numargs << 8)); gs.gen_call(numargs);
} else { } else {
idname.push_back('\0'); idname.push_back('\0');
ident *id = ts.pstate->get_ident(idname.str_term()); ident *id = ts.pstate->get_ident(idname.str_term());
@ -1423,18 +1404,21 @@ noid:
if (more) { if (more) {
more = compilearg(*this, VAL_ANY); more = compilearg(*this, VAL_ANY);
} }
gs.code.push_back( if (!more) {
(more ? BC_INST_RESULT : BC_INST_NULL) | gs.gen_result_null(rettype);
ret_code(rettype) } else {
); gs.code.push_back(BC_INST_RESULT | ret_code(rettype));
}
break; break;
case ID_NOT: case ID_NOT:
if (more) { if (more) {
more = compilearg(*this, VAL_ANY); more = compilearg(*this, VAL_ANY);
} }
gs.code.push_back( if (!more) {
(more ? BC_INST_NOT : BC_INST_TRUE) | ret_code(rettype) gs.gen_result_true(rettype);
); } else {
gs.code.push_back(BC_INST_NOT | ret_code(rettype));
}
break; break;
case ID_AND: case ID_AND:
case ID_OR: case ID_OR: