基于LLVM-增加JIT支持

匿名 (未验证) 提交于 2019-12-03 00:37:01

JIT其实就是Just-In-Time也就是即时编译,在程序运行的时候会将代码翻译成机器码并且去执行,与之相对的就是AOT(Ahead Of Time),它在程序运行之前就会将代码翻译成机器码,JIT结合了AOT和解释执行的优势,它能够产生高效的机器码,并且具备足够的灵活性

首先我们定义一个执行引擎作为全局静态变量

static ExecutionEngine *TheExecutionEngine;

然后就是在main函数当中增加如下代码

  //InitializeNativeTarget――主程序应该调用此函数来初始化与主机对应的本机目标。这对于JIT应用程序非常有用,以确保目标被正确地链接。客户端对这个函数进行多次调用是合法的。     InitializeNativeTarget();     //主程序应该调用此函数来初始化本机目标asm打印机     InitializeNativeTargetAsmPrinter();     //InitializeNativeTargetAsmParser――主程序应该调用这个函数来初始化本机目标asm解析器。     InitializeNativeTargetAsmParser();

还有下面的代码

 std::unique_ptr<Module> Owner = make_unique<Module>("my compiler", *llvmcx);     Module_Ob = Owner.get();      std::string ErrStr;     TheExecutionEngine =     EngineBuilder(std::move(Owner))     .setErrorStr(&ErrStr)     .setMCJITMemoryManager(llvm::make_unique<SectionMemoryManager>())     .create();

最后修改顶级表达式的解析器,修改为如下所示

//封装的函数 static void HandleTopExpression() {     if(FunctionDefnAST *F = top_level_parser()) {         if(Function *LF = F->Codegen()) {             TheExecutionEngine->finalizeObject();             void *FPtr = TheExecutionEngine->getPointerToFunction(LF);              double (*FP)() = (double (*)())(intptr_t)FPtr;             fprintf(stderr, "Evaluated to %f\n", FP());         }     }     else {         next_token();     } }

去分析4+5;的表达式,得到的结果如下所示

Evaluated to 0.000000 ; ModuleID = 'my compiler' source_filename = "my compiler" target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"  define i32 @0() { entry:   ret i32 9 }

LLVM当中的JIT编译器会匹配本机的ABI平台,它会把得到的指针转成相应类型的函数指针,然后直接去调用,这样JIT编译得到的代码与静态编译链接的本地机器码没有区别

关于ABI平台其实就是应用程序二进制接口(ABI-Application Binary Interface)定义了一组在PowerPC系统软件上编译应用程序所需要遵循的一套规则。主要包括基本数据类型,通用寄存器的使用,参数的传递规则,以及堆栈的使用等等

ABI涵盖了各种细节:如数据类型、大小和对齐;调用约定(控制着函数的参数如何传送以及如何接受返回值);系统调用的编码和一个应用如何向操作系统进行系统调用;以及在一个完整的操作系统ABI中,目标文件的二进制格式、程序库等等。一个完整的ABI,像Intel二进制兼容标准 (iBCS)[1] ,允许支持它的操作系统上的程序不经修改在其他支持此ABI的操作体统上运行

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!