在互联网和 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 /* ... */ }
我提到的帖子真的很老,我想知道两件事:
- 如何在运行时使用 llvm 3.2 初始化引擎并执行此类代码(使用 C++)?仍然使用相同的调用吗?
- 在编译期间创建了大量的库。我怎么知道哪些必须链接?
我的代码有效,可能需要一些优化
#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;
}