move all codegen stuff, make instruction vector private

master
Daniel Kolesa 2021-04-10 02:56:49 +02:00
parent 05661662d2
commit d2b53b174e
3 changed files with 107 additions and 68 deletions

View File

@ -20,6 +20,10 @@ std::size_t gen_state::count() const {
return code.size();
}
std::uint32_t gen_state::peek(std::size_t idx) const {
return code[idx];
}
bcode_ref gen_state::steal_ref() {
auto *cp = bcode_alloc(ts.istate, code.size());
std::memcpy(cp, code.data(), code.size() * sizeof(std::uint32_t));
@ -50,6 +54,71 @@ void gen_state::gen_not(int ltype) {
code.push_back(BC_INST_NOT | ret_code(ltype));
}
bool gen_state::gen_if(std::size_t tpos, std::size_t fpos, int ltype) {
auto inst1 = code[tpos];
auto op1 = inst1 & ~BC_INST_RET_MASK;
auto tlen = std::uint32_t(fpos - tpos - 1);
if (!fpos) {
if (is_block(tpos, fpos)) {
code[tpos] = (tlen << 8) | BC_INST_JUMP_B | BC_INST_FLAG_FALSE;
code[tpos + 1] = BC_INST_ENTER_RESULT;
code[tpos + tlen] = (
code[tpos + tlen] & ~BC_INST_RET_MASK
) | ret_code(ltype);
return true;
}
gen_block();
} else {
auto inst2 = code[fpos];
auto flen = std::uint32_t(count() - fpos - 1);
if (is_block(fpos)) {
if (is_block(tpos, fpos)) {
code[tpos] = (std::uint32_t(fpos - tpos) << 8)
| BC_INST_JUMP_B | BC_INST_FLAG_FALSE;
code[tpos + 1] = BC_INST_ENTER_RESULT;
code[tpos + tlen] = (
code[tpos + tlen] & ~BC_INST_RET_MASK
) | ret_code(ltype);
code[fpos] = (flen << 8) | BC_INST_JUMP;
code[fpos + 1] = BC_INST_ENTER_RESULT;
code[fpos + flen] = (
code[fpos + flen] & ~BC_INST_RET_MASK
) | ret_code(ltype);
return true;
} else if (op1 == BC_INST_EMPTY) {
code[tpos] = BC_INST_NULL | (inst2 & BC_INST_RET_MASK);
code[fpos] = (flen << 8) | BC_INST_JUMP_B | BC_INST_FLAG_TRUE;
code[fpos + 1] = BC_INST_ENTER_RESULT;
code[fpos + flen] = (
code[fpos + flen] & ~BC_INST_RET_MASK
) | ret_code(ltype);
return true;
}
}
}
return false;
}
void gen_state::gen_and_or(bool is_or, std::size_t start, int ltype) {
std::uint32_t op;
if (is_or) {
op = (BC_INST_JUMP_RESULT | BC_INST_FLAG_TRUE);
} else {
op = (BC_INST_JUMP_RESULT | BC_INST_FLAG_FALSE);
}
code.push_back(op);
std::size_t end = count();
while ((start + 1) < end) {
uint32_t len = code[start] >> 8;
code[start] = std::uint32_t((end - start - 1) << 8) | op;
code[start + 1] = BC_INST_ENTER;
code[start + len] = (
code[start + len] & ~BC_INST_RET_MASK
) | ret_code(ltype);
start += len + 1;
}
}
void gen_state::gen_val_null() {
code.push_back(BC_INST_VAL_INT | BC_RET_NULL);
}
@ -392,6 +461,15 @@ void gen_state::gen_main_float(float_type v) {
code.push_back(BC_INST_EXIT);
}
bool gen_state::is_block(std::size_t idx, std::size_t epos) const {
if (!epos) {
epos = count();
}
return ((code[idx] & ~BC_INST_RET_MASK) == (
BC_INST_BLOCK | (std::uint32_t(epos - idx - 1) << 8)
));
}
void gen_state::gen_block() {
code.push_back(BC_INST_EMPTY);
}

View File

@ -15,7 +15,6 @@ namespace cubescript {
struct gen_state {
thread_state &ts;
valbuf<std::uint32_t> code;
gen_state() = delete;
gen_state(thread_state &tsr):
@ -23,6 +22,7 @@ struct gen_state {
{}
std::size_t count() const;
std::uint32_t peek(std::size_t idx) const;
bcode_ref steal_ref();
@ -33,6 +33,8 @@ struct gen_state {
void gen_force(int ltype);
void gen_not(int ltype = 0);
bool gen_if(std::size_t tpos, std::size_t fpos, int ltype = 0);
void gen_and_or(bool is_or, std::size_t start, int ltype = 0);
void gen_val_null();
void gen_result_null(int ltype = 0);
@ -92,11 +94,16 @@ struct gen_state {
void gen_main_integer(integer_type v);
void gen_main_float(float_type v);
bool is_block(std::size_t idx, std::size_t epos = 0) const;
void gen_block();
std::pair<std::size_t, std::string_view> gen_block(
std::string_view v, std::size_t line,
int ret_type = BC_RET_NULL, int term = '\0'
);
private:
valbuf<std::uint32_t> code;
};
} /* namespace cubescript */

View File

@ -1137,62 +1137,28 @@ static void compile_if(
parser_state &gs, ident *id, bool &more, int rettype
) {
if (more) {
/* condition */
more = compilearg(gs, VAL_ANY);
}
if (!more) {
/* no condition: expr is nothing */
gs.gs.gen_result_null(rettype);
} else {
std::size_t start1 = gs.gs.code.size();
auto tpos = gs.gs.count();
/* true block */
more = compilearg(gs, VAL_CODE);
if (!more) {
/* we only had condition: expr is nothing */
gs.gs.gen_pop();
gs.gs.gen_result_null(rettype);
} else {
std::size_t start2 = gs.gs.code.size();
auto fpos = gs.gs.count();
/* false block */
more = compilearg(gs, VAL_CODE);
std::uint32_t inst1 = gs.gs.code[start1];
std::uint32_t op1 = inst1 & ~BC_INST_RET_MASK;
auto len1 = std::uint32_t(start2 - (start1 + 1));
if (!more) {
if (op1 == (BC_INST_BLOCK | (len1 << 8))) {
gs.gs.code[start1] = (len1 << 8) | BC_INST_JUMP_B | BC_INST_FLAG_FALSE;
gs.gs.code[start1 + 1] = BC_INST_ENTER_RESULT;
gs.gs.code[start1 + len1] = (
gs.gs.code[start1 + len1] & ~BC_INST_RET_MASK
) | ret_code(rettype);
return;
}
gs.gs.gen_block();
} else {
std::uint32_t inst2 = gs.gs.code[start2];
std::uint32_t op2 = inst2 & ~BC_INST_RET_MASK;
auto len2 = std::uint32_t(gs.gs.code.size() - (start2 + 1));
if (op2 == (BC_INST_BLOCK | (len2 << 8))) {
if (op1 == (BC_INST_BLOCK | (len1 << 8))) {
gs.gs.code[start1] = (std::uint32_t(start2 - start1) << 8)
| BC_INST_JUMP_B | BC_INST_FLAG_FALSE;
gs.gs.code[start1 + 1] = BC_INST_ENTER_RESULT;
gs.gs.code[start1 + len1] = (
gs.gs.code[start1 + len1] & ~BC_INST_RET_MASK
) | ret_code(rettype);
gs.gs.code[start2] = (len2 << 8) | BC_INST_JUMP;
gs.gs.code[start2 + 1] = BC_INST_ENTER_RESULT;
gs.gs.code[start2 + len2] = (
gs.gs.code[start2 + len2] & ~BC_INST_RET_MASK
) | ret_code(rettype);
return;
} else if (op1 == (BC_INST_EMPTY | (len1 << 8))) {
gs.gs.code[start1] = BC_INST_NULL | (inst2 & BC_INST_RET_MASK);
gs.gs.code[start2] = (len2 << 8) | BC_INST_JUMP_B | BC_INST_FLAG_TRUE;
gs.gs.code[start2 + 1] = BC_INST_ENTER_RESULT;
gs.gs.code[start2 + len2] = (
gs.gs.code[start2 + len2] & ~BC_INST_RET_MASK
) | ret_code(rettype);
return;
}
}
if (!gs.gs.gen_if(tpos, more ? fpos : 0)) {
/* can't fully compile: use a call */
gs.gs.gen_command_call(*id, BC_INST_COM, rettype);
}
gs.gs.code.push_back(BC_INST_COM | ret_code(rettype) | (id->get_index() << 8));
}
}
}
@ -1202,9 +1168,11 @@ static void compile_and_or(
) {
std::uint32_t numargs = 0;
if (more) {
/* first */
more = compilearg(gs, VAL_COND);
}
if (!more) {
/* no first: generate true or false */
if (ident_p{*id}.impl().p_type == ID_AND) {
gs.gs.gen_result_true(rettype);
} else {
@ -1212,47 +1180,33 @@ static void compile_and_or(
}
} else {
numargs++;
std::size_t start = gs.gs.code.size(), end = start;
std::size_t start = gs.gs.count(), end = start;
for (;;) {
/* keep going as long as we only get blocks */
more = compilearg(gs, VAL_COND);
if (!more) {
break;
}
numargs++;
if ((gs.gs.code[end] & ~BC_INST_RET_MASK) != (
BC_INST_BLOCK | (uint32_t(gs.gs.code.size() - (end + 1)) << 8)
)) {
if (!gs.gs.is_block(end)) {
break;
}
end = gs.gs.code.size();
end = gs.gs.count();
}
if (more) {
/* last parsed thing was not a block, fall back to call */
for (;;) {
/* but first, parse out the remainder of values */
more = compilearg(gs, VAL_COND);
if (!more) {
break;
}
numargs++;
}
gs.gs.code.push_back(
BC_INST_COM_V | ret_code(rettype) | (id->get_index() << 8)
);
gs.gs.code.push_back(numargs);
gs.gs.gen_command_call(*id, BC_INST_COM_V, rettype, numargs);
} else {
std::uint32_t op = (ident_p{*id}.impl().p_type == ID_AND)
? (BC_INST_JUMP_RESULT | BC_INST_FLAG_FALSE)
: (BC_INST_JUMP_RESULT | BC_INST_FLAG_TRUE);
gs.gs.code.push_back(op);
end = gs.gs.code.size();
while ((start + 1) < end) {
uint32_t len = gs.gs.code[start] >> 8;
gs.gs.code[start] = std::uint32_t((end - (start + 1)) << 8) | op;
gs.gs.code[start + 1] = BC_INST_ENTER;
gs.gs.code[start + len] = (
gs.gs.code[start + len] & ~BC_INST_RET_MASK
) | ret_code(rettype);
start += len + 1;
}
/* all blocks and nothing left */
gs.gs.gen_and_or((ident_p{*id}.impl().p_type != ID_AND), start);
}
}
}