LLVM程序集:使用varargs调用函数

Mil*_*red 6 assembly llvm variadic-functions

我想在LLVM程序集中定义一个函数,该函数作为参数:

  • 子功能的标识符
  • 一个vararg

此函数应该进行一些预处理,找到标识符的正确函数并使用vararg调用它,并返回其结果.

就像是:

define ??? @1 (i32 %identifier, ...vararg...)
{
  switch i32 %identifier, label %def, i32 1, label %a
a:
  %1 = tail call @function_for_a, ...vararg...
  ret ??? %1
def:
  ret void
}
Run Code Online (Sandbox Code Playgroud)

这似乎不可能.还有办法吗?我认为应该可以使用普通的汇编程序.

这旨在成为面向对象语言的调度功能.我希望它快.

我想要的是一种方式:

  • 从堆栈中删除@ 1使用的第一个参数
  • 分支到第二个功能.

然后执行第二个函数代替第一个函数(它是一个尾调用),但是带有一个参数列表,该参数列表与第一个函数(第一个函数的vararg)不完全相同.

osg*_*sgx 3

第一:如果你想传递可变参数,你不能使用尾部调用:

http://llvm.org/docs/LangRef.html

  1. 可选的“tail”标记指示被调用函数不访问调用方中的任何分配器或可变参数。

第二:你的调用约定是什么?

第三:要处理可变参数(就像在 C 中一样),您需要使用va_*函数创建一个新的 va_list 并将所有参数复制到其中:

http://llvm.org/docs/LangRef.html#int-varargs

最后:此调度程序调用的每个函数都必须使用va_*函数来获取其参数。

更新:

在谈论堆栈作为函数参数的存储之前,您应该知道将使用哪种调用约定(默认值是什么)。然后。如果没有 va_* 函数,则无法访问不传递“...”参数,因为这是在 LLVM 程序集中访问它们的唯一方法。

有一种像 C 语言一样的方法,这里 printf 将使用所有“...”参数调用 vfprintf,并且不知道要传递多少个参数

// 3-clause BSD licensed to The Regents of the University of California.

int
printf(const char *fmt, ...)
{
        int ret;
        va_list ap;

        va_start(ap, fmt);
        ret = vfprintf(stdout, fmt, ap);
        va_end(ap);
        return (ret);
}
Run Code Online (Sandbox Code Playgroud)

Vfprintf 以特殊方式声明以获取“...”并从中提取参数:

int
vfprintf(FILE *fp, const char *fmt0, __va_list ap)
{
...
va_arg(ap, type) //to get next arg of type `type`
Run Code Online (Sandbox Code Playgroud)