C以及Rust编译的过程

  • 主流的编译器
    • GCC
    • LLVM
  • C语言编译过程
    • LLVM编译过程
      • 将C源码转为LLVM IR
      • 将IR转化为BitCode
      • 将BitCode转为目标平台汇编码
      • 执行BitCode
  • Rust编译过程
  • 下一步做什么

主流的编译器

GCC

GCC编译器是由GNU开发的编译器,原名为GUN编译器,原本只能处理C语言随着发展,后续支持了C++,Java,Go等语言,所以改名为GNU编译器套件,GCC主要分为以下接口

  1. 前端接口: 将源码经过词法分析,语法分析生成与语言无关的低级中间语言表示层,然后经过优化后转化为RTL中间表示层
  2. 中间接口: 中间接口主要在RTL中间表示上进行各种优化,如循环优化,公共子表达式删除,指令重排等等
  3. 后端接口:GCC对每条RTL通过模板匹配方法调用对应的汇编模板生成汇编代码,生成的代码因处理器的不同而不同

LLVM

LLVM由C++编写,用于优化任意语言编写的程序,LLVM的命名最早源于Low Level Virtual Machine的缩写,LLVM代码有3种表示形式,IR,bitcode,汇编码,llvm提供了不同的优化Pass,对每个Pass的源码编译,得到一个Object文件,之后这些文件链接得到一个库,Pass之间由LLVM Pass管理器来统一管理
LLVM有很多其项目其中包括 LLVM Core libraries,ClangLLD,LLDB,libc++ & libc++ ABI等等

C语言编译过程

一般的编译过程流程图大概是这样的

编译
汇编器
链接器
源代码
汇编语言
目标文件
可执行文件

但是不同的编译器有着不同的编译方式,下面我们使用LLVM对C语言编译的过程进行实践

LLVM编译过程

clang
llvm-as
llc
main.c
main.ll IR文件
main.bc bitCode
目标平台汇编码

我们开始准备LLVM的一些环境

  • llvm
  • llvm-as(Windows 安装llvm时没有这个文件,打开网站后输入llvm-as.exe搜索下载)
  • llc (同llvm-as)

首先我们创建一个test.c文件然后输入以下内容

int mult() {int a = 5; int b = 3; int c = a * b;return c;
}

将C源码转为LLVM IR

输入一下命令

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

其中我们使用了clang作为前端进行编译,-emit-llvm用于LLVM IR写到.ll文件,-S表示仅运行预处理和编译步骤,-o参数用于将生成的内容输出到test.ll文件中

执行完毕后会在test.c同级目录下生成一个test.ll文件,将C语言代码分解为Token流(每个Token可表示标识符,字面量,运算符等等),Token流会传递给语法分析器,语法分析器使用CFG(上下文无关文法)组织成AST(抽象语法树),紧接着进行语义分析,然后生成IR

将IR转化为BitCode

我们使用一个较为简单的IR文件,内容如下

// test.ll
define i32 @mult(i32 %a, i32 %b) #0 { %1 = mul nsw i32 %a, %b  ret i32 %1
}

使用命令如下

llvm-as test.ll -o test.bc

我们使用llvm-as(LLVM汇编器)将LLVM IR转为BitCode,-o参数用于将生成的BitCode输出到test.bc文件中

将BitCode转为目标平台汇编码

我们使用LLVM的静态编译器LLC把BitCode转为汇编码,命令如下

llc test.bc -o test.s

或者我们可以使用Clang从BitCode文件生成汇编码,命令如下

clang -S test.bc -o test.s -fomit-frame-pointer

我们使用了fomit-frame-pointer参数消除帧指针,因为Clang默认不消除帧指针,但是llc却默认消除帧指针

llc命令把LLVM的BitCode编译为指定架构的汇编语言,如果命令中没有指定任何架构默认生成的本机汇编码

执行BitCode

我们把test.c的内容换为以下内容

#include<stdio.h> int main(){int num = 5; printf("number is %d\n", num); return 0;
}

然后我们按照之前的步骤将test.c转为BitCode

$ clang -emit-llvm -S test.c -o test.ll
$ llvm-as test.ll -o test.bc

注: 在Windows执行第2步是会出现以下错误
llvm-as: test.ll:31:62: error: expected ‘global’ or ‘constant’
@"??_C@_0O@BAPFBKAP@number?5is?5?CFd?6?CFd?6?CFd?6?AA@" = linkonce_odr dso_local unnamed_addr constant [14 x i8] c"number is %d\0A\00", comdat, align 1
错误原因等待解决

最后我们使用LLI命令来运行BitCode

$ lli test.bc

LLI使用LLVM bitcode格式 作为输入并且使用即时编译器(JIT)执行,如果当前的架构不 存在JIT编译器,会用解释器执行

Rust编译过程

Rust使用的是rustc进行编译,编译的过程如下

语法分析,宏扩展
类型检查
转换
LLVM
链接
RustCode
HIR
MIR
LLVM IR
.o文件
可执行程序

详细过程如下

  1. 解析输入:将.rs文件作为输入并进行解析生成AST(抽象语法树)
  2. 名称解析,宏扩展和属性配置:解析完毕后处理AST,处理#[cfg]节点解析路径,扩展宏
  3. 转为HIR:名称解析完毕后将AST转换为HIR(高级中间表示),HIR比AST处理的更多,但是他不负责解析Rust的语法,例如((1+2)+3)1+2+3在AST中会保留括号,虽然两者的含义相同但是会被解析成不同的树,但是在HIR中括号节点将会被删除,这两个表达式会以相同的方式表达
  4. 类型检查以及后续分析:处理HIR的重要步骤就是类型检查,例如使用x.f时如果我们不知道x的类型就无法判断访问的哪个f字段,类型检查会创建TypeckTables其中包括表达式的类型,方法的解析方式
  5. 转为MIR以及后置处理:完成类型检查后,将HIR转为MIR(中级中间表示)进行借用检查以及优化
  6. 转为LLVM IR和优化:LLVM进行优化,从而生成许多.o文件
  7. 链接: 最后将那些.o文件链接在一起

我们开始实践这一过程

首先我们创建一个Cargo项目

~$ cargo new complier_test

main.rs文件中的内容如下

fn main(){println!("Hello");
}

将源代码转为HIR
我们可以使用cargo的 -Zunpretty参数来生成hir,rustc命令没有找到。。

~/complier_test$ cargo rustc -- -Zunpretty=hir-tree -o main.hir

然后在src目录下会生成main.hir文件

将源代码转为MIR
转为mir的过程我们可以使用rustc来完成

~/complier_test/src$ rustc --emit mir  -o main.mir main.rs

我们使用emit来生成emit用来生成mir,除此之外还可以使用emit来生成LLVM IR

~/complier_test/src$ rustc --emit llvm-ir -o main.ll main.rs

转换为BitCode

然后我们可以使用llvm-as将IR转为BitCode

~/complier_test/src$ llvm-as main.ll -o main.bc

或者我们可以使用rustc的emit参数生成

~/complier_test/src$ rustc --emit llvm-bc -o main.bc

最后我们可以使用LLI来运行BitCode

~/complier_test/src$ lli main.bc

下一步做什么

在下一篇文章我们使用Rust实现一个分词器,我们还需要掌握一些关于分词的理论知识

使用Rust开发编译系统(C以及Rust编译的过程)相关推荐

  1. c语言程序链接过程,C语言简明教程(二):C程序编译链接过程和实例对照详解...

    不像高级编程语言,在C语言开发中,了解其编译链接过程显得相对重要,因为C语言是较为底层的语言,很多时候我们调试C程序或者解决其它问题都可能会涉及到C编译链接的相关知识,例如编译动态库或者静态库.下面我 ...

  2. [译]使用 Rust 开发一个简单的 Web 应用,第 4 部分 —— CLI 选项解析

    原文地址:A Simple Web App in Rust, Part 4 -- CLI Option Parsing 原文作者:Joel's Journal 译文出自:掘金翻译计划 本文永久链接:g ...

  3. 百度安全 TrustZone SDK 正式成为 OP-TEE 官方推荐 Rust 开发环境

    百度安全与 OP-TEE 社区共同合作,推进 Teacalve TrustZone SDK 正式成为 OP-TEE 官方推荐的 Rust 开发环境.OP-TEE 是当今广泛使用的开源 ARM Trus ...

  4. rust开发环境_Rust 环境搭建

    Rust 环境搭建 Rust 支持很多的集成开发环境(IDE)或开发专用的文本编辑器. 本教程将使用 Visual Studio Code 作为我们的开发环境(Eclipse 有专用于 Rust 开发 ...

  5. 用 Rust 开发 Linux,可行吗?

    作者 | 马超 出品 | CSDN(ID:CSDNnews) 继Python之后,Rust最近也火爆得出了圈,目前Rust在Serverless等很多云原生领域已经稳定占据了C位,那么让Rust更进一 ...

  6. rust开发环境_Rust开发环境搭建

    1.Rust概述 按照百度百科的说法,Rust是一门系统编程语言 ,专注于安全 ,尤其是并发安全,支持函数式和命令式以及泛型等编程范式的多范式语言.Rust在语法上和C++类似 ,但是设计者想要在保证 ...

  7. mac10.11+vim rust开发环境搭建

    mac10.11+vim rust开发环境搭建 1.安装rust 打开终端 输入如下命令 curl -sf -L https://static.rust-lang.org/rustup.sh | sh ...

  8. Rust开发调试环境搭建Windows

    Rust Windows环境搭建 2019年02月18日 13:48:31 6日Simmp 阅读数 1672 该文章主要讲述在windows10+vscode下如何构建一个完整的rust编译调试环境, ...

  9. ios 腐蚀rust手游_用 Rust 开发 iOS 应用(粗糙版)

    把环境搞定 在搞事情之前, 我们先把 Rust 环境配好, 这个很简单, 直接用官网的这条命令. curl https://sh.rustup.rs -sSf | sh 复制代码 随便装一个版本, 稳 ...

最新文章

  1. 努力过头了,其实并不好
  2. LeetCode 295. 数据流的中位数(大小堆)
  3. cocos 制作动态生成内容的列表_零代码工具,让你在线轻松制作交互内容!
  4. (转)C++优先队列中元素及结构体的排序
  5. wince6.0远程控制工具_用微信远程控制你的电脑,这个工具又加了一些小功能(硬件+软件)...
  6. 面试题|集合ArrayList list = new ArrayList(20) 中的list扩充几次?
  7. 金蝶计算机会计实验报告总结,会计实训总结(精选5篇)
  8. 如何注册电子邮箱账号,教你创建email邮箱账号
  9. Django+bootstrap启动登录模板页面(Django第三篇)
  10. seo关键词优化技巧是什么
  11. 如何区分自己mac电脑的CUP型号
  12. ggalluvial:冲击图展示组间变化、时间序列和复杂多属性alluvial diagram
  13. destoon7.0第三方短信插件下载 destoon7.0整合云信通短信平台教程
  14. 【kali-漏洞利用】(3.4)Metasploit渗透攻击应用:MySQL渗透过程
  15. 计算机毕业设计php+vue基于微信小程序的叽喳音乐播放小程序
  16. 简单保护动物网页制作stu-works.com学生保护动物网页设计作品HTML 濒危动物静态网页成品下载
  17. 一粒云文控模块使用心得
  18. 打造爆文的8个软文营销写作技巧,提升你的文案写作能力
  19. Outlook Express邮件丢失的原因
  20. Android行业薪资现状,月薪2万属于低收入!

热门文章

  1. idea license server 最新可用 IntelliJ IDEA 2018.1 x64 激活 idea license server
  2. 【Linux】 常用命令
  3. 深度暗色调色效果Lr预设
  4. knex入门学习使用方法
  5. 计算机考研复试面试问题总结和回答
  6. FFmpeg从入门到入魔(2):保存流到本地MP4
  7. 华为路由器显示连接到服务器失败怎么办,华为路由WS5200可以搜到wifi但无法连接怎么办...
  8. mysql查询数据量
  9. g.SetGDIHigh()错误
  10. 史上最佳十大游戏排名 魔兽世界位列第十