// // Generated using code_generating_script.py // enum Operation: U16{ BC_END_OF_INSTRUCTIONS, BC_POP_STACK, BC_PUSH_STACK, BC_LOAD_CONSTANT, BC_LOAD_FROM_MEMORY64, BC_LOAD_FROM_MEMORY32, BC_LOAD_FROM_MEMORY16, BC_LOAD_FROM_MEMORY8, BC_STORE_TO_MEMORY64, BC_STORE_TO_MEMORY32, BC_STORE_TO_MEMORY16, BC_STORE_TO_MEMORY8, BC_ADD_S64, BC_SUB_S64, BC_DIV_S64, BC_MUL_S64, BC_MOD_S64, BC_SHR_S64, BC_SHL_S64, BC_BITAND_S64, BC_BITOR_S64, BC_BITXOR_S64, BC_BITNOT_S64, BC_EQ_S64, BC_NEQ_S64, BC_GT_S64, BC_LT_S64, BC_OR_S64, BC_GTE_S64, BC_LTE_S64, BC_ADD_U64, BC_SUB_U64, BC_DIV_U64, BC_MUL_U64, BC_MOD_U64, BC_SHR_U64, BC_SHL_U64, BC_BITAND_U64, BC_BITOR_U64, BC_BITXOR_U64, BC_BITNOT_U64, BC_EQ_U64, BC_NEQ_U64, BC_GT_U64, BC_LT_U64, BC_OR_U64, BC_GTE_U64, BC_LTE_U64, BC_ADD_F64, BC_SUB_F64, BC_DIV_F64, BC_MUL_F64, BC_EQ_F64, BC_NEQ_F64, BC_GT_F64, BC_LT_F64, BC_GTE_F64, BC_LTE_F64, }; const char *op_name[] = { "BC_END_OF_INSTRUCTIONS", "BC_POP_STACK", "BC_PUSH_STACK", "BC_LOAD_CONSTANT", "BC_LOAD_FROM_MEMORY64", "BC_LOAD_FROM_MEMORY32", "BC_LOAD_FROM_MEMORY16", "BC_LOAD_FROM_MEMORY8", "BC_STORE_TO_MEMORY64", "BC_STORE_TO_MEMORY32", "BC_STORE_TO_MEMORY16", "BC_STORE_TO_MEMORY8", "BC_ADD_S64", "BC_SUB_S64", "BC_DIV_S64", "BC_MUL_S64", "BC_MOD_S64", "BC_SHR_S64", "BC_SHL_S64", "BC_BITAND_S64", "BC_BITOR_S64", "BC_BITXOR_S64", "BC_BITNOT_S64", "BC_EQ_S64", "BC_NEQ_S64", "BC_GT_S64", "BC_LT_S64", "BC_OR_S64", "BC_GTE_S64", "BC_LTE_S64", "BC_ADD_U64", "BC_SUB_U64", "BC_DIV_U64", "BC_MUL_U64", "BC_MOD_U64", "BC_SHR_U64", "BC_SHL_U64", "BC_BITAND_U64", "BC_BITOR_U64", "BC_BITXOR_U64", "BC_BITNOT_U64", "BC_EQ_U64", "BC_NEQ_U64", "BC_GT_U64", "BC_LT_U64", "BC_OR_U64", "BC_GTE_U64", "BC_LTE_U64", "BC_ADD_F64", "BC_SUB_F64", "BC_DIV_F64", "BC_MUL_F64", "BC_EQ_F64", "BC_NEQ_F64", "BC_GT_F64", "BC_LT_F64", "BC_GTE_F64", "BC_LTE_F64", }; // // **End** of generated using code_generating_script.py // union Register{ F64 f64; S64 s64; U64 *pointer_u64; U64 u64; S64 *pointer_s64; F64 *pointer_f64; U64 *pointer64; U8 *pointer; }; enum{ REG_STACK_POINTER, REG_INS_POINTER, }; struct Instruction{ U64 di; // @debug_id Operation operation; U16 left; union{U16 right; U16 src;}; U16 dst; }; struct Instruction_Constant{ U64 di; // @debug_id Operation operation; U32 dst; Register constant; U64 debug_type_flag; }; static_assert(sizeof(Instruction)*2 == sizeof(Instruction_Constant), "Should be double the size"); static_assert(sizeof(Instruction) % 8 == 0,"Should be 8 bit aligned"); static_assert(sizeof(Instruction_Constant) % 8 == 0,"Should be 8 bit aligned"); // // Bytecode interpreter context // struct Bc{ U64 dis; // @debug_id U8 *stack_bottom; Register registers[256]; Arena instructions; Arena stack; // We reserve 4 gibs and allocate only 4 kibs to make sure we know when we // accidently overshoot the stack by 2 gigabytes woo yeee }; function Bc create_bytecode_interp(){ Bc b = {}; { arena_init(&b.instructions, "Bytecode instructions"_s); b.instructions.alignment = 1; // Commit arena_push_size(&b.instructions, 16); arena_clear(&b.instructions); b.registers[REG_INS_POINTER].pointer = b.instructions.memory.data; } { arena_init(&b.stack, "Bytecode stack"_s); b.stack.alignment = 8; // Setup a 4 kilobyte stack arena_push_size(&b.stack, kib(4)); b.registers[REG_STACK_POINTER].pointer = b.stack_bottom = b.stack.memory.data; } return b; } function void emit_load_constant_f64(Bc *b, U8 dst, F64 constant){ auto i = exp_alloc_type(&b->instructions, Instruction_Constant); i->di = b->dis++; i->operation = BC_LOAD_CONSTANT; i->constant.f64 = constant; i->dst = dst; i->debug_type_flag = TYPE_F64; } function void emit_load_constant_s64(Bc *b, U8 dst, S64 constant){ auto i = exp_alloc_type(&b->instructions, Instruction_Constant); i->di = b->dis++; i->operation = BC_LOAD_CONSTANT; i->constant.s64 = constant; i->dst = dst; i->debug_type_flag = TYPE_S64; } function void emit_load_constant_u64(Bc *b, U8 dst, U64 constant){ auto i = exp_alloc_type(&b->instructions, Instruction_Constant); i->di = b->dis++; i->operation = BC_LOAD_CONSTANT; i->constant.u64 = constant; i->dst = dst; i->debug_type_flag = TYPE_U64; } function void emit_push(Bc *b, U8 src){ Instruction *i = exp_alloc_type(&b->instructions, Instruction); i->di = b->dis++; i->operation = BC_PUSH_STACK; i->src = src; } function void emit_pop(Bc *b, U8 dst){ Instruction *i = exp_alloc_type(&b->instructions, Instruction); i->di = b->dis++; i->operation = BC_POP_STACK; i->dst = dst; } function void emit_memory(Bc *b, Operation ins, U8 dst, U8 src){ Instruction *i = exp_alloc_type(&b->instructions, Instruction); i->di = b->dis++; i->operation = ins; i->dst = dst; i->src = src; } function void emit_arithmetic(Bc *b, Operation ins, U8 left, U8 right, U8 dst){ Instruction *i = exp_alloc_type(&b->instructions, Instruction); i->di = b->dis++; i->operation = ins; i->left = left; i->right = right; i->dst = dst; } function void emit_end(Bc *b){ Instruction *i = exp_alloc_type(&b->instructions, Instruction); i->di = b->dis++; i->operation = BC_END_OF_INSTRUCTIONS; } #define BC_LOG 1 #if BC_LOG #define bc_log(...) log_info(__VA_ARGS__) #else #define bc_log(...) #endif function void run_bytecode_interp(Bc *b){ for(;;){ auto instr = (Instruction *)b->registers[REG_INS_POINTER].pointer64; bc_log("%llu.[%llx] - %s ", instr->di, b->registers[REG_INS_POINTER].pointer64, op_name[instr->operation]); b->registers[REG_INS_POINTER].pointer += sizeof(Instruction); switch(instr->operation){ case BC_LOAD_FROM_MEMORY64:{ U64 *load_address = b->registers[instr->src].pointer64; b->registers[instr->dst].u64 = *load_address; bc_log("r%u(dst) [%llx|%lld|%f]", instr->dst, b->registers[instr->dst].u64, b->registers[instr->dst].u64, b->registers[instr->dst].u64); }break; case BC_STORE_TO_MEMORY64:{ U64 *store_address = b->registers[instr->dst].pointer64; *store_address = b->registers[instr->src].u64; bc_log("r%u(src) [%llx|%lld|%f]", instr->src, *store_address, *store_address, *store_address); }break; case BC_PUSH_STACK:{ U64 *stack = b->registers[REG_STACK_POINTER].pointer64++; U64 src = b->registers[instr->src].u64; bc_log("r%u(src) [%llx|%lld|%f]", instr->src, src, src, src); *stack = src; }break; case BC_POP_STACK:{ U64 *stack = --b->registers[REG_STACK_POINTER].pointer64; bc_log("r%u(dst) [%llx|%lld|%f]", instr->dst, *stack, *stack, *stack); b->registers[instr->dst].u64 = *stack; }break; case BC_END_OF_INSTRUCTIONS:{ goto end_of_program; }break; case BC_LOAD_CONSTANT: { b->registers[REG_INS_POINTER].pointer+=sizeof(Instruction); // Constant is twice the size of regular Instruction auto i = (Instruction_Constant *)instr; b->registers[i->dst] = i->constant; #if BC_LOG switch(i->debug_type_flag){ case TYPE_S64: bc_log("r%u(dst) [%lld]", i->dst, i->constant.s64); break; case TYPE_U64: bc_log("r%u(dst) [%llu]", i->dst, i->constant.u64); break; case TYPE_F64: bc_log("r%u(dst) [%f]" , i->dst, i->constant.f64); break; invalid_default_case; } #endif }break; // // Generated using code_generating_script.py // case BC_ADD_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left + right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] + [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_SUB_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left - right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] - [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_DIV_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left / right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] / [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_MUL_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left * right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] * [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_MOD_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left % right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] % [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_SHR_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left >> right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] >> [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_SHL_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left << right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] << [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_BITAND_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left & right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] & [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_BITOR_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left | right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] | [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_BITXOR_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left ^ right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] ^ [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_BITNOT_S64:{ S64 left = (S64)b->registers[instr->left].s64; S64 result = ~left; S64 *dst = b->registers[instr->dst].pointer_s64; *dst = result; bc_log("~ [%lld] = [%lld]", left, result); }break; case BC_EQ_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left == right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] == [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_NEQ_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left != right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] != [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_GT_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left > right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] > [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_LT_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left < right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] < [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_OR_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left || right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] || [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_GTE_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left >= right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] >= [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_LTE_S64:{ S64 left = b->registers[instr->left].s64; S64 right = b->registers[instr->right].s64; S64 result = left <= right; b->registers[instr->dst].s64 = result; bc_log("r%u + r%u = r%u => [%lld] <= [%lld] = [%lld]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_ADD_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left + right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] + [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_SUB_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left - right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] - [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_DIV_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left / right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] / [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_MUL_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left * right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] * [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_MOD_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left % right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] % [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_SHR_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left >> right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] >> [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_SHL_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left << right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] << [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_BITAND_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left & right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] & [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_BITOR_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left | right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] | [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_BITXOR_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left ^ right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] ^ [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_BITNOT_U64:{ U64 left = (U64)b->registers[instr->left].u64; U64 result = ~left; U64 *dst = b->registers[instr->dst].pointer_u64; *dst = result; bc_log("~ [%llu] = [%llu]", left, result); }break; case BC_EQ_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left == right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] == [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_NEQ_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left != right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] != [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_GT_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left > right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] > [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_LT_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left < right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] < [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_OR_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left || right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] || [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_GTE_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left >= right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] >= [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_LTE_U64:{ U64 left = b->registers[instr->left].u64; U64 right = b->registers[instr->right].u64; U64 result = left <= right; b->registers[instr->dst].u64 = result; bc_log("r%u + r%u = r%u => [%llu] <= [%llu] = [%llu]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_ADD_F64:{ F64 left = b->registers[instr->left].f64; F64 right = b->registers[instr->right].f64; F64 result = left + right; b->registers[instr->dst].f64 = result; bc_log("r%u + r%u = r%u => [%f] + [%f] = [%f]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_SUB_F64:{ F64 left = b->registers[instr->left].f64; F64 right = b->registers[instr->right].f64; F64 result = left - right; b->registers[instr->dst].f64 = result; bc_log("r%u + r%u = r%u => [%f] - [%f] = [%f]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_DIV_F64:{ F64 left = b->registers[instr->left].f64; F64 right = b->registers[instr->right].f64; F64 result = left / right; b->registers[instr->dst].f64 = result; bc_log("r%u + r%u = r%u => [%f] / [%f] = [%f]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_MUL_F64:{ F64 left = b->registers[instr->left].f64; F64 right = b->registers[instr->right].f64; F64 result = left * right; b->registers[instr->dst].f64 = result; bc_log("r%u + r%u = r%u => [%f] * [%f] = [%f]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_EQ_F64:{ F64 left = b->registers[instr->left].f64; F64 right = b->registers[instr->right].f64; F64 result = left == right; b->registers[instr->dst].f64 = result; bc_log("r%u + r%u = r%u => [%f] == [%f] = [%f]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_NEQ_F64:{ F64 left = b->registers[instr->left].f64; F64 right = b->registers[instr->right].f64; F64 result = left != right; b->registers[instr->dst].f64 = result; bc_log("r%u + r%u = r%u => [%f] != [%f] = [%f]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_GT_F64:{ F64 left = b->registers[instr->left].f64; F64 right = b->registers[instr->right].f64; F64 result = left > right; b->registers[instr->dst].f64 = result; bc_log("r%u + r%u = r%u => [%f] > [%f] = [%f]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_LT_F64:{ F64 left = b->registers[instr->left].f64; F64 right = b->registers[instr->right].f64; F64 result = left < right; b->registers[instr->dst].f64 = result; bc_log("r%u + r%u = r%u => [%f] < [%f] = [%f]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_GTE_F64:{ F64 left = b->registers[instr->left].f64; F64 right = b->registers[instr->right].f64; F64 result = left >= right; b->registers[instr->dst].f64 = result; bc_log("r%u + r%u = r%u => [%f] >= [%f] = [%f]", instr->left, instr->right, instr->dst, left, right, result); }break; case BC_LTE_F64:{ F64 left = b->registers[instr->left].f64; F64 right = b->registers[instr->right].f64; F64 result = left <= right; b->registers[instr->dst].f64 = result; bc_log("r%u + r%u = r%u => [%f] <= [%f] = [%f]", instr->left, instr->right, instr->dst, left, right, result); }break; // // **End** of generated using code_generating_script.py // } bc_log("\n"); } end_of_program:; } function void test_interpreter(){ Bc b = create_bytecode_interp(); emit_load_constant_f64(&b, 2, 100.32); emit_load_constant_f64(&b, 3, 200.68); emit_arithmetic(&b, BC_ADD_F64, 2, 3, 4); emit_push(&b, 4); emit_pop(&b, 5); emit_end(&b); run_bytecode_interp(&b); }