2

在互联网和 Stackoverflow 的一些研究中,关于如何在运行时执行 IR 代码的唯一示例是SO上的这个示例。我现在已经用 Visual Studio 2012 编译了 llvm 和 clang,我能够编译一些我想用于“脚本”扩展的源文件,clang File.cpp -S -emit-llvm -O3这样输出就是通常的 IR 代码,比如

; ModuleID = '.\Test.cpp'
target datalayout = "/* ... */"
target triple = "i686-pc-win32"
define i32 @test() #0 {
  ret i32 43
}
attributes #0 = { nounwind /* ... */ }

我提到的帖子真的很老,我想知道两件事:

  1. 如何在运行时使用 llvm 3.2 初始化引擎并执行此类代码(使用 C++)?仍然使用相同的调用吗?
  2. 在编译期间创建了大量的库。我怎么知道哪些必须链接?

我的代码有效,可能需要一些优化

#include <iostream>
#include <llvm/IR/LLVMContext.h>
#include <llvm/ADT/Triple.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/CodeGen/LinkAllCodegenComponents.h>
#include <llvm/ExecutionEngine/GenericValue.h>
#include <llvm/ExecutionEngine/Interpreter.h>
#include <llvm/ExecutionEngine/JIT.h>
#include <llvm/ExecutionEngine/JITEventListener.h>
#include <llvm/ExecutionEngine/JITMemoryManager.h>
#include <llvm/ExecutionEngine/MCJIT.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Type.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/Debug.h>
#include <llvm/Support/DynamicLibrary.h>
#include <llvm/Support/Format.h>
#include <llvm/Support/IRReader.h>
#include <llvm/Support/ManagedStatic.h>
#include <llvm/Support/MathExtras.h>
#include <llvm/Support/Memory.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Support/PluginLoader.h>
#include <llvm/Support/PrettyStackTrace.h>
#include <llvm/Support/Process.h>
#include <llvm/Support/Signals.h>
#include <llvm/Support/TargetSelect.h>
#include <llvm/Support/raw_ostream.h>

#pragma comment(lib, "LLVMMCJIT.lib")
#pragma comment(lib, "LLVMInterpreter.lib")
#pragma comment(lib, "LLVMBitReader.lib")
#pragma comment(lib, "LLVMAsmParser.lib")
#pragma comment(lib, "LLVMX86CodeGen.lib")
#pragma comment(lib, "LLVMX86AsmParser.lib")
#pragma comment(lib, "LLVMX86Disassembler.lib")
#pragma comment(lib, "LLVMJIT.lib")
#pragma comment(lib, "LLVMAsmPrinter.lib")
#pragma comment(lib, "LLVMSelectionDAG.lib")
#pragma comment(lib, "LLVMX86Desc.lib")
#pragma comment(lib, "LLVMExecutionEngine.lib")
#pragma comment(lib, "LLVMRuntimeDyld.lib")
#pragma comment(lib, "LLVMMCParser.lib")
#pragma comment(lib, "LLVMCodeGen.lib")
#pragma comment(lib, "LLVMX86AsmPrinter.lib")
#pragma comment(lib, "LLVMX86Info.lib")
#pragma comment(lib, "LLVMObjCARCOpts.lib")
#pragma comment(lib, "LLVMScalarOpts.lib")
#pragma comment(lib, "LLVMX86Utils.lib")
#pragma comment(lib, "LLVMInstCombine.lib")
#pragma comment(lib, "LLVMTransformUtils.lib")
#pragma comment(lib, "LLVMipa.lib")
#pragma comment(lib, "LLVMAnalysis.lib")
#pragma comment(lib, "LLVMTarget.lib")
#pragma comment(lib, "LLVMCore.lib")
#pragma comment(lib, "LLVMMC.lib")
#pragma comment(lib, "LLVMObject.lib")
#pragma comment(lib, "LLVMSupport.lib")

using namespace llvm;

int main(int argc, char **argv) {
    InitializeNativeTarget();
    LLVMContext &context = getGlobalContext();
    ExecutionEngine *ee;
    SMDiagnostic diag;
    Module *m = ParseIRFile("Script.s", diag, context);
    if(!m) {
        diag.print("LLVMSandbox", errs());
        return 1;
    }
    m->MaterializeAllPermanently();
    ee = EngineBuilder(m).create();
    Function *func = ee->FindFunctionNamed("main");
    typedef int (*PFN)();
    PFN pfn = reinterpret_cast<PFN>(ee->getPointerToFunction(func));
    int i = pfn();
    std::cout << i;
    std::cin.get();
    delete ee;
    return 0;
}
4

1 回答 1

4

LLVM 正在以惊人的速度发展,并且难以跟上。因此,找到在 LLVM 不断向前发展的同时继续工作的代码的最佳方法是查看使用 LLVM 构建和测试的代码。

在这种情况下,您需要该lli工具(tools/lli在代码中)。它是 LLVM IR 的通用“执行器”,使用解释器或 JIT 引擎之一。它也应该在 Windows 上工作。您可以将它用作实例化所有必需的 LLVM 机器(就 C++ 代码而言)和构建新的独立工具(您可以模仿它的 makefile 或CMakeLists.txt)的示例

于 2013-02-26T14:44:56.423 回答