我想在LLVM程序集中定义一个函数,该函数作为参数:
此函数应该进行一些预处理,找到标识符的正确函数并使用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
}
似乎不可能。还有办法吗?我认为应该可以使用普通的汇编程序。
这是一个面向对象语言的调度函数。我希望它快。
我想要的是一种方式:
然后执行第二个函数代替第一个函数(它是一个尾调用),但是带有一个参数列表,该参数列表与第一个函数(第一个函数的vararg)不完全相同。
答案 0 :(得分:3)
首先:如果你想传递varargs,你不能使用尾调用:
http://llvm.org/docs/LangRef.html
- 可选的“tail”标记表示被调用者函数不访问调用者中的任何allocas或varargs。
醇>
第二:你的电话会议是什么?
第三:要处理varargs(如C语言),您需要使用va_*
函数创建一个新的va_list并将所有参数复制到其中:
http://llvm.org/docs/LangRef.html#int-varargs
Last:此调度程序将调用的每个函数都必须使用va_*
函数来获取其参数。
更新:
在您说堆栈作为函数参数的存储之前,您应该知道将使用哪个调用约定(默认值是什么)。然后。如果没有va_ *函数,则无法访问不传递“...”参数,因为它是在LLVM程序集中访问它们的唯一方法。
有一种方法可以像在C中那样做smth,这里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);
}
以特殊方式声明Vfprintf以获取“...”并从中提取参数:
int
vfprintf(FILE *fp, const char *fmt0, __va_list ap)
{
...
va_arg(ap, type) //to get next arg of type `type`
答案 1 :(得分:1)
(这对评论来说太大了。我担心我对LLVM没有多少实际经验,所以请大家多加一点)
我一直在考虑这个,我怀疑你是否能够写出这样的功能。
考虑使用C调用约定以x86_64汇编语言编写此函数,或者实际上任何支持varargs的函数(请参阅pg. 20示例)。通常你会在分支之前移位寄存器(rdi< -rsi,rsi< -rdx等),但是如果参数是例如你不应该这样做。漂浮,所以你必须知道类型!或者你必须使用类似vfprintf
的函数。
其他架构存在类似的论点,因此我会考虑另一种解决问题的方法。特别是你不能只用一个跳转表中的查找替换对@1
的调用,并将分支替换为%identifier
指定的函数指针吗?这可以成为一个函数,它检查%identifier
并返回正确的函数指针并适当地处理无效的标识符。