separate bytecode bits into its own file
parent
63251f0eac
commit
3d2f115de5
|
@ -0,0 +1,113 @@
|
||||||
|
#include "cs_bcode.hh"
|
||||||
|
|
||||||
|
#include "cs_util.hh"
|
||||||
|
|
||||||
|
namespace cscript {
|
||||||
|
|
||||||
|
/* public API impls */
|
||||||
|
|
||||||
|
LIBCUBESCRIPT_EXPORT cs_bcode_ref::cs_bcode_ref(cs_bcode *v): p_code(v) {
|
||||||
|
bcode_ref(reinterpret_cast<std::uint32_t *>(p_code));
|
||||||
|
}
|
||||||
|
LIBCUBESCRIPT_EXPORT cs_bcode_ref::cs_bcode_ref(cs_bcode_ref const &v):
|
||||||
|
p_code(v.p_code)
|
||||||
|
{
|
||||||
|
bcode_ref(reinterpret_cast<std::uint32_t *>(p_code));
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBCUBESCRIPT_EXPORT cs_bcode_ref::~cs_bcode_ref() {
|
||||||
|
bcode_unref(reinterpret_cast<std::uint32_t *>(p_code));
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBCUBESCRIPT_EXPORT cs_bcode_ref &cs_bcode_ref::operator=(
|
||||||
|
cs_bcode_ref const &v
|
||||||
|
) {
|
||||||
|
bcode_unref(reinterpret_cast<std::uint32_t *>(p_code));
|
||||||
|
p_code = v.p_code;
|
||||||
|
bcode_ref(reinterpret_cast<std::uint32_t *>(p_code));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
LIBCUBESCRIPT_EXPORT cs_bcode_ref &cs_bcode_ref::operator=(cs_bcode_ref &&v) {
|
||||||
|
bcode_unref(reinterpret_cast<std::uint32_t *>(p_code));
|
||||||
|
p_code = v.p_code;
|
||||||
|
v.p_code = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* private funcs */
|
||||||
|
|
||||||
|
struct bcode_hdr {
|
||||||
|
cs_shared_state *cs; /* needed to construct the allocator */
|
||||||
|
std::size_t asize; /* alloc size of the bytecode block */
|
||||||
|
std::uint32_t init; /* CS_CODE_START + refcount */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* returned address is the 'init' member of the header */
|
||||||
|
std::uint32_t *bcode_alloc(cs_state &cs, std::size_t sz) {
|
||||||
|
auto a = cs_allocator<std::uint32_t>{cs};
|
||||||
|
std::size_t hdrs = sizeof(bcode_hdr) / sizeof(std::uint32_t);
|
||||||
|
auto p = a.allocate(sz + hdrs - 1);
|
||||||
|
bcode_hdr *hdr = reinterpret_cast<bcode_hdr *>(p);
|
||||||
|
hdr->cs = cs_get_sstate(cs);
|
||||||
|
hdr->asize = sz + hdrs - 1;
|
||||||
|
return p + hdrs - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bc's address must be the 'init' member of the header */
|
||||||
|
static inline void bcode_free(std::uint32_t *bc) {
|
||||||
|
auto *rp = bc + 1 - (sizeof(bcode_hdr) / sizeof(std::uint32_t));
|
||||||
|
bcode_hdr *hdr = reinterpret_cast<bcode_hdr *>(rp);
|
||||||
|
cs_allocator<std::uint32_t>{hdr->cs}.deallocate(rp, hdr->asize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcode_incr(std::uint32_t *bc) {
|
||||||
|
*bc += 0x100;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcode_decr(std::uint32_t *bc) {
|
||||||
|
*bc -= 0x100;
|
||||||
|
if (std::int32_t(*bc) < 0x100) {
|
||||||
|
bcode_free(bc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcode_ref(std::uint32_t *code) {
|
||||||
|
if (!code) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((*code & CS_CODE_OP_MASK) == CS_CODE_START) {
|
||||||
|
bcode_incr(code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (code[-1]&CS_CODE_OP_MASK) {
|
||||||
|
case CS_CODE_START:
|
||||||
|
bcode_incr(&code[-1]);
|
||||||
|
break;
|
||||||
|
case CS_CODE_OFFSET:
|
||||||
|
code -= std::ptrdiff_t(code[-1] >> 8);
|
||||||
|
bcode_incr(code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcode_unref(std::uint32_t *code) {
|
||||||
|
if (!code) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((*code & CS_CODE_OP_MASK) == CS_CODE_START) {
|
||||||
|
bcode_decr(code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (code[-1]&CS_CODE_OP_MASK) {
|
||||||
|
case CS_CODE_START:
|
||||||
|
bcode_decr(&code[-1]);
|
||||||
|
break;
|
||||||
|
case CS_CODE_OFFSET:
|
||||||
|
code -= std::ptrdiff_t(code[-1] >> 8);
|
||||||
|
bcode_decr(code);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace cscript */
|
|
@ -0,0 +1,74 @@
|
||||||
|
#ifndef LIBCUBESCRIPT_BCODE_HH
|
||||||
|
#define LIBCUBESCRIPT_BCODE_HH
|
||||||
|
|
||||||
|
#include <cubescript/cubescript.hh>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
namespace cscript {
|
||||||
|
|
||||||
|
struct cs_bcode;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CS_VAL_NULL = 0, CS_VAL_INT, CS_VAL_FLOAT, CS_VAL_STRING,
|
||||||
|
CS_VAL_ANY, CS_VAL_CODE, CS_VAL_IDENT, CS_VAL_WORD,
|
||||||
|
CS_VAL_POP, CS_VAL_COND
|
||||||
|
};
|
||||||
|
|
||||||
|
/* instruction: uint32 [length 24][retflag 2][opcode 6] */
|
||||||
|
enum {
|
||||||
|
CS_CODE_START = 0,
|
||||||
|
CS_CODE_OFFSET,
|
||||||
|
CS_CODE_NULL, CS_CODE_TRUE, CS_CODE_FALSE, CS_CODE_NOT,
|
||||||
|
CS_CODE_POP,
|
||||||
|
CS_CODE_ENTER, CS_CODE_ENTER_RESULT,
|
||||||
|
CS_CODE_EXIT, CS_CODE_RESULT_ARG,
|
||||||
|
CS_CODE_VAL, CS_CODE_VAL_INT,
|
||||||
|
CS_CODE_DUP,
|
||||||
|
CS_CODE_BOOL,
|
||||||
|
CS_CODE_BLOCK, CS_CODE_EMPTY,
|
||||||
|
CS_CODE_COMPILE, CS_CODE_COND,
|
||||||
|
CS_CODE_FORCE,
|
||||||
|
CS_CODE_RESULT,
|
||||||
|
CS_CODE_IDENT, CS_CODE_IDENT_U, CS_CODE_IDENT_ARG,
|
||||||
|
CS_CODE_COM, CS_CODE_COM_C, CS_CODE_COM_V,
|
||||||
|
CS_CODE_CONC, CS_CODE_CONC_W, CS_CODE_CONC_M,
|
||||||
|
CS_CODE_SVAR, CS_CODE_SVAR1,
|
||||||
|
CS_CODE_IVAR, CS_CODE_IVAR1, CS_CODE_IVAR2, CS_CODE_IVAR3,
|
||||||
|
CS_CODE_FVAR, CS_CODE_FVAR1,
|
||||||
|
CS_CODE_LOOKUP, CS_CODE_LOOKUP_U, CS_CODE_LOOKUP_ARG,
|
||||||
|
CS_CODE_LOOKUP_M, CS_CODE_LOOKUP_MU, CS_CODE_LOOKUP_MARG,
|
||||||
|
CS_CODE_ALIAS, CS_CODE_ALIAS_U, CS_CODE_ALIAS_ARG,
|
||||||
|
CS_CODE_CALL, CS_CODE_CALL_U, CS_CODE_CALL_ARG,
|
||||||
|
CS_CODE_PRINT,
|
||||||
|
CS_CODE_LOCAL,
|
||||||
|
CS_CODE_DO, CS_CODE_DO_ARGS,
|
||||||
|
CS_CODE_JUMP, CS_CODE_JUMP_B, CS_CODE_JUMP_RESULT,
|
||||||
|
CS_CODE_BREAK,
|
||||||
|
|
||||||
|
CS_CODE_OP_MASK = 0x3F,
|
||||||
|
CS_CODE_RET = 6,
|
||||||
|
CS_CODE_RET_MASK = 0xC0,
|
||||||
|
|
||||||
|
/* return type flags */
|
||||||
|
CS_RET_NULL = CS_VAL_NULL << CS_CODE_RET,
|
||||||
|
CS_RET_STRING = CS_VAL_STRING << CS_CODE_RET,
|
||||||
|
CS_RET_INT = CS_VAL_INT << CS_CODE_RET,
|
||||||
|
CS_RET_FLOAT = CS_VAL_FLOAT << CS_CODE_RET,
|
||||||
|
|
||||||
|
/* CS_CODE_JUMP_B, CS_CODE_JUMP_RESULT */
|
||||||
|
CS_CODE_FLAG_TRUE = 1 << CS_CODE_RET,
|
||||||
|
CS_CODE_FLAG_FALSE = 0 << CS_CODE_RET
|
||||||
|
};
|
||||||
|
|
||||||
|
std::uint32_t *bcode_alloc(cs_state &cs, std::size_t sz);
|
||||||
|
|
||||||
|
void bcode_incr(std::uint32_t *code);
|
||||||
|
void bcode_decr(std::uint32_t *code);
|
||||||
|
void bcode_ref(std::uint32_t *code);
|
||||||
|
void bcode_unref(std::uint32_t *code);
|
||||||
|
|
||||||
|
} /* namespace cscript */
|
||||||
|
|
||||||
|
#endif
|
98
src/cs_vm.cc
98
src/cs_vm.cc
|
@ -135,104 +135,6 @@ cs_stack_state cs_error::save_stack(cs_state &cs) {
|
||||||
return cs_stack_state(cs, ret, total > dalias->get_value());
|
return cs_stack_state(cs, ret, total > dalias->get_value());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bcode_hdr {
|
|
||||||
cs_shared_state *cs; /* needed to construct the allocator */
|
|
||||||
std::size_t asize; /* alloc size of the bytecode block */
|
|
||||||
std::uint32_t init; /* CS_CODE_START + refcount */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* returned address is the 'init' member of the header */
|
|
||||||
static inline std::uint32_t *bcode_alloc(cs_state &cs, std::size_t sz) {
|
|
||||||
auto a = cs_allocator<uint32_t>{cs};
|
|
||||||
std::size_t hdrs = sizeof(bcode_hdr) / sizeof(std::uint32_t);
|
|
||||||
auto p = a.allocate(sz + hdrs - 1);
|
|
||||||
bcode_hdr *hdr = reinterpret_cast<bcode_hdr *>(p);
|
|
||||||
hdr->cs = cs_get_sstate(cs);
|
|
||||||
hdr->asize = sz + hdrs - 1;
|
|
||||||
return p + hdrs - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* bc's address must be the 'init' member of the header */
|
|
||||||
static inline void bcode_free(uint32_t *bc) {
|
|
||||||
auto *rp = bc + 1 - (sizeof(bcode_hdr) / sizeof(std::uint32_t));
|
|
||||||
bcode_hdr *hdr = reinterpret_cast<bcode_hdr *>(rp);
|
|
||||||
cs_allocator<uint32_t>{hdr->cs}.deallocate(rp, hdr->asize);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bcode_incr(uint32_t *bc) {
|
|
||||||
*bc += 0x100;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void bcode_decr(uint32_t *bc) {
|
|
||||||
*bc -= 0x100;
|
|
||||||
if (std::int32_t(*bc) < 0x100) {
|
|
||||||
bcode_free(bc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bcode_ref(uint32_t *code) {
|
|
||||||
if (!code) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((*code & CS_CODE_OP_MASK) == CS_CODE_START) {
|
|
||||||
bcode_incr(code);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (code[-1]&CS_CODE_OP_MASK) {
|
|
||||||
case CS_CODE_START:
|
|
||||||
bcode_incr(&code[-1]);
|
|
||||||
break;
|
|
||||||
case CS_CODE_OFFSET:
|
|
||||||
code -= std::ptrdiff_t(code[-1] >> 8);
|
|
||||||
bcode_incr(code);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void bcode_unref(uint32_t *code) {
|
|
||||||
if (!code) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((*code & CS_CODE_OP_MASK) == CS_CODE_START) {
|
|
||||||
bcode_decr(code);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (code[-1]&CS_CODE_OP_MASK) {
|
|
||||||
case CS_CODE_START:
|
|
||||||
bcode_decr(&code[-1]);
|
|
||||||
break;
|
|
||||||
case CS_CODE_OFFSET:
|
|
||||||
code -= std::ptrdiff_t(code[-1] >> 8);
|
|
||||||
bcode_decr(code);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cs_bcode_ref::cs_bcode_ref(cs_bcode *v): p_code(v) {
|
|
||||||
bcode_ref(reinterpret_cast<uint32_t *>(p_code));
|
|
||||||
}
|
|
||||||
cs_bcode_ref::cs_bcode_ref(cs_bcode_ref const &v): p_code(v.p_code) {
|
|
||||||
bcode_ref(reinterpret_cast<uint32_t *>(p_code));
|
|
||||||
}
|
|
||||||
|
|
||||||
cs_bcode_ref::~cs_bcode_ref() {
|
|
||||||
bcode_unref(reinterpret_cast<uint32_t *>(p_code));
|
|
||||||
}
|
|
||||||
|
|
||||||
cs_bcode_ref &cs_bcode_ref::operator=(cs_bcode_ref const &v) {
|
|
||||||
bcode_unref(reinterpret_cast<uint32_t *>(p_code));
|
|
||||||
p_code = v.p_code;
|
|
||||||
bcode_ref(reinterpret_cast<uint32_t *>(p_code));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
cs_bcode_ref &cs_bcode_ref::operator=(cs_bcode_ref &&v) {
|
|
||||||
bcode_unref(reinterpret_cast<uint32_t *>(p_code));
|
|
||||||
p_code = v.p_code;
|
|
||||||
v.p_code = nullptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cs_alias_impl::clean_code() {
|
void cs_alias_impl::clean_code() {
|
||||||
uint32_t *bcode = reinterpret_cast<uint32_t *>(p_acode);
|
uint32_t *bcode = reinterpret_cast<uint32_t *>(p_acode);
|
||||||
if (bcode) {
|
if (bcode) {
|
||||||
|
|
53
src/cs_vm.hh
53
src/cs_vm.hh
|
@ -9,6 +9,7 @@
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include "cs_util.hh"
|
#include "cs_util.hh"
|
||||||
|
#include "cs_bcode.hh"
|
||||||
|
|
||||||
namespace cscript {
|
namespace cscript {
|
||||||
|
|
||||||
|
@ -201,12 +202,6 @@ struct cs_valarray {
|
||||||
std::aligned_storage_t<sizeof(T), alignof(T)> stor[N];
|
std::aligned_storage_t<sizeof(T), alignof(T)> stor[N];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
|
||||||
CS_VAL_NULL = 0, CS_VAL_INT, CS_VAL_FLOAT, CS_VAL_STRING,
|
|
||||||
CS_VAL_ANY, CS_VAL_CODE, CS_VAL_IDENT, CS_VAL_WORD,
|
|
||||||
CS_VAL_POP, CS_VAL_COND
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int cs_valtypet[] = {
|
static const int cs_valtypet[] = {
|
||||||
CS_VAL_NULL, CS_VAL_INT, CS_VAL_FLOAT, CS_VAL_STRING,
|
CS_VAL_NULL, CS_VAL_INT, CS_VAL_FLOAT, CS_VAL_STRING,
|
||||||
CS_VAL_CODE, CS_VAL_IDENT
|
CS_VAL_CODE, CS_VAL_IDENT
|
||||||
|
@ -216,52 +211,6 @@ static inline int cs_vtype_to_int(cs_value_type v) {
|
||||||
return cs_valtypet[int(v)];
|
return cs_valtypet[int(v)];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* instruction: uint32 [length 24][retflag 2][opcode 6] */
|
|
||||||
enum {
|
|
||||||
CS_CODE_START = 0,
|
|
||||||
CS_CODE_OFFSET,
|
|
||||||
CS_CODE_NULL, CS_CODE_TRUE, CS_CODE_FALSE, CS_CODE_NOT,
|
|
||||||
CS_CODE_POP,
|
|
||||||
CS_CODE_ENTER, CS_CODE_ENTER_RESULT,
|
|
||||||
CS_CODE_EXIT, CS_CODE_RESULT_ARG,
|
|
||||||
CS_CODE_VAL, CS_CODE_VAL_INT,
|
|
||||||
CS_CODE_DUP,
|
|
||||||
CS_CODE_BOOL,
|
|
||||||
CS_CODE_BLOCK, CS_CODE_EMPTY,
|
|
||||||
CS_CODE_COMPILE, CS_CODE_COND,
|
|
||||||
CS_CODE_FORCE,
|
|
||||||
CS_CODE_RESULT,
|
|
||||||
CS_CODE_IDENT, CS_CODE_IDENT_U, CS_CODE_IDENT_ARG,
|
|
||||||
CS_CODE_COM, CS_CODE_COM_C, CS_CODE_COM_V,
|
|
||||||
CS_CODE_CONC, CS_CODE_CONC_W, CS_CODE_CONC_M,
|
|
||||||
CS_CODE_SVAR, CS_CODE_SVAR1,
|
|
||||||
CS_CODE_IVAR, CS_CODE_IVAR1, CS_CODE_IVAR2, CS_CODE_IVAR3,
|
|
||||||
CS_CODE_FVAR, CS_CODE_FVAR1,
|
|
||||||
CS_CODE_LOOKUP, CS_CODE_LOOKUP_U, CS_CODE_LOOKUP_ARG,
|
|
||||||
CS_CODE_LOOKUP_M, CS_CODE_LOOKUP_MU, CS_CODE_LOOKUP_MARG,
|
|
||||||
CS_CODE_ALIAS, CS_CODE_ALIAS_U, CS_CODE_ALIAS_ARG,
|
|
||||||
CS_CODE_CALL, CS_CODE_CALL_U, CS_CODE_CALL_ARG,
|
|
||||||
CS_CODE_PRINT,
|
|
||||||
CS_CODE_LOCAL,
|
|
||||||
CS_CODE_DO, CS_CODE_DO_ARGS,
|
|
||||||
CS_CODE_JUMP, CS_CODE_JUMP_B, CS_CODE_JUMP_RESULT,
|
|
||||||
CS_CODE_BREAK,
|
|
||||||
|
|
||||||
CS_CODE_OP_MASK = 0x3F,
|
|
||||||
CS_CODE_RET = 6,
|
|
||||||
CS_CODE_RET_MASK = 0xC0,
|
|
||||||
|
|
||||||
/* return type flags */
|
|
||||||
CS_RET_NULL = CS_VAL_NULL << CS_CODE_RET,
|
|
||||||
CS_RET_STRING = CS_VAL_STRING << CS_CODE_RET,
|
|
||||||
CS_RET_INT = CS_VAL_INT << CS_CODE_RET,
|
|
||||||
CS_RET_FLOAT = CS_VAL_FLOAT << CS_CODE_RET,
|
|
||||||
|
|
||||||
/* CS_CODE_JUMP_B, CS_CODE_JUMP_RESULT */
|
|
||||||
CS_CODE_FLAG_TRUE = 1 << CS_CODE_RET,
|
|
||||||
CS_CODE_FLAG_FALSE = 0 << CS_CODE_RET
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CsBreakException {
|
struct CsBreakException {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ libcubescript_header_src = [
|
||||||
]
|
]
|
||||||
|
|
||||||
libcubescript_src = [
|
libcubescript_src = [
|
||||||
|
'cs_bcode.cc',
|
||||||
'cs_gen.cc',
|
'cs_gen.cc',
|
||||||
'cs_util.cc',
|
'cs_util.cc',
|
||||||
'cs_val.cc',
|
'cs_val.cc',
|
||||||
|
|
Loading…
Reference in New Issue