日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(三)Clang/ LLVM编译流程简述

發(fā)布時間:2025/3/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (三)Clang/ LLVM编译流程简述 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
  • LLVM概述

    LLVM是構(gòu)架編譯器(compiler)的框架系統(tǒng),以C++編寫而成,用于優(yōu)化以任意程序語言編寫的程序的編譯時間(compile-time)鏈接時間(link-time)運行時間(run-time) 以及空閑時間(idle-time),對開發(fā)者保持開放,并兼容已有腳本。
  • 傳統(tǒng)編譯器設(shè)計


    編譯器不同于解釋器,解釋器可以將高級語言邊轉(zhuǎn)譯邊執(zhí)行。但是編譯器需要將所有的源代碼編譯成機器代碼之后,然后才能執(zhí)行,所以如圖不管傳統(tǒng)的還是LLVM都一定是源代碼輸入,輸出是機器代碼(也就是0101組合),中間還分前端優(yōu)化器后端
    • 編譯器前端(Frontend)

      編譯器前端的任務(wù)是解析源代碼。它會進行:詞法分析語法分析語義分析, 檢查源代碼是否存在錯誤,然后構(gòu)建抽象語法樹(Abstract Syntax Tree,AST) ,LLVM的前端還會生成中間代碼(intermediate representation , IR)。
    • 優(yōu)化器(Optimizer)

      優(yōu)化器負責進行各種優(yōu)化。改善代碼的運行時間,例如消除冗余計算等。
    • 后端(Backend) /代碼生成器(CodeGenerator)

      將代碼映射到目標指令集。生成機器語言,并且進行機器相關(guān)的代碼優(yōu)化
    • iOS的編譯器架構(gòu)

    Objective C/C/C++使用的編譯器前端是Clang, Swift是Swift,后端都是LLVM。
  • LLVM的設(shè)計


    當編譯器決定支持多種源語言或多種硬件架構(gòu)時,LLVM最重要的地方就來了。 其他的編譯器如GCC,它方法非常成功,但由于它是作為整體應用程序設(shè)計的, 因此它們的用途受到了很大的限制。
    LLVM設(shè)計的最重要方面是,使用通用的代碼表示形式(IR),它是用來在編譯器中標識代碼的形式(其實就是一種中間代碼)。所以LLVM可以為任何變成語言獨立編寫前端,并且可以為任意硬件架構(gòu)獨立編寫后端。
  • Clang

    Clang是LLVM項目中的一個子項目。它是基于LLVM架構(gòu)的輕量級編譯器,誕生之初是為了替代GCC,提供更快的編譯速度。它是負責編譯C、C++、Objecte-C語言的編譯器,它屬于整個LLVM架構(gòu)中的,編譯器前端。
  • 編譯流程

    首先簡單寫一個demo如下: #import <stdio.h>//#define C 30//typedef int TD_INT_64;int test(int a,int b){return a + b + 3;}int main(int argc, const char * argv[]) {int a = test(1, 2);printf("%d",a);return 0;} 復制代碼
    • 通過命令打印查看源碼的編譯階段

      命令:clang -ccc-print-phases main.m

      可以發(fā)現(xiàn)主要分6個步驟
      • 0:輸入文件:找到源文件。
      • 1:預處理階段:這個過程處理包括宏的替換,頭文件的導入。
      • 2:編譯階段:進行詞法分析、語法分析、檢測語法是否正確,最終生成IR。
      • 3:后端:這里LLVM會通過一個一個的Pass去優(yōu)化,每個Pass做一些事情,最終生成匯編代碼。
      • 4:生成目標文件。
      • 5:鏈接:鏈接需要的動態(tài)庫和靜態(tài)庫,生成可執(zhí)行文件。
      • 6:通過不同的架構(gòu),生成對應的可執(zhí)行文件。
    • 預處理階段

      命令:clang -E main.m

      宏在預處理階段會被替換掉,typedef不會被替換掉,所以一般為了安全可以使用,做代碼混淆
    • 編譯階段

      • 詞法分析

        預處理完成后就會進行詞法分析.這里會把代碼切成一個個Token,比如大小括 號,等于號還有字符串等
        命令: clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m

        注:如果頭文件找不到可以指定sdk
        clang -isysroot (自己SDK路徑) -fmodules -fsyntax-only -Xclang -dump-tokens main.m
        clang -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator14.1.sdk/ -fmodules -fsyntax-only -Xclang -dump-tokens main.m
      • 語法分析

        詞法分析完成之后就是語法分析,它的任務(wù)是驗證語法是否正確。在詞法分析的基礎(chǔ)上將單詞序列組合成各類語法短語,如“程序”,“語句”,“表達式”等等,然后將所有節(jié)點組成抽象語法樹(Abstract Syntax Tree, AST)。語法分析程序判斷源程序在結(jié)構(gòu)上是否正確。
        命令: clang -fmodules -fsyntax-only -Xclang -ast-dump main.m

        • FunctionDecl 函數(shù)
        • ParmVarDecl 參數(shù)
        • CallExpr 調(diào)用一個函數(shù)
        • BinaryOperator 運算符
      • 生成中間代碼IR

        完成以上步驟后就開始生成中間代碼IR了,代碼生成器(Code Generation)會將語法樹自頂向下遍歷逐步翻譯成LLVM IR。通過下面命令可以生成.11的文本文件,查看IR代碼。
        命令:clang -S -fobjc-arc -emit-llvm main.m
        Objective C代碼在這一步會進行runtime的橋接:property合成,ARC處理等
        IR的基本語法:
        • @ 全局標識
        • % 局部標識
        • alloca 開辟空間
        • align 內(nèi)存對齊
        • i32 32個bit, 4個字節(jié)
        • store 寫入內(nèi)存
        • load 讀取數(shù)據(jù)
        • call 調(diào)用函數(shù)
        • ret 返回

        IR優(yōu)化:
        LLVM的優(yōu)化級別分別是-O0 -O1 -O2 -O3 -Os(第一個是大寫英文字母O)
        優(yōu)化命令:clang -Os -S -fobjc-arc -emit-llvm main.m -o main.ll 一般設(shè)置是在target - Build Setting - Optimization Level(優(yōu)化器等級)中設(shè)置

        Debug情況下默認是不優(yōu)化,Release情況下默認Fastest、Smallest
        優(yōu)化后的代碼

      • bitCode

        xcode7以后開啟bitcode蘋果會做進一步的優(yōu)化。生成.be的中間代碼。 我們通過優(yōu)化后的IR代碼生成.be代碼
        命令:clang -emit-llvm -c main.ll -o main.bc
      • 生成匯編代碼

        最終通過.be或者.ll代碼生成匯編代碼
        命令:
        clang -S -fobjc-arc main.bc -o main.s
        clang -S -fobjc-arc main.ll -o main.s

        當然生成的匯編代碼也可以進行優(yōu)化(注意如果生成IR代碼已經(jīng)做過優(yōu)化了此時在優(yōu)化不會再起作用)
        命令:clang -Os -S -fobjc-arc main.m -o main.s
      • 生成目標文件(匯編器)

        目標文件的生成,是匯編器以匯編代碼作為輸入,將匯編代碼轉(zhuǎn)換為機器代碼, 最后輸出目標文件(object file)
        命令: clang -fmodules -c main.s -o main.o

        可以發(fā)現(xiàn)是個Mach-O文件
        通過nm命令,查看下main.o中的符號
        命令: xcrun nm -nm main.o

        發(fā)現(xiàn)找不到_printf這個方法,應為_printf是從外部的庫引入
      • 生成可執(zhí)行文件(鏈接)

        連接器把編譯產(chǎn)生的.o文件和(.dylib .a)文件,生成一個mach-o文件。
        命令:clang main.o -o main

        發(fā)現(xiàn)此時是一個可執(zhí)行的Mach-O文件
        再查看鏈接之后的符號

        應為OC的特性運行時,動態(tài)庫實在運行時需要使用的時候再加載到內(nèi)存的,所以編一階段找不到對應的方法
  • LLVM編譯流程圖


作者:Potato_土豆
鏈接:https://juejin.cn/post/6959865646125416484
來源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

?

總結(jié)

以上是生活随笔為你收集整理的(三)Clang/ LLVM编译流程简述的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。