M new/include/viua/vm/core.h => new/include/viua/vm/core.h +7 -0
@@ 283,6 283,11 @@ struct Frame {
viua::arch::Register_access result_to;
+ struct {
+ uint64_t fp { 0 };
+ uint64_t sbrk { 0 };
+ } saved;
+
inline Frame(size_t const sz, addr_type const e, addr_type const r)
: registers(sz), entry_address{e}, return_address{r}
{}
@@ 472,6 477,8 @@ struct Process {
stack_type stack;
std::vector<Page> memory;
+ uint64_t frame_pointer { 0 };
+ uint64_t stack_break { 0 };
using Pointer = std::pair<bool, uintptr_t>;
auto memory_at(Pointer const) const -> void const*;
M new/src/vm/ins.cpp => new/src/vm/ins.cpp +24 -0
@@ 1221,6 1221,18 @@ auto execute(CALL const op, Stack& stack, ip_type const ip) -> ip_type
throw abort_execution{ip, "invalid IP after call"};
}
+ /*
+ * Save:
+ *
+ * - frame pointer ie, pointer to where the frames memory area begins
+ * - stack break ie, pointer to where next unallocated pointer is on the
+ * stack memory
+ *
+ * They should be restored when the frame is popped.
+ */
+ stack.frames.back().saved.fp = stack.proc->frame_pointer;
+ stack.frames.back().saved.sbrk = stack.proc->stack_break;
+
auto const fr_return = (stack.ip + 1);
auto const fr_entry = (stack.proc->module.ip_base
+ (fn_addr / sizeof(viua::arch::instruction_type)));
@@ 1230,6 1242,15 @@ auto execute(CALL const op, Stack& stack, ip_type const ip) -> ip_type
stack.frames.back().parameters = std::move(stack.args);
stack.frames.back().result_to = op.instruction.out;
+ /*
+ * Set the frame pointer to stack break to. Usually, one of the first
+ * instructions in the callee is AMA which will increase the stack break
+ * giving the function some memory to work with.
+ */
+ stack.proc->frame_pointer = stack.proc->stack_break;
+ stack.frames.back().saved.fp = stack.proc->frame_pointer;
+ stack.frames.back().saved.sbrk = stack.proc->stack_break;
+
return fr_entry;
}
@@ 1260,6 1281,9 @@ auto execute(RETURN const op, Stack& stack, ip_type const ip) -> ip_type
out = std::move(fr.registers.at(op.instruction.out.index));
}
+ stack.proc->frame_pointer = fr.saved.fp;
+ stack.proc->stack_break = fr.saved.sbrk;
+
return fr.return_address;
}