https://github.com/fwsgonzo/libriscv/blob/master/lib/libiscv/machine_vmcall.hpp#l35
https://github.com/fwsgonzo/libriscv/blob/master/lib/libiscv/machine_vmcall.hpp#l18
结构将被推到堆栈上,地址将占用整数寄存器插槽。因此,我可以将常规功能调用变成我的虚拟机。我认为没有其他编程语言可以做到这一点。现在,另一方面是系统呼叫处理程序。他们看起来像这样:
https://github.com/fwsgonzo/libriscv/blob/master/emulator/src/syscalls.cpp#l20为了简化系统调用处理,我希望能够列出参数类型的列表,对它们执行一些逻辑(根据类型提取值),然后选择将lambda与我构建的参数调用。例如这样:
template <int, int, int>
void simplified_systemcall_handler(machine& machine, std::function<int, int int> callback)
{
parameter_pack p;
int i = 0;
foreach (Arg : <int, int, int>) {
if constexpr (std::is_integral_v<Arg>) {
p.append(machine.get_syscall_arg<int> (i++));
}
}
callback(p);
}
当然,这不会起作用,因为您无法构建我所知的参数包,也无法像这样迭代模板参数。但是,伪代码告诉您我想做什么。目标是使系统调用处理更简单,并通过一次提取系统调用参数一行,从而大大简化API。那么,第二好的是什么?
能够一口气提取几个参数,但是如何将其临时存储并迭代C ++?这样的东西:
auto list = machine.get_syscall_arguments<int, long, float> ();
// process list assuming list[0] is int, list[1] is long
提前已知参数的数量和类型。直到从机器寄存器中提取它们时,这些值才知道。
嗯,这是你追求的吗?
1 is integral
42 is integral
0 is integral
operator,
可能是瑞士人折叠式表达的瑞士军刀。您甚至不需要实际值:
template<class... Args> void omg()
{
std::size_t i{};
((++i,
std::is_integral_v<Args> && std::cout <<
"Arg #" << i << " is integral\n"
|| std::is_scalar_v<Args> && std::cout <<
"Arg #" << i << " is not integral, yet is scalar\n"
), ...);
}
int main() {
omg<int, int, double, char const *, std::size_t>();
}
如果您没有实际的值,但是它们的类型和索引访问,那么,您可以通过某种非常基本的方式轻松地检索它们:
template<class... Args, std::size_t... indices> void add_args(
std::index_sequence<indices...>)
{
(p.append(sys.get_arg<Args>(indices)), ...);
}
template<class... Args> void add_args() {
add_args<Args...>(std::index_sequence_for<Args...>{});
}
将它们存放在元组中有点棘手,而且不是很简单:
std::tuple<std::decay_t<Args>...> retval;
((std::get<indices>(retval) = sys.get_arg<Args>(indices)), ...);
return retval;