手工将一个 llvm IR 汇编代码解析成为 bitcode 文件

2024-03-06 21:20

本文主要是介绍手工将一个 llvm IR 汇编代码解析成为 bitcode 文件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1,原始c语言文件

sum.c

int sum(int a, int b)
{return a+b;
}

2,编译成为 LLVM-IR 汇编语言

clang sum.c -emit-llvm -S -c -o sum.ll

3,手工把 llvm IR 汇编语言解析成 bitcode

3.1,源码

gen_llvm_ir.cpp

#include <llvm/ADT/SmallVector.h>
#include <llvm/IR/BasicBlock.h>
#include <llvm/IR/CallingConv.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/Bitcode/ReaderWriter.h>
#include <llvm/Support/FileSystem.h>
#include <llvm/Support/ToolOutputFile.h>
using namespace llvm;//手工解析 sum.ll 成为 bitcode
Module *makeLLVMModule() 
{Module *mod = new Module("sum.ll", getGlobalContext());SmallVector<Type*, 2> FuncTyArgs;FuncTyArgs.push_back(IntegerType::get(mod->getContext(), 32));FuncTyArgs.push_back(IntegerType::get(mod->getContext(), 32));FunctionType *FuncTy = FunctionType::get(IntegerType::get(mod->getContext(), 32), FuncTyArgs, false);// define function sum return type;Function *funcSum =	Function::Create(FuncTy, GlobalValue::ExternalLinkage, "sum", mod);//define Function objectfuncSum->setCallingConv(CallingConv::C);Function::arg_iterator args = funcSum->arg_begin();// define arguments of sum()Value *int32_a = args++;int32_a->setName("a");// name the first argumentValue *int32_b = args++;int32_b->setName("b");// name the second argumentBasicBlock *labelEntry = BasicBlock::Create(mod->getContext(), "entry", funcSum, 0);// define entry of function AllocaInst *ptrA = new AllocaInst(IntegerType::get(mod->getContext(), 32), "a.addr", labelEntry); // %a.addr = alloca i32, align 4ptrA->setAlignment(4);AllocaInst *ptrB = new AllocaInst(IntegerType::get(mod->getContext(), 32), "b.addr", labelEntry); // %b.addr = alloca i32, align 4ptrB->setAlignment(4);StoreInst *st0 = new StoreInst(int32_a, ptrA, false, labelEntry);// store i32 %a, i32* %a.addr, align 4st0->setAlignment(4);StoreInst *st1 = new StoreInst(int32_b, ptrB, false, labelEntry);// store i32 %b, i32* %b.addr, align 4st1->setAlignment(4);LoadInst *ld0 = new LoadInst(ptrA, "", false, labelEntry);// %0 = load i32* %a.addr, align 4ld0->setAlignment(4);LoadInst *ld1 = new LoadInst(ptrB, "", false, labelEntry);// %1 = load i32* %b.addr, align 4ld1->setAlignment(4);BinaryOperator *addRes = BinaryOperator::Create(Instruction::Add, ld0, ld1,	"add", labelEntry);//%add = add msw i32 %0, %1ReturnInst::Create(mod->getContext(), addRes, labelEntry);// ret i32 %addreturn mod;
}int main(int argc, char **argv) 
{Module *Mod = makeLLVMModule();std::string ErrorInfo;std::unique_ptr<tool_output_file> Out(new tool_output_file("./sum.bc", ErrorInfo, sys::fs::F_None));if (!ErrorInfo.empty()) {errs() << ErrorInfo << "\n";return -1;}WriteBitcodeToFile(Mod, Out->os());Out->keep();return 0;
}

Makefile

LLVM_CONFIG ?= llvm-config
#CXX := clang++
ifndef VERBOSE
QUIET :=@
endifSRC_DIR ?= $(PWD)
LDFLAGS += $(shell $(LLVM_CONFIG) --ldflags) 
COMMON_FLAGS = -Wall -Wextra
CXXFLAGS += $(COMMON_FLAGS) $(shell $(LLVM_CONFIG) --cxxflags)
LCXX :=$(shell $(LLVM_CONFIG) --cxxflags)
CPPFLAGS += $(shell $(LLVM_CONFIG) --cppflags) -I$(SRC_DIR)CLANGLIBS = \-Wl,--start-group \-lclang \-lclangFrontend \-lclangDriver \-lclangSerialization \-lclangParse \-lclangSema \-lclangAnalysis \-lclangEdit \-lclangAST \-lclangLex \-lclangBasic \-Wl,--end-groupLLVMLIBS = $(shell $(LLVM_CONFIG) --libs)PROJECT = gen_llvm_ir
PROJECT_OBJECTS = gen_llvm_ir.odefault: $(PROJECT)%.o : $(SRC_DIR)/%.cpp@echo Compiling $*.cpp$(QUIET)$(CXX) -c $(CPFLAGS) $(CXXFLAGS) $<$(PROJECT) : $(PROJECT_OBJECTS) @echo Linking $@$(QUIET)$(CXX) -o $@ $(LDFLAGS) $^ $(CLANGLIBS) $(LLVMLIBS) -lncurses.PHONY: clean
clean:$(QUIET)rm -f $(PROJECT) $(PROJECT_OBJECTS).PHONY: echo
echo:@echo "CXX 	is	$(CXX)"@echo "LDFLAGS 	is	$(LDFLAGS)}"@echo "CXXFLAGS	is	$(CXXFLAGS)"@echo "CPPFLAGS	is	$(CPPFLAGS)"@echo "SRC_DIR	is	$(SRC_DIR)"

3.2,测试

注意:

使用 llvm-dis 出来的 sum.ll 文件中,最后的%add = add i32 %0, %1中,没有nsw关键字。

这篇关于手工将一个 llvm IR 汇编代码解析成为 bitcode 文件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/781397

相关文章

MySQL 添加索引5种方式示例详解(实用sql代码)

《MySQL添加索引5种方式示例详解(实用sql代码)》在MySQL数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中,下面给大家分享MySQL添加索引5种方式示例详解(实用sql代码),... 在mysql数据库中添加索引可以帮助提高查询性能,尤其是在数据量大的表中。索引可以在创建表时定义,也可

Mybatis Plus JSqlParser解析sql语句及JSqlParser安装步骤

《MybatisPlusJSqlParser解析sql语句及JSqlParser安装步骤》JSqlParser是一个用于解析SQL语句的Java库,它可以将SQL语句解析为一个Java对象树,允许... 目录【一】jsqlParser 是什么【二】JSqlParser 的安装步骤【三】使用场景【1】sql语

使用C#删除Excel表格中的重复行数据的代码详解

《使用C#删除Excel表格中的重复行数据的代码详解》重复行是指在Excel表格中完全相同的多行数据,删除这些重复行至关重要,因为它们不仅会干扰数据分析,还可能导致错误的决策和结论,所以本文给大家介绍... 目录简介使用工具C# 删除Excel工作表中的重复行语法工作原理实现代码C# 删除指定Excel单元

SpringBoot整合Sa-Token实现RBAC权限模型的过程解析

《SpringBoot整合Sa-Token实现RBAC权限模型的过程解析》:本文主要介绍SpringBoot整合Sa-Token实现RBAC权限模型的过程解析,本文给大家介绍的非常详细,对大家的学... 目录前言一、基础概念1.1 RBAC模型核心概念1.2 Sa-Token核心功能1.3 环境准备二、表结

Python实现一键PDF转Word(附完整代码及详细步骤)

《Python实现一键PDF转Word(附完整代码及详细步骤)》pdf2docx是一个基于Python的第三方库,专门用于将PDF文件转换为可编辑的Word文档,下面我们就来看看如何通过pdf2doc... 目录引言:为什么需要PDF转Word一、pdf2docx介绍1. pdf2docx 是什么2. by

Spring Security介绍及配置实现代码

《SpringSecurity介绍及配置实现代码》SpringSecurity是一个功能强大的Java安全框架,它提供了全面的安全认证(Authentication)和授权(Authorizatio... 目录简介Spring Security配置配置实现代码简介Spring Security是一个功能强

Java 关键字transient与注解@Transient的区别用途解析

《Java关键字transient与注解@Transient的区别用途解析》在Java中,transient是一个关键字,用于声明一个字段不会被序列化,这篇文章给大家介绍了Java关键字transi... 在Java中,transient 是一个关键字,用于声明一个字段不会被序列化。当一个对象被序列化时,被

通过cmd获取网卡速率的代码

《通过cmd获取网卡速率的代码》今天从群里看到通过bat获取网卡速率两段代码,感觉还不错,学习bat的朋友可以参考一下... 1、本机有线网卡支持的最高速度:%v%@echo off & setlocal enabledelayedexpansionecho 代码开始echo 65001编码获取: >

Java集成Onlyoffice的示例代码及场景分析

《Java集成Onlyoffice的示例代码及场景分析》:本文主要介绍Java集成Onlyoffice的示例代码及场景分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 需求场景:实现文档的在线编辑,团队协作总结:两个接口 + 前端页面 + 配置项接口1:一个接口,将o

SpringBoot实现Kafka动态反序列化的完整代码

《SpringBoot实现Kafka动态反序列化的完整代码》在分布式系统中,Kafka作为高吞吐量的消息队列,常常需要处理来自不同主题(Topic)的异构数据,不同的业务场景可能要求对同一消费者组内的... 目录引言一、问题背景1.1 动态反序列化的需求1.2 常见问题二、动态反序列化的核心方案2.1 ht