M new/src/tools/exec/asm.cpp => new/src/tools/exec/asm.cpp +17 -9
@@ 2062,6 2062,13 @@ auto expand_flow_control(ast::Instruction const& raw,
std::map<std::string, size_t> const& symbol_map,
Decl_map const& decl_map) -> Text
{
+ using viua::libs::lexer::TOKEN;
+ auto const jump_addr_already_loaded =
+ raw.operands.back().ingredients.front() == TOKEN::DOLLAR;
+ if (jump_addr_already_loaded) {
+ return {emit_instruction(raw)};
+ }
+
auto cooked = Text{};
auto const target = raw.operands.back();
@@ 2079,13 2086,13 @@ auto expand_flow_control(ast::Instruction const& raw,
lx.make_synth("l", TOKEN::LITERAL_ATOM));
}
- auto li = ast::Instruction{};
+ auto atxtp = ast::Instruction{};
{
- li.leader = raw.leader;
- li.leader.text = "g.li";
+ atxtp.leader = raw.leader;
+ atxtp.leader.text = "g.atxtp";
- li.operands.push_back(jmp_offset);
- li.operands.push_back(raw.operands.back());
+ atxtp.operands.push_back(jmp_offset);
+ atxtp.operands.push_back(raw.operands.back());
using viua::libs::lexer::TOKEN;
@@ 2137,11 2144,12 @@ auto expand_flow_control(ast::Instruction const& raw,
.add(decl_sym.leader));
}
- li.operands.back().ingredients.front().text =
+ atxtp.operands.back().ingredients.front().text =
(std::to_string(sym_off) + 'u');
- li.operands.back().ingredients.front().token = TOKEN::LITERAL_INTEGER;
+ atxtp.operands.back().ingredients.front().token =
+ TOKEN::LITERAL_INTEGER;
}
- std::ranges::copy(expand_li(li, true), std::back_inserter(cooked));
+ cooked.push_back(emit_instruction(atxtp));
auto jmp = ast::Instruction{};
{
@@ 2915,7 2923,7 @@ auto make_reloc_table(Text const& text) -> std::vector<Elf64_Rel>
static_cast<OPCODE>(each & viua::arch::ops::OPCODE_MASK);
switch (op) {
using enum viua::arch::ops::OPCODE;
- case IF:
+ // FIXME ATOM and DOUBLE should rely on ARODP
case ATOM:
case DOUBLE:
case ARODP:
M new/src/vm/ins.cpp => new/src/vm/ins.cpp +11 -3
@@ 1290,17 1290,25 @@ auto execute(DIVIU const op, Stack& stack, ip_type const) -> void
auto execute(IF const op, Stack& stack, ip_type const ip) -> ip_type
{
auto const condition = immutable_proxy(stack, op.instruction.out);
- auto tt = mutable_proxy(stack, op.instruction.in);
auto const take_branch =
(condition.holds<void>() or *condition.cast_to<bool>());
+ auto target_offset = size_t{};
+ if (auto jmp = mutable_proxy(stack, op.instruction.in)
+ .get<register_type::pointer_type>();
+ jmp) {
+ target_offset = jmp->ptr;
+ jmp.reset();
+ } else {
+ throw abort_execution{stack, "invalid in operand to if instruction"};
+ }
+
auto const target_addr =
- (*tt.target->get<uint64_t>() / sizeof(viua::arch::instruction_type));
+ target_offset / sizeof(viua::arch::instruction_type);
auto const target = take_branch ? (stack.proc->module.ip_base + target_addr)
: (ip + 1);
- tt.reset();
return target;
}