LLVM(5)ORC实例分析

2023-10-15 16:30
文章标签 分析 实例 llvm orc

本文主要是介绍LLVM(5)ORC实例分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ORC实例总结

总结

  1. 因为API茫茫多,逻辑上的一些概念需要搞清,编码时会容易很多。
  2. JIT的运行实体使用LLVMOrcCreateLLJIT可以创建出来,逻辑上的JIT实例。
  3. JIT实例需要加入运行库(依赖库)和用户定义的context(运行内容)才能运行,LLVMOrcLLJITAddLLVMIRModule函数负责将运行库和ctx加入JIT实例。
  4. context相当于给用户自定义代码的上下文,其中可以加入多个module,每个module中又可以加入多个function。可以理解为一个工程(context)里面加入多个文件,每个文件(module)中又包含多个函数(function)。

请添加图片描述

注释

LLVMOrcThreadSafeModuleRef createDemoModule(void) {
// 创建一个新的ThreadSafeContext和底层的LLVMContext。
LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();// 获取底层的LLVMContext的引用。
LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);// 创建一个新的LLVM模块。
LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx);// 添加一个名为"sum"的函数:
// - 创建函数类型和函数实例。
LLVMTypeRef ParamTypes[] = {LLVMInt32Type(), LLVMInt32Type()};
LLVMTypeRef SumFunctionType =
LLVMFunctionType(LLVMInt32Type(), ParamTypes, 2, 0);
LLVMValueRef SumFunction = LLVMAddFunction(M, "sum", SumFunctionType);// - 向函数添加一个基本块。
LLVMBasicBlockRef EntryBB = LLVMAppendBasicBlock(SumFunction, "entry");// - 创建一个IR构建器并将其定位到基本块的末尾。
LLVMBuilderRef Builder = LLVMCreateBuilder();
LLVMPositionBuilderAtEnd(Builder, EntryBB);// - 获取两个函数参数,并使用它们构造一个"add"指令。
LLVMValueRef SumArg0 = LLVMGetParam(SumFunction, 0);
LLVMValueRef SumArg1 = LLVMGetParam(SumFunction, 1);
LLVMValueRef Result = LLVMBuildAdd(Builder, SumArg0, SumArg1, "result");// - 构建返回指令。
LLVMBuildRet(Builder, Result);// 演示模块现在已经完成。将其和ThreadSafeContext封装到ThreadSafeModule中。
LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);// 释放本地的ThreadSafeContext值。底层的LLVMContext将由ThreadSafeModule TSM保持活动状态。
LLVMOrcDisposeThreadSafeContext(TSCtx);// 返回结果。
return TSM;
}int main(int argc, char *argv[]) {
int MainResult = 0;// 解析命令行参数并初始化LLVM Core。
LLVMParseCommandLineOptions(argc, (const char **)argv, "");
LLVMInitializeCore(LLVMGetGlobalPassRegistry());// 初始化本地目标代码生成和汇编打印器。
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();// 创建LLJIT实例。
LLVMOrcLLJITRef J;
{
LLVMErrorRef Err;
if ((Err = LLVMOrcCreateLLJIT(&J, 0))) {
MainResult = handleError(Err);
goto llvm_shutdown;
}
}// 创建演示模块。
LLVMOrcThreadSafeModuleRef TSM = createDemoModule();// 将演示模块添加到JIT中。
{
LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);
LLVMErrorRef Err;
if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, TSM))) {
// 如果添加ThreadSafeModule失败,我们需要自己清理它。
// 如果添加成功,JIT将管理内存。
LLVMOrcDisposeThreadSafeModule(TSM);
MainResult = handleError(Err);
goto jit_cleanup;
}
}// 查找演示入口点的地址。
LLVMOrcJITTargetAddress SumAddr;
{
LLVMErrorRef Err;
if ((Err = LLVMOrcLLJITLookup(J, &SumAddr, "sum"))) {
MainResult = handleError(Err);
goto jit_cleanup;
}
}// 如果程序执行到这里,说明一切顺利。执行JIT生成的代码。
int32_t (Sum)(int32_t, int32_t) = (int32_t()(int32_t, int32_t))SumAddr;
int32_t Result = Sum(1, 2);// 打印结果。
printf("1 + 2 = %i\n", Result);jit_cleanup:
// 销毁JIT实例。这将清理JIT所拥有的任何内存。
// 这个操作是非平凡的(例如,可能需要JIT静态析构函数),也可能失败。
// 如果失败,我们希望将错误输出到stderr,但不要覆盖任何现有的返回值。
{
LLVMErrorRef Err;
if ((Err = LLVMOrcDisposeLLJIT(J))) {
int NewFailureResult = handleError(Err);
if (MainResult == 0) MainResult = NewFailureResult;
}
}llvm_shutdown:
// 关闭LLVM。
LLVMShutdown();return MainResult;
}

ORC完整

//===------ OrcV2CBindingsBasicUsage.c - Basic OrcV2 C Bindings Demo ------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//#include <stdio.h>#include "llvm-c/Core.h"
#include "llvm-c/Error.h"
#include "llvm-c/Initialization.h"
#include "llvm-c/LLJIT.h"
#include "llvm-c/Support.h"
#include "llvm-c/Target.h"int handleError(LLVMErrorRef Err) {char *ErrMsg = LLVMGetErrorMessage(Err);fprintf(stderr, "Error: %s\n", ErrMsg);LLVMDisposeErrorMessage(ErrMsg);return 1;
}LLVMOrcThreadSafeModuleRef createDemoModule(void) {// Create a new ThreadSafeContext and underlying LLVMContext.LLVMOrcThreadSafeContextRef TSCtx = LLVMOrcCreateNewThreadSafeContext();// Get a reference to the underlying LLVMContext.LLVMContextRef Ctx = LLVMOrcThreadSafeContextGetContext(TSCtx);// Create a new LLVM module.LLVMModuleRef M = LLVMModuleCreateWithNameInContext("demo", Ctx);// Add a "sum" function"://  - Create the function type and function instance.LLVMTypeRef ParamTypes[] = {LLVMInt32Type(), LLVMInt32Type()};LLVMTypeRef SumFunctionType =LLVMFunctionType(LLVMInt32Type(), ParamTypes, 2, 0);LLVMValueRef SumFunction = LLVMAddFunction(M, "sum", SumFunctionType);//  - Add a basic block to the function.LLVMBasicBlockRef EntryBB = LLVMAppendBasicBlock(SumFunction, "entry");//  - Add an IR builder and point it at the end of the basic block.LLVMBuilderRef Builder = LLVMCreateBuilder();LLVMPositionBuilderAtEnd(Builder, EntryBB);//  - Get the two function arguments and use them co construct an "add"//    instruction.LLVMValueRef SumArg0 = LLVMGetParam(SumFunction, 0);LLVMValueRef SumArg1 = LLVMGetParam(SumFunction, 1);LLVMValueRef Result = LLVMBuildAdd(Builder, SumArg0, SumArg1, "result");//  - Build the return instruction.LLVMBuildRet(Builder, Result);// Our demo module is now complete. Wrap it and our ThreadSafeContext in a// ThreadSafeModule.LLVMOrcThreadSafeModuleRef TSM = LLVMOrcCreateNewThreadSafeModule(M, TSCtx);// Dispose of our local ThreadSafeContext value. The underlying LLVMContext// will be kept alive by our ThreadSafeModule, TSM.LLVMOrcDisposeThreadSafeContext(TSCtx);// Return the result.return TSM;
}int main(int argc, char *argv[]) {int MainResult = 0;// Parse command line arguments and initialize LLVM Core.LLVMParseCommandLineOptions(argc, (const char **)argv, "");LLVMInitializeCore(LLVMGetGlobalPassRegistry());// Initialize native target codegen and asm printer.LLVMInitializeNativeTarget();LLVMInitializeNativeAsmPrinter();// Create the JIT instance.LLVMOrcLLJITRef J;{LLVMErrorRef Err;if ((Err = LLVMOrcCreateLLJIT(&J, 0))) {MainResult = handleError(Err);goto llvm_shutdown;}}// Create our demo module.LLVMOrcThreadSafeModuleRef TSM = createDemoModule();// Add our demo module to the JIT.{LLVMOrcJITDylibRef MainJD = LLVMOrcLLJITGetMainJITDylib(J);LLVMErrorRef Err;if ((Err = LLVMOrcLLJITAddLLVMIRModule(J, MainJD, TSM))) {// If adding the ThreadSafeModule fails then we need to clean it up// ourselves. If adding it succeeds the JIT will manage the memory.LLVMOrcDisposeThreadSafeModule(TSM);MainResult = handleError(Err);goto jit_cleanup;}}// Look up the address of our demo entry point.LLVMOrcJITTargetAddress SumAddr;{LLVMErrorRef Err;if ((Err = LLVMOrcLLJITLookup(J, &SumAddr, "sum"))) {MainResult = handleError(Err);goto jit_cleanup;}}// If we made it here then everything succeeded. Execute our JIT'd code.int32_t (*Sum)(int32_t, int32_t) = (int32_t(*)(int32_t, int32_t))SumAddr;int32_t Result = Sum(1, 2);// Print the result.printf("1 + 2 = %i\n", Result);jit_cleanup:// Destroy our JIT instance. This will clean up any memory that the JIT has// taken ownership of. This operation is non-trivial (e.g. it may need to// JIT static destructors) and may also fail. In that case we want to render// the error to stderr, but not overwrite any existing return value.{LLVMErrorRef Err;if ((Err = LLVMOrcDisposeLLJIT(J))) {int NewFailureResult = handleError(Err);if (MainResult == 0) MainResult = NewFailureResult;}}llvm_shutdown:// Shut down LLVM.LLVMShutdown();return MainResult;
}

这篇关于LLVM(5)ORC实例分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/218372

相关文章

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

MySQL中的表连接原理分析

《MySQL中的表连接原理分析》:本文主要介绍MySQL中的表连接原理分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、环境3、表连接原理【1】驱动表和被驱动表【2】内连接【3】外连接【4编程】嵌套循环连接【5】join buffer4、总结1、背景

java向微信服务号发送消息的完整步骤实例

《java向微信服务号发送消息的完整步骤实例》:本文主要介绍java向微信服务号发送消息的相关资料,包括申请测试号获取appID/appsecret、关注公众号获取openID、配置消息模板及代码... 目录步骤1. 申请测试系统2. 公众号账号信息3. 关注测试号二维码4. 消息模板接口5. Java测试

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

python中Hash使用场景分析

《python中Hash使用场景分析》Python的hash()函数用于获取对象哈希值,常用于字典和集合,不可变类型可哈希,可变类型不可,常见算法包括除法、乘法、平方取中和随机数哈希,各有优缺点,需根... 目录python中的 Hash除法哈希算法乘法哈希算法平方取中法随机数哈希算法小结在Python中,

Java Stream的distinct去重原理分析

《JavaStream的distinct去重原理分析》Javastream中的distinct方法用于去除流中的重复元素,它返回一个包含过滤后唯一元素的新流,该方法会根据元素的hashcode和eq... 目录一、distinct 的基础用法与核心特性二、distinct 的底层实现原理1. 顺序流中的去重

关于MyISAM和InnoDB对比分析

《关于MyISAM和InnoDB对比分析》:本文主要介绍关于MyISAM和InnoDB对比分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录开篇:从交通规则看存储引擎选择理解存储引擎的基本概念技术原理对比1. 事务支持:ACID的守护者2. 锁机制:并发控制的艺

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部