LLVM 汇编:使用可变参数调用函数
我想在 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
}
这似乎不可能。还有办法做到这一点吗?我认为使用简单的汇编程序应该是可能的。
这是面向对象语言的调度函数。我希望它能快点。
我想要的是一种方法:
- 从堆栈中删除 @1
- 分支使用的第一个参数到第二个函数。
然后,第二个函数将代替第一个函数(它是尾部调用)执行,但带有第一个函数不确切知道的参数列表(第一个函数的可变参数)。
I want to define a function in LLVM assembly that takes as argument:
- an identifier to a sub-function
- a vararg
This function should do some preprocessing, find the correct function for the identifier and call it using the vararg, and return its result.
Something like:
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
}
It doesn't seem to be possible. Is there a way to do that still? I think it should be possible using plain assembler.
This is intended to be a dispatching function for an object-oriented language. I would prefer it to be fast.
What I would like is a way to:
- remove from the stack the first argument used by @1
- branch to the second function.
The second function would then be executed in place of the first (it's a tail call), but with a list of argument that is not known exactly to the first function (the first function's vararg).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
第一:如果要传递可变参数,则不能使用尾调用:
http://llvm.org/docs /LangRef.html
第二:你的调用约定是什么?
第三:要处理可变参数(就像在 C 中一样),您需要使用 va_* 函数创建一个新的 va_list 并将所有参数复制到其中:
http://llvm.org/docs/LangRef.html#int-varargs
最后:此调度程序调用的每个函数都必须使用
va_*
函数来获取其参数。更新:
在谈论堆栈作为函数参数的存储之前,您应该知道将使用哪种调用约定(默认值是什么)。然后。如果没有 va_* 函数,则无法访问不传递“...”参数,因为这是在 LLVM 程序集中访问它们的唯一方法。
有一种像 C 语言一样的方法,这里 printf 将使用所有“...”参数调用 vfprintf,并且不知道要传递多少个参数
Vfprintf 以特殊方式声明以获取“...”并提取参数来自它:
First: You can't use tail call if you want to pass varargs:
http://llvm.org/docs/LangRef.html
Second: What is your Calling Conventions?
Third: To handle varargs (like in C) you need to use
va_*
functions to create a new va_list and copy all parameters into it:http://llvm.org/docs/LangRef.html#int-varargs
Last: Every function which will be called by this dispatcher must use
va_*
functions to get its arguments.UPDATE:
You should know which calling convention will you use (what is the default) before you will say about stack as storage of function arguments. Then. You can't access not pass "..." argument without va_* functions, because it is the ONLY way to access them in LLVM assembly.
There is a way of doing smth like in C, here the printf will call vfprintf with all "..." arguments and without knowing how many arguments to pass
Vfprintf is declared in special way to get "..." and to extract arguments from it:
(这个问题太大了,无法发表评论。恐怕我对 LLVM 没有太多实践经验,所以对此持保留态度)
我一直在考虑这个问题,我怀疑你是否能够来写一个这样的函数。
考虑使用 C 调用约定或任何支持可变参数的 x86_64 汇编语言编写此函数(请参阅 第 20 页 为例)。通常,您会在分支之前移动寄存器(rdi<-rsi、rsi<-rdx 等),但如果参数是浮点数,则不应该这样做,因此您必须了解类型!或者您必须使用类似
vfprintf
的函数。其他架构也存在类似的论点,因此我会考虑考虑另一种方法来解决问题。特别是,您不能将对
@1
的调用替换为在跳转表中查找并分支到%identifier
指定的函数指针吗?这可以制作成一个函数来检查%identifier
并返回正确的函数指针并适当地处理无效标识符。(This grew too big for a comment. I'm afraid I don't have much practical experience with LLVM, so take this with a grain of salt)
I've been thinking about this and I doubt you're going to be able to write such a function.
Consider writing this function in x86_64 assembler language using the C calling convention, or really any that supports varargs (see pg. 20 for an example). Normally you would shift the registers (rdi<-rsi, rsi<-rdx and so on) before branching, but you shouldn't do that if the arguments are e.g. floats, so you have to know about the types! Or you have to use a
vfprintf
-like function.Similar arguments exist for other architectures, so I'd consider thinking about another way to solve the problem. In particular couldn't you just replace the call to
@1
with a look up in a jump table and a branch to the function pointer specified by%identifier
? This could be made into a function that checks%identifier
and returns the correct function pointer and handles invalid identifiers appropriately.