我可以将现有方法绑定到 LLVM Function* 并从 JIT 编译的代码中使用它吗?
我正在研究 LLVM C++ API。我想 JIT 编译代码并运行它。
但是,我需要从所述 JIT 编译的代码中调用 C++ 方法。通常,LLVM 将方法调用视为函数调用,并将对象指针作为第一个参数传递,因此调用应该不成问题。真正的问题是将该函数放入 LLVM 中。
据我所知,可以使用函数的外部链接并通过其名称获取它。问题是,由于它是一个 C++ 方法,它的名称将会被破坏,所以我认为这样做不是一个好主意。
制作 FunctionType
对象非常简单。但从那里,我如何通知 LLVM 我的方法并为其获取一个 Function
对象?
I'm toying around with the LLVM C++ API. I'd like to JIT compile code and run it.
However, I need to call a C++ method from said JIT-compiled code. Normally, LLVM treats method calls as function calls with the object pointer passed as the first argument, so calling shouldn't be a problem. The real problem is to get that function into LLVM.
As far as I can see, it's possible to use external linkage for functions and get it by its name. Problem is, since it's a C++ method, its name is going to be mangled, so I don't think it's a good idea to go that way.
Making the FunctionType
object is easy enough. But from there, how can I inform LLVM of my method and get a Function
object for it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
LLVM 邮件列表中的家伙足够有帮助,可以提供更好的解决方案。他们没有说如何获取从方法到函数的指针,但我已经弄清楚了这部分,所以没关系。
编辑 一种干净的方法是将您的方法包装到一个函数中:
然后使用
Foo_Bar
的地址而不是尝试获取Foo::bar< /代码> 的。使用 llvm::ExecutionEngine::addGlobalMapping 添加映射,如下所示。
像往常一样,最简单的解决方案有一些有趣的好处。例如,它可以毫无问题地使用虚拟函数。 (但它的娱乐性要低得多。答案的其余部分保留用于历史目的,主要是因为我在研究 C++ 运行时的内部时获得了很多乐趣。另请注意,它是不可移植的。)
您需要一些东西沿着这些线来计算方法的地址(请注意,这是一个肮脏的黑客,可能只与 Itanium ABI 兼容):
然后使用 llvm::ExecutionEngine::addGlobalMapping 来映射函数到您获得的地址。要调用它,请将您的对象作为第一个参数传递给它,其余部分照常进行。这是一个简单的例子。
The dudes from the LLVM mailing list were helpful enough to provide a better solution. They didn't say how to get the pointer from the method to the function, but I've already figured out this part so it's okay.
EDIT A clean way to do this is simply to wrap your method into a function:
Then use
Foo_Bar
's address instead of trying to getFoo::bar
's. Usellvm::ExecutionEngine::addGlobalMapping
to add the mapping as shown below.As usual, the simplest solution has some interesting benefits. For instance, it works with virtual functions without a hiccup. (But it's so much less entertaining. The rest of the answer is kept for historical purposes, mainly because I had a lot of fun poking at the internals of my C++ runtime. Also note that it's non-portable.)
You'll need something along these lines to figure the address of a method (be warned, that's a dirty hack that probably will only be compatible with the Itanium ABI):
Then use
llvm::ExecutionEngine::addGlobalMapping
to map a function to the address you've gotten. To call it, pass it your object as the first parameter, and the rest as usual. Here's a quick example.一种方法是对所需方法进行 C 包装,即
extern "C"
位使函数使用 C 调用约定并防止任何名称修改。请参阅http://www.parashift。 com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.6 有关 C/C++ 互操作的详细信息,包括extern "C"
您也应该能够获取 C++ 代码中函数的地址,然后将该地址存储在 LLVM 已知的全局中。
One way is a C wrapper around the desired method, i.e.
The
extern "C"
bit makes the function use C calling conventions and prevents any name mangling. See http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.6 for details on C/C++ interop includingextern "C"
You should also probably be able to get the address of the function in your C++ code and then store that address in a global known to LLVM.
呵呵,使用非标准的 dladdr 和一种极其复杂且不安全的方法将方法指针转换为 void 指针,似乎有一种方法可以从方法的指针获取方法的名称。
这肯定比枪支更危险。不要在家里(或在工作中)这样做。
即使使用全能的 C 强制转换,C++ 也禁止将方法指针强制转换为 void*(这是 dladdr 工作所必需的),但您可以欺骗这一点。
从那里:
...aaa并且您应该能够在 LLVM 中使用该符号名称。但它不适用于虚拟方法(不使用它的另一个很好的理由)。
编辑 深入研究虚拟方法指针的处理方式,我整理了一个更复杂的函数,也适用于它们。只有最勇敢的人才应该关注此链接。
Huh, using the non-standard
dladdr
and a ridiculously convoluted and unsafe way to cast method pointers to void pointers, there seems to be a way to obtain the name of a method from its pointer.This is certainly more dangerous than firearms. Don't do this at home (or at work, for that matter).
C++ forbids to cast method pointers to void* (which is required by
dladdr
to work) even with the almighty C cast, but you can cheat that.From there:
...aaaand you should be able to use that symbol name with LLVM. But it won't work with virtual methods (another good reason to not use it).
EDIT Hacking much, much deeper into how virtual method pointers are handled, I've put together a more elaborate function that works for them, too. Only the most courageous of you should follow this link.