Текущая (старая) сигнатура вызова функции:
long vmcall(const std::string& function_name,
std::vector<address_t> args);
Теперь, поскольку я могу звонить только гостю, используя целые (размер адреса), это довольно ограниченный интерфейс, и я хочу его расширить по крайней мере, также обрабатывать значения с плавающей запятой и, возможно, другие, например, так:
template <typename... Args>
long vmcall(const std::string& function_name,
Args&&... args);
Это будет новая сигнатура функции, заменяющая старую.
Чтобы показать, как вектор аргументов в настоящее время используется:
template <int W>
inline void Machine<W>::setup_call(
address_t call_addr, address_t retn_addr,
std::vector<address_t> args)
{
assert(args.size() <= 8);
cpu.reg(RISCV::REG_RA) = retn_addr;
for (size_t arg = 0; arg < args.size(); arg++) {
cpu.reg(RISCV::REG_ARG0 + arg) = args[arg];
}
cpu.jump(call_addr);
}
Эта функция вызывается из vmcall с помощью std :: move (args), и все, что она делает, это копирует целочисленные аргументы в векторе args в интегральные регистры ЦП, постепенно. Это прекрасно работает, когда я хочу вызвать функцию, которая принимает только интегральные аргументы. Итак, если бы я хотел вызвать функцию, которая, скажем, принимает один аргумент с плавающей точкой, то сделать это невозможно. Это связано с тем, что регистры FP полностью разделены и должны обрабатываться по-разному.
Кроме того, 32-разрядные и 64-разрядные операции с плавающей запятой обрабатываются по-разному посредством NaN-бокса. Итак, было бы неплохо, если бы можно было различить и float, и double.
Я не так силен в магах шаблонов c для начала. Как мне перейти на тип каждого элемента в пакете параметров?