【问题标题】:llvm jit windows 8.1llvm jit windows 8.1
【发布时间】:2015-05-05 06:36:42
【问题描述】:

我正在尝试在 VS 2013 编译的 Windows 8.1 上运行斐波那契演示。 到目前为止,我解决了几个问题: 1. 不兼容的目标文件格式 - 我在 windows 的函数 getDefaultFormat(const Triple &T) 中将 Triple::COFF 更改为 Triple::ELF 2. 缺少 asm 打印机 - 我添加了 InitializeNativeTargetAsmPrinter() 3. 内存保护 - 我手动将 VirtualProtect 设置为 PAGE_EXECUTE(它没有设置,我不知道它应该如何工作)

现在我可以运行生成的代码,但是它崩溃了,这里是反汇编代码: 000000EC4B890000 推送 rsi
000000EC4B890001 推 rdi
000000EC4B890002 推送 rbx
000000EC4B890003 sub rsp,20h
000000EC4B890007 mov esi,ecx
000000EC4B890009 cmp esi,2
000000EC4B89000C jg 000000EC4B890015
000000EC4B89000E mov eax,1
000000EC4B890013 跳转 000000EC4B89002F
000000EC4B890015 lea ecx,[rsi-1]
000000EC4B890018 mov rbx,0
000000EC4B890022 调用 rbx
000000EC4B890024 mov edi,eax
000000EC4B890026 添加 esi,0FFFFFFFEh
000000EC4B890029 mov ecx,esi
000000EC4B89002B 调用 rbx
000000EC4B89002D 添加 eax,edi
000000EC4B89002F 添加 rsp,20h
000000EC4B890033 弹出 rbx
000000EC4B890034 弹出 rdi
000000EC4B890035 弹出 rsi
000000EC4B890036 ret

在地址 000000EC4B890018 上是指令 mov rbx,0 并在调用 rbx 之后立即导致崩溃。还有一个奇怪的事情,调用堆栈似乎被破坏了,在prologue之后调试器调用堆栈中有没有被调用的函数。

这里是红外:

define i32 @fib(i32 %AnArg) {
EntryBlock:
  %cond = icmp sle i32 %AnArg, 2
  br i1 %cond, label %return, label %recurse

return:                                           ; preds = %EntryBlock
  ret i32 1

recurse:                                          ; preds = %EntryBlock
  %arg = sub i32 %AnArg, 1
  %fibx1 = tail call i32 @fib(i32 %arg)
  %arg1 = sub i32 %AnArg, 2
  %fibx2 = tail call i32 @fib(i32 %arg1)
  %addresult = add i32 %fibx1, %fibx2
  ret i32 %addresult
}

我正在运行 Windows 8.1 专业版 LLVM 使用 VS 2013 社区版在 x64 配置中编译 我正在使用 LLVM 3.6.0

注意:x86 配置有效(发布时解释器除外,它会崩溃)

我错过了什么吗?我应该将 ELF 用于 x64 还是 COFF(我认为它没有在 JIT 中实现)?

我正在开始一个大项目。性能很关键,我想在其中使用一个脚本,但它必须是 jitted。最重要的平台是 Windows、Android 和 iOS。我担心 llvm 对这些平台的 JIT 支持。我知道 llvm 和 clang 在所有这些平台上都被广泛使用,但由于我目前遇到的问题,我对 JIT 不太确定。

【问题讨论】:

  • 那么,该函数的 LLVM IR 是什么?

标签: windows crash llvm jit


【解决方案1】:

MC JIT 尚不(尽管即将推出:http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150216/261096.html)支持动态可加载的 COFF 对象。

因此,如果您想要跨平台的 LLVM JIT,您需要检查您是否在 Windows 上运行,然后将目标三元组更改为附加“-elf”。

我对 C++ API 不太熟悉,所以我举了一个例子(使用 LLVM .NET C# Bindings):

var platform = Environment.OSVersion.Platform;
if (platform == PlatformID.Win32NT) // On Windows, LLVM currently (3.6) does not support PE/COFF
{
   LLVM.SetTarget(mod, Marshal.PtrToStringAnsi(LLVM.GetDefaultTargetTriple()) + "-elf");
}

【讨论】:

    【解决方案2】:

    我在使用 Windows 8.1、Visual Studio 2013、LLVM 3.6.1(-elf hack)时遇到了完全相同的问题。 JIT 代码未解析(mov reg, 0x0),内存页不可执行(立即崩溃)。

    问题是:JIT 模块实际上并没有最终确定,我认为它可能来自 -elf hack。 为了解决这个问题,我必须在 ExecutionEngine::getFunctionAddress (应该确保模块已完成)和对JIT 代码。

    // Call the JIT'ed code
    auto pCode = (BasicBlockCode)sm_pExecutionEngine->getFunctionAddress(pExecFunc->getName());
    // NOTE: We must call this method explicitly since it seems getFunctionAddress won't call it
    // -elf windows hack?
    sm_pExecutionEngine->finalizeObject();
    pCode(reinterpret_cast<u8*>(m_pCpuCtxt), reinterpret_cast<u8*>(m_pMemCtxt));
    

    【讨论】:

    • 你能在问题中添加一些相关的标签吗?我可以说它是 C++ 和某种 JIT,但就目前而言,如果我们不知道它是否是 .NET JIT 之类的,就很难回答这个问题
    • 谢谢,“finalizeObject()”解决了我的问题。这是一个问题参考,以防万一:llvm.org/bugs/show_bug.cgi?id=22910
    猜你喜欢
    • 1970-01-01
    • 2011-03-31
    • 2012-11-01
    • 2011-05-03
    • 2019-12-27
    • 1970-01-01
    • 2011-02-17
    • 2012-08-17
    • 1970-01-01
    相关资源
    最近更新 更多