编译器 llvm clang 源码转换示例

编译器  llvm  clang  源码转换示例 

从git获取llvm项目的源码方式:

git clone https://github.com/llvm/llvm-project.git

下载源码后,进入llvm-project目录包括如下内容:

 

 

 llvm-project/llvm目录包括如下内容:

 

 

 

  CLANG实战

实战 利用Clang制作自己的编译器 source-to-source 源代码转换

参考:

https://github.com/Ewenwan/llvm-clang-samples/blob/master/src_clang/tooling_sample.cpp

void foo(int* a, int *b) {

  if (a[0] > 1)

  {

    b[0] = 2;

  }

}

void bar(float x, float y); // just a declaration

自动添加 添加注释

// Begin function foo returning void

void foo(int* a, int *b) {

  if (a[0] > 1) // the 'if' part

  {

    b[0] = 2;

  }

}

// End function foo

void bar(float x, float y); // just a declaration

LLVM实战

函数签名

C语言中的函数签名由以下几部分组成:

  • 返回类型
  • 函数名
  • 参数个数及参数类型

比如

 
 
 
 
 

    
 
 
 

}

这段C程序代码中的add函数的函数签名就是int add(int, int)

待处理的C程序代码

#include <stdio.h>
#include <stdlib.h>
 
 
 

    

}
 
 
 
 
 
 

    
 
 
 

}
 
 
 
 

    
 
 
 

}
 
 
 
 
 
 

    
 

}

项目运行结果是

 

 

 在待处理的代码中定义了包括main函数在内的四个函数,但是最终结果却是六个函数,这是因为调用了C标准库中的printf函数和malloc函数,编译器在预处理阶段将这两个函数的声明加入到了代码中。

另外一个值得关注之处是,与C语言中intchar等类型不同,打印出来的函数签名中的类型是i32i8,这其实是因为我们首先需要把待处理的C程序代码转换为LLVM IR字节码,然后才会用自定义LLVM项目对其进行处理,打印出来的类型其实是LLVM IR的类型,除此之外,long对应i64float对应f32double对应f64,不过LLVM IR void和指针两种类型还是与C语言相同的。

函数签名

C语言中的函数签名由以下几部分组成:

返回类型 函数名 (参数个数及参数类型)

// 本程序 输入 llvm IR文件 输出 IR中的函数签名
// 输入的IR文件 可以由clang编译得到
// 例如 clang -emit-llvm -c test.c -o test.bc // test.c为测试程序
// 本程序编译命令
// clang++ $(llvm-config --cxxflags --ldflags --libs) main.cpp -o main
// 运行程序
// ./main test.bc
 
// 引入相关LLVM头文件
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/Module.h>
#include <llvm/IRReader/IRReader.h>
#include <llvm/Support/SourceMgr.h>
#include <llvm/Support/CommandLine.h>
 
using namespace llvm

 
// LLVM上下文全局变量
 ManagedStatic
LLVMContext
 GlobalContext

 
// 命令行位置参数全局变量, 这个参数的含义是需要处理的LLVM IR字节码的文件名
 cl
opt
std
string
 
cl
Positional
 cl
 cl
Required

 
 
 argc
 
 
argv
 

    

    SMDiagnostic Err

    

    cl
argc
 argv

    

    std
unique_ptr
Module
 M 
 
InputFilename
 Err
 
GlobalContext

    

    
 
M
 

        Err
argv
 

        
 

    

    

    
 
Function 
F
M
 
 

        

        
 
F
 

            

            
 
 
F

            

            
 
 
 
 F
 
 
 

            

            
 
Function
arg_iterator it 
 F
 ie 
 F
 it 
 ie
 it
 

                

                
 
 
it

                
 
it 
 ie 
 
 

                    
 
 

                

            

            
 
 

        

    

}

项目编译运行

在编译项目之前,需要确认一下编译运行环境 :

Ÿ   操作系统:Ubuntu 18.04 64位

Ÿ   LLVM版本:9.0.0

Ÿ   待处理的C程序代码文件:test.c

Ÿ   项目代码文件:main.cpp

然后获取待处理的C程序代码的LLVM IR字节码

clang -emit-llvm -c test.c -o test.bc

再编译项目代码

clang++ 
llvm-config --cxxflags --ldflags --libs
 main.cpp -o main

最后运行得到上文图示的结果

./main test.bc

 

参考链接:

https://www.freesion.com/article/3548547366/

https://www.freesion.com/article/4240352588/

https://zhuanlan.zhihu.com/p/102270840

https://github.com/Ewenwan/llvm-clang-samples/blob/master/src_clang/tooling_sample.cpp

 

posted @   吴建明wujianming  阅读(297)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示