.
This commit is contained in:
12
lib/code.c
12
lib/code.c
@@ -176,6 +176,18 @@ Instruction code_next_instruction(Code const* code, uint32_t function_id, uint32
|
||||
|
||||
#ifdef DEBUG_ASSEMBLY
|
||||
|
||||
void code_debug_bytecode(Code const* code)
|
||||
{
|
||||
for (int i = 0; i < code->bytecode_sz; ++i) {
|
||||
if (i % 16 == 0)
|
||||
printf("%04X : ", i);
|
||||
printf("%02X ", code->bytecode[i]);
|
||||
if (i % 16 == 15)
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void code_decompile(Code const* code)
|
||||
{
|
||||
if (code_n_consts(code) > 0)
|
||||
|
||||
@@ -279,7 +279,7 @@ local function assemble(proto)
|
||||
if type(bin[i]) == 'string' then
|
||||
local label_addr = labels[bin[i]]
|
||||
if label_addr == nil then error("Label not found: " .. bin[i]) end
|
||||
replace32(i, label_addr)
|
||||
replace16(i, label_addr)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -227,6 +227,7 @@ uint32_t code_n_functions(Code const* code);
|
||||
uint32_t code_function_sz(Code const* code, uint32_t f_id);
|
||||
Instruction code_next_instruction(Code const* code, uint32_t function_id, uint32_t pc);
|
||||
|
||||
void code_debug_bytecode(Code const* code);
|
||||
void code_decompile(Code const* code);
|
||||
void code_parse_instruction(Instruction inst, char* outbuf, size_t sz);
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ void tyc_destroy(TycheVM* t);
|
||||
// debugging (DEBUG_ASSEMBLY needs to be setup in compilation options)
|
||||
void tyc_debug_to_console(TycheVM* T, bool activate);
|
||||
void tyc_assembly_decompile(TycheVM* T);
|
||||
void tyc_print_bytecode(TycheVM* T);
|
||||
|
||||
// code loading and execution
|
||||
TYC_RESULT tyc_load_bytecode(TycheVM* T, uint8_t const* bytecode, size_t bytecode_sz);
|
||||
@@ -48,6 +49,7 @@ void tyc_pushnil(TycheVM* T);
|
||||
void tyc_pushinteger(TycheVM* T, int32_t value);
|
||||
TYC_RESULT tyc_type(TycheVM* T, int idx, TYC_TYPE* type);
|
||||
TYC_RESULT tyc_tointeger(TycheVM* T, int idx, int32_t* value);
|
||||
TYC_RESULT tyc_tostring(TycheVM* T, int idx, const char** str);
|
||||
TYC_RESULT tyc_expr(TycheVM* T, TYC_EXPR expr);
|
||||
|
||||
#endif //TYCHE_TYCHE_H
|
||||
|
||||
56
lib/vm.c
56
lib/vm.c
@@ -144,6 +144,11 @@ void tyc_assembly_decompile(TycheVM* T)
|
||||
code_decompile(T->code);
|
||||
}
|
||||
|
||||
void tyc_print_bytecode(TycheVM* T)
|
||||
{
|
||||
code_debug_bytecode(T->code);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
@@ -269,13 +274,26 @@ TYC_RESULT tyc_type(TycheVM* T, int idx, TYC_TYPE* type)
|
||||
TYC_RESULT tyc_tointeger(TycheVM* T, int idx, int32_t* value)
|
||||
{
|
||||
VALUE v;
|
||||
TYC_RESULT r = stack_at(T->stack, idx, &v);
|
||||
if (r == T_OK) {
|
||||
if (v.type != TT_INTEGER)
|
||||
return T_ERR_TYPE_UNEXPECTED;
|
||||
*value = value_integer(v);
|
||||
}
|
||||
return r;
|
||||
TYC_RESULT r;
|
||||
TRY(stack_at(T->stack, idx, &v))
|
||||
if (v.type != TT_INTEGER)
|
||||
return T_ERR_TYPE_UNEXPECTED;
|
||||
*value = value_integer(v);
|
||||
return T_OK;
|
||||
}
|
||||
|
||||
TYC_RESULT tyc_tostring(TycheVM* T, int idx, const char** str)
|
||||
{
|
||||
VALUE v;
|
||||
TYC_RESULT r;
|
||||
TRY(stack_at(T->stack, idx, &v))
|
||||
if (v.type == TT_STRING)
|
||||
return heap_get_string(T->heap, value_idx(v), str);
|
||||
else if (v.type == TT_STRING_CONST)
|
||||
*str = code_const_string(T->code, value_idx(v));
|
||||
else
|
||||
return T_ERR_TYPE_UNEXPECTED;
|
||||
return T_OK;
|
||||
}
|
||||
|
||||
TYC_RESULT tyc_expr(TycheVM* T, TYC_EXPR op)
|
||||
@@ -322,11 +340,21 @@ static TYC_RESULT step(TycheVM* T)
|
||||
break;
|
||||
|
||||
case TO_PUSHF:
|
||||
if (inst.operand < 0 || inst.operand > (int) code_n_functions(T->code))
|
||||
if (inst.operand < 0 || inst.operand >= (int) code_n_functions(T->code))
|
||||
return T_ERR_VALUE_OUT_OF_RANGE;
|
||||
TRY(stack_push(T->stack, create_value_idx(TT_FUNCTION, (uint32_t) inst.operand)))
|
||||
break;
|
||||
|
||||
case TO_PUSHC:
|
||||
if (inst.operand < 0 || inst.operand >= (int) code_n_consts(T->code))
|
||||
return T_ERR_VALUE_OUT_OF_RANGE;
|
||||
if (code_const_type(T->code, (size_t) inst.operand) == TC_STRING) {
|
||||
TRY(stack_push(T->stack, create_value_idx(TT_STRING_CONST, inst.operand)))
|
||||
} else {
|
||||
abort(); // REAL consts not supported for now
|
||||
}
|
||||
break;
|
||||
|
||||
case TO_POP:
|
||||
TRY(stack_pop(T->stack, NULL))
|
||||
break;
|
||||
@@ -400,14 +428,14 @@ static TYC_RESULT step(TycheVM* T)
|
||||
//
|
||||
|
||||
case TO_JMP:
|
||||
if (inst.operand < 0)
|
||||
return T_ERR_VALUE_OUT_OF_RANGE; // TODO - also check function size
|
||||
if (inst.operand < 0 || inst.operand >= code_function_sz(T->code, loc->function_id))
|
||||
return T_ERR_VALUE_OUT_OF_RANGE;
|
||||
loc->pc = (uint32_t) inst.operand;
|
||||
goto dont_update_pc;
|
||||
|
||||
case TO_BZ:
|
||||
if (inst.operand < 0)
|
||||
return T_ERR_VALUE_OUT_OF_RANGE; // TODO - also check function size
|
||||
if (inst.operand < 0 || inst.operand >= code_function_sz(T->code, loc->function_id))
|
||||
return T_ERR_VALUE_OUT_OF_RANGE;
|
||||
TRY(stack_pop(T->stack, &a))
|
||||
if (value_is_zero(a)) {
|
||||
loc->pc = (uint32_t) inst.operand;
|
||||
@@ -416,8 +444,8 @@ static TYC_RESULT step(TycheVM* T)
|
||||
break;
|
||||
|
||||
case TO_BNZ:
|
||||
if (inst.operand < 0)
|
||||
return T_ERR_VALUE_OUT_OF_RANGE; // TODO - also check function size
|
||||
if (inst.operand < 0 || inst.operand >= code_function_sz(T->code, loc->function_id))
|
||||
return T_ERR_VALUE_OUT_OF_RANGE;
|
||||
TRY(stack_pop(T->stack, &a))
|
||||
if (!value_is_zero(a)) {
|
||||
loc->pc = (uint32_t) inst.operand;
|
||||
|
||||
Reference in New Issue
Block a user