|
關(guān)注+星標(biāo)公眾號(hào),不錯(cuò)過精彩內(nèi)容
2c0tk5gropu64047606646.jpg (92.58 KB, 下載次數(shù): 0)
下載附件
保存到相冊
2c0tk5gropu64047606646.jpg
2024-10-26 07:33 上傳
作者 | strongerHuang微信公眾號(hào) | 嵌入式專欄
Keil MDK自V5.36版本之后,就“拋棄”了AC5(Arm Compiler 5)編譯器,你會(huì)發(fā)現(xiàn),下載最新版V5.38a,沒有AC5編譯器。
而AC6相較于AC5在編譯速度上有很大的提升,那么,你知道為什么嗎?
原因在于AC6是基于現(xiàn)代LLVM和Clang技術(shù)構(gòu)建而成,今天就來講講AC6和LLVM的編譯原理。
關(guān)于編譯器AC6
早在2015年,Arm就推出了AC6編譯器,并集成在Keil MDK中。但由于AC5和AC6對(duì)代碼的的兼容性不友好,導(dǎo)致很多使用Keil MDK的用戶還是AC5編譯器。
所以兼容性不友好,但AC6的編譯速度相比AC5快很多,因此還是吸引了一部分人使用AC6編譯器。
為什么AC6編譯速度快了很多呢?原因在于AC6使用了一套全新的架構(gòu)技術(shù)。
AC6組件如下圖:
wlatsngrls564047606746.png (64.04 KB, 下載次數(shù): 0)
下載附件
保存到相冊
wlatsngrls564047606746.png
2024-10-26 07:33 上傳
1.armclang基于現(xiàn)代LLVM和Clang技術(shù)構(gòu)建支持GNU語法匯編與最初為GCC編寫的源代碼高度兼容實(shí)現(xiàn)規(guī)范,包括ANSI / ISO C和C ++,用于Arm架構(gòu)的ABI,用于64位Arm架構(gòu)的ABI以及Arm C語言擴(kuò)展(ACLE)
2.armlink功能豐富的專用嵌入式鏈接器,該鏈接器將對(duì)象和庫組合在一起以生成可執(zhí)行文件
3.Arm C庫:由Arm針對(duì)性能和代碼密度進(jìn)行了優(yōu)化,并包括 用于深度嵌入式應(yīng)用程序的微型MicroLib。
4.Arm C++庫:基于LLVM libc ++項(xiàng)目的庫
這部分內(nèi)容可參看:
https://developer.arm.com/tools-and-software/embedded/arm-compiler
Keil MDK 編譯器 AC5 和 AC6 優(yōu)化選項(xiàng)重要內(nèi)容有著很大區(qū)別:ARM Compiler 5(和更早版本)使用armcc編譯器,而ARM Compiler 6將armcc替換為armclang,armclang基于LLVM,它具有不同的命令行參數(shù)、指令等,因此算是一個(gè)新的編譯器。
這里推薦閱讀:
手把手教你Keil MDK編譯器從V5升級(jí)到V6手把手教你升級(jí)Keil MDK的ARM編譯器手把手教你在Keil MDK中使用GCC編譯器工具鏈Keil MDK使用編譯器AC5與AC6生成瀏覽信息的差異
LLVM基礎(chǔ)內(nèi)容
上面我們講到了AC6是基于LLVM,下面就來講講關(guān)于LLVM的內(nèi)容。
1.什么LLVM?
LLVM是構(gòu)架編譯器(compiler)的框架系統(tǒng),以C++編寫而成,用于優(yōu)化以任意程序語言編寫的程序的編譯時(shí)間(compile-time)、鏈接時(shí)間(link-time)、運(yùn)行時(shí)間(run-time)以及空閑時(shí)間(idle-time),對(duì)開發(fā)者保持開放,并兼容已有腳本。
在理解LLVM時(shí),我們可以認(rèn)為它包括了一個(gè)狹義的LLVM和一個(gè)廣義的LLVM。廣義的LLVM其實(shí)就是指整個(gè)LLVM編譯器架構(gòu),包括了前端、后端、優(yōu)化器、眾多的庫函數(shù)以及很多的模塊;而狹義的LLVM其實(shí)就是聚焦于編譯器后端功能(代碼生成、代碼優(yōu)化、JIT等)的一系列模塊和庫。
2.LLVM優(yōu)勢傳統(tǒng)編譯器分三個(gè)階段: 前端(Frontend)-- 優(yōu)化器(Optimizer)-- 后端(Backend)
前端負(fù)責(zé)分析源代碼,可以檢查語法級(jí)錯(cuò)誤,并構(gòu)建針對(duì)語言的抽象語法樹(AST);抽象語法樹可以進(jìn)一步轉(zhuǎn)換為優(yōu)化,最終轉(zhuǎn)為新的表示方式,然后再交給讓優(yōu)化器和后端處理;
最終由后端生成可執(zhí)行的機(jī)器碼。
ylqfrv11ovs64047606846.png (21.56 KB, 下載次數(shù): 0)
下載附件
保存到相冊
ylqfrv11ovs64047606846.png
2024-10-26 07:33 上傳
llvm也分三個(gè)階段,但是設(shè)計(jì)上略微的有些區(qū)別, LLVM不同的就是對(duì)于不同的語言它都提供了同一種中間表示:
esph3ludzxm64047606946.png (60.78 KB, 下載次數(shù): 1)
下載附件
保存到相冊
esph3ludzxm64047606946.png
2024-10-26 07:33 上傳
前端可以使用不同的編譯工具對(duì)代碼文件做詞法分析以形成抽象語法樹AST,然后將分析好的代碼轉(zhuǎn)換成LLVM的中間表示IR(intermediate representation);中間部分的優(yōu)化器只對(duì)中間表示IR操作,通過一系列的pass對(duì)IR做優(yōu)化;后端負(fù)責(zé)將優(yōu)化好的IR解釋成對(duì)應(yīng)平臺(tái)的機(jī)器碼。LLVM的優(yōu)點(diǎn)在于,中間表示IR代碼編寫良好,而且不同的前端語言最終都轉(zhuǎn)換成同一種的IR。
為什么使用三段式設(shè)計(jì)?優(yōu)勢在哪里?首先解決一個(gè)很大的問題:假如有N種語言(C、OC、C++、Swift...)的前端,同時(shí)也有M個(gè)架構(gòu)(模擬器、arm64、x86...)的target,是否就需要N*M個(gè)編譯器?三段式架構(gòu)的價(jià)值就提現(xiàn)出來了,通過共享優(yōu)化器的中轉(zhuǎn),很好的解決了這個(gè)問題。
Clang和LLVM關(guān)系
Clang是一個(gè)C++編寫、基于LLVM、發(fā)布于LLVM BSD許可證下的C/C++/Objective-C/Objective-C++編譯器。那么為什么已經(jīng)有了GCC還要開發(fā)Clang呢?Clang相比于GCC有什么優(yōu)勢呢?
其實(shí),這也是Clang當(dāng)初在設(shè)計(jì)開發(fā)的時(shí)候所主要考慮的原因。Clang是一個(gè)高度模塊化開發(fā)的輕量級(jí)編譯器,它的編譯速度快、占用內(nèi)存小、非常方便進(jìn)行二次開發(fā)。
LVM和Clang的關(guān)系是怎樣的呢。我們將它們對(duì)應(yīng)于傳統(tǒng)的編譯器當(dāng)中的幾個(gè)獨(dú)立的部分,這樣能夠更加方便明確生動(dòng)的表述。
tlt11uoey1v64047607046.png (30.76 KB, 下載次數(shù): 0)
下載附件
保存到相冊
tlt11uoey1v64047607046.png
2024-10-26 07:33 上傳
其實(shí),對(duì)應(yīng)到這個(gè)圖中,我們就可以非常明確的找出它們的對(duì)應(yīng)關(guān)系。LLVM與Clang是C/C++編譯器套件。對(duì)于整個(gè)LLVM的框架來說,包含了Clang,因?yàn)镃lang是LLVM的框架的一部分,是它的一個(gè)C/C++的前端。Clang使用了LLVM中的一些功能,目前知道的就是針對(duì)中間格式代碼的優(yōu)化,或許還有一部分生成代碼的功能。
從源代碼角度來講,clang是基于LLVM的一個(gè)工具。而功能的角度來說,LLVM可以認(rèn)為是一個(gè)編譯器的后端,而clang是一個(gè)編譯器的前端,他們的關(guān)系更加的明了,一個(gè)編譯器前端想要程序最終變成可執(zhí)行文件,是缺少不了對(duì)編譯器后端的介紹的。
LLVM編譯工具鏈編譯流程
使用LLVM的對(duì)一門語言編譯的簡圖如下所示:
ugjbj2vme2564047607146.png (28.9 KB, 下載次數(shù): 1)
下載附件
保存到相冊
ugjbj2vme2564047607146.png
2024-10-26 07:33 上傳
LLVM編譯一個(gè)源文件的過程:預(yù)處理 -> 詞法分析 -> Token -> 語法分析 -> AST -> 代碼生成 -> LLVM IR -> 優(yōu)化 -> 生成匯編代碼 -> Link -> 目標(biāo)文件.
完全需要我們手工,或者依靠其他工具如lex, yacc來做的事情,是從源代碼到token的詞法分析和從token到AST的語法分析;詞法分析的輸出是將源代碼解析成一個(gè)個(gè)的token。這些token就是有類型和值的一些小單元,比如是關(guān)鍵字,還是數(shù)字,還是標(biāo)識(shí)符,從AST轉(zhuǎn)LLVM開始,LLVM就開始提供一系列的工具幫助我們快速開發(fā)。從IR(中間指令代碼)到DAG(有向無環(huán)圖)再到機(jī)器指令,針對(duì)常用的平臺(tái),LLVM有完善的后端。也就是說,我們只要完成了到IR這一步,后面的工作我們就享有和Clang一樣的先進(jìn)生產(chǎn)力了。
CodeGen負(fù)責(zé)將語法樹從頂至下遍歷,翻譯成LLVM IR,LLVM IR是Frontend的輸出,也是LLVM Backerend的輸入,橋接前后端。
LLVM命令:可以使用 llc 將 LLVM 字節(jié)代碼轉(zhuǎn)換成特定于平臺(tái)的匯編代碼lli 可以通過解釋器或使用高級(jí)選項(xiàng)中的即時(shí) (JIT) 編譯器執(zhí)行此工作llvm-gcc 是 GNU Compiler Collection (gcc) 的修改版本,可以在使用 -S -emit-llvm 選項(xiàng)運(yùn)行時(shí)會(huì)生成 LLVM 字節(jié)代碼。
編譯指令:clang -c -emit-llvm test1.c -o test1.bc 編譯產(chǎn)生字節(jié)碼
clang -S -emit-llvm test.c -o test.ll 編譯產(chǎn)生可視化字節(jié)碼
llvm-dis test1.bc test1.ll bc字節(jié)碼轉(zhuǎn)為可視化字節(jié)碼ll
llvm-as test1.ll test1.bc 可視化字節(jié)碼轉(zhuǎn)為字節(jié)碼bc
------------ END ------------
ysywjiqbxyq64047607247.gif (71.87 KB, 下載次數(shù): 1)
下載附件
保存到相冊
ysywjiqbxyq64047607247.gif
2024-10-26 07:33 上傳
●專欄《嵌入式工具》
●專欄《嵌入式開發(fā)》
●專欄《Keil教程》
●嵌入式專欄精選教程
關(guān)注公眾號(hào)回復(fù)“加群”按規(guī)則加入技術(shù)交流群,回復(fù)“1024”查看更多內(nèi)容。
mumwc53sb2y64047607347.png (214.79 KB, 下載次數(shù): 1)
下載附件
保存到相冊
mumwc53sb2y64047607347.png
2024-10-26 07:33 上傳
點(diǎn)擊“閱讀原文”查看更多分享。 |
|