色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

LLVM源碼淺析-1

汽車電子技術(shù) ? 來源:程序芯世界 ? 作者:coderSun ? 2023-03-02 16:06 ? 次閱讀

前言

作為一個優(yōu)秀的開源編譯器框架,llvm的代碼比gcc代碼的可讀性更好。因此無論是學(xué)習(xí)c++,還是學(xué)習(xí)編譯原理、設(shè)計模式、數(shù)據(jù)結(jié)構(gòu),都是一個很好的學(xué)習(xí)目標(biāo)。

這篇文章是受侯捷老師《STL源碼剖析》的啟發(fā),希望對llvm中的數(shù)據(jù)結(jié)構(gòu)進行一些解讀,因為llvm中有許多類似于STL中的數(shù)據(jù)。例如 map-like containner、set-like container、sequential container、string container、bit container等容器。

原創(chuàng)不易,您的關(guān)注就是我最大的動力。希望看到的朋友能點個關(guān)注,后續(xù)會把這個llvm數(shù)據(jù)結(jié)構(gòu)系列持續(xù)更新下去。

本文將對llvm中源碼進行分析,主要是了解其中一個類似于std::vector的數(shù)據(jù)結(jié)構(gòu)。并與之進行對比。

1.SmallVector概述

SmallVector是llvm中自定義的一種通用數(shù)據(jù)結(jié)構(gòu),在llvm的各層次間都可以使用。SmallVector與std::Vector非常類似 ,支持迭代、push_back、pop_back,以及隨機存取元素。

但是SmallVector對于元素較少的情況時性能是優(yōu)于std::vector的。這是因為SmallVector使用了一種比較通用的局部緩存設(shè)計模式,減少了malloc/free的巨大開銷。接下來會以SmallVecotor為載體,一步步揭開局部緩存設(shè)計模式的神秘面紗。同時我們還可以從中學(xué)到一些設(shè)計類的技巧。

這篇文章需要一點c++基礎(chǔ),需要c++資料的同學(xué)可以在我的公眾號[程序芯世界]回復(fù)c++即可獲取Modern C++的學(xué)習(xí)資料。里面有一本講c++ 設(shè)計模式的書個人感覺不錯,并且提到了本文中的局部緩存設(shè)計模式,有興趣的可以看看(因為覺得不錯,當(dāng)初還花了我30塊買的這本電子書)。圖片

2.局部緩存設(shè)計模式

在詳細(xì)了解SmallVector之前先來回顧一下std::vector和std::array,對比之后更容易了解SmallVector的優(yōu)勢。

std::vector會調(diào)用malloc函數(shù)申請一塊內(nèi)存用于放置元素 std::array是對內(nèi)置數(shù)組的一個封裝,因此其存放元素的數(shù)組會與std::array放置在同一個位置。如果std::array是在棧上聲明的,那么其存放元素的數(shù)組也位于棧上。

內(nèi)存的位置不同導(dǎo)致了std::array與std::vector效率的不同。因為std::vector是通過malloc申請的堆內(nèi)存,而std::array是棧內(nèi)存。

堆內(nèi)存的申請需要調(diào)用系統(tǒng)函數(shù)分配內(nèi)存,這個開銷是巨大的。相比之下,棧內(nèi)存幾乎是零開銷,因為只需要調(diào)整棧指針。當(dāng)然std::array也并不總是在棧上的,取決于你分配它的方式。但是任然會比std::vector少分配一次堆內(nèi)存。

stackoverflow上有一個很好的關(guān)于兩者的對比。std::vector versus std::array in C++

smallvector的本質(zhì)就是當(dāng)元素個數(shù)少的時候像std::array一樣將存儲元素的內(nèi)存放在類里面,當(dāng)元素個數(shù)多的時候像std::vector一樣分配堆內(nèi)存。這樣就兼具了兩者的優(yōu)點。這種操作被稱為局部緩存設(shè)計模式,在llvm很多地方都有體現(xiàn)。

下一節(jié)會對SmallVector進行詳細(xì)介紹,主要是關(guān)注類之間的抽象。

2.SmallVector的繼承關(guān)系

為了減少代碼冗余和提高代碼的可復(fù)用性,llvm對SmallVecotr這個類進行了多個層次的抽象。本節(jié)主要介紹與SmallVecotr有繼承關(guān)系的六個類。

由于這幾個類之間本身的關(guān)系并不復(fù)雜,因此沒有使用UML圖,而是簡單的畫出了繼承關(guān)系。

圖片

SmallVector繼承關(guān)系圖

2.1 SmallVector

其中SmallVector繼承自SmallVectorImpl和SmallVectorStorage。

template

首先來看SmallVector,它繼承了SmallVectorImpl和SmallVectorStorage。SmallVector本身只有一系列構(gòu)造函數(shù)(拷貝構(gòu)造、賦值構(gòu)造等),沒有成員變量,具體的一些成員函數(shù)放在SmallVectorImpl中,存儲元素的數(shù)組放在SmallVectorStorage中。需要注意的是SmallVectorStorage類中直接聲明了一個數(shù)組。

2.2 SmallVectorStorage

template <typename T, unsigned N>
struct SmallVectorStorage {
  alignas(T) char InlineElts[N * sizeof(T)];
};

這個數(shù)組會和對象放在同一塊內(nèi)存,當(dāng)需要存放的元素較少時就可以放在這個數(shù)組中,避免了調(diào)用malloc產(chǎn)生巨大的開銷。

2.3 SmallVectorImpl

template <typename T>
class SmallVectorImpl : public SmallVectorTemplateBase

上面提到SmallVector中之定義了一些構(gòu)造函數(shù),而其他的一些具體的操作函數(shù)則定義在SmallVectorImpl。這樣做的原因是什么呢?看明白下面這個小例子就理解為啥這樣設(shè)計了。

// DISCOURAGED: Clients cannot pass e.g. SmallVector
hardcodedSmallSize(SmallVector

從上述的例子可以看出,hardcodedSmallSize函數(shù)接受的參數(shù)是SmallVector,如果傳入的參數(shù)是SmallVector肯定是類型不匹配。此時SmallVectorImpl就起作用了,因為SmallVectorImpl是SmallVector的父類,可以向上隱式轉(zhuǎn)換,同時也不用傳遞參數(shù)N。這就是設(shè)計SmallVectorImpl的妙處。

2.4 SmallVectorTemplateBase

下面兩個都是SmallVectorTemplateBase類,不同的是第二個模板參數(shù)不同。針對元素是否為POD類型進行了偏特化。

template

以grow函數(shù)為例,來看是否為POD類型時不同的處理方式。下面為類型為非POD類型時grow函數(shù)的實現(xiàn)方式

template <typename T, bool TriviallyCopyable>
void SmallVectorTemplateBase

可以看到,非POD類型時,會調(diào)用moveElementsForGrow函數(shù)對每一個元素進行移動。同時會調(diào)用takeAllocationForGrow,如果是在堆上分配的內(nèi)存takeAllocationForGrow會調(diào)用free釋放之前分配的內(nèi)存。

template <typename T>
class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon

下面是POD類型時grow函數(shù)的實現(xiàn)方式。

template <class Size_T>
void SmallVectorBase

與非POD類型的grow函數(shù)對比可以發(fā)現(xiàn),這兒移動元素是調(diào)用memcpy直接對整體的內(nèi)存進行拷貝。同時也沒有對每一個元素的內(nèi)存進行釋放。

2.5 SmallVectorTemplateCommon

template <typename T, typename = void>
class SmallVectorTemplateCommon
    : public SmallVectorBase

SmallVectorTemplateCommon是不依賴于是否為POD類型的公共部分,冗余的模版參數(shù)T是為了給ArrayRef使用。ArrayRef可以是SmallVector或者std::Vector的引用,后續(xù)會寫文章介紹ArrayRef。

2.6 SmallVectorBase

SmallVectorBase是SmallVector所有的公共部分

template <class Size_T> class SmallVectorBase {
protected:
  void *BeginX;
  Size_T Size = 0, Capacity;
  ...
}

其中BeginX表示目前使用空間的頭部,Size表示已經(jīng)使用的空間大小,Capacity表示目前空間的容量。需要注意的是BeginX的初始化。前面已經(jīng)提到過,當(dāng)元素數(shù)量較少時是存儲在SmallVectorStorage定義的數(shù)組中。因此BeginX的初始值應(yīng)該是InlineElts的地址。如下所示是SmallVectorTemplateCommon的構(gòu)造函數(shù)

SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {}

調(diào)用該構(gòu)造函數(shù)時會首先對SmallVectorBase的構(gòu)造函數(shù),此時會對BeginX進行初始化,上面的Base就代表SmallVectorBase。可以看到BeginX是調(diào)用getFirstEl()進行初始化的。在來看看getFirstEl(),該函數(shù)會通過this指針的地址加上一個偏移量來得到。這個偏移量是通過一個SmallVectorAlignmentAndSize的struct得到。

void *getFirstEl() const {
    return const_cast<void *>(reinterpret_cast<const void *>(
        reinterpret_cast<const char *>(this) +
        offsetof(SmallVectorAlignmentAndSize

再來看看SmallVectorAlignmentAndSize這個結(jié)構(gòu)體,是由SmallVectorBase和FirstEl組成,正好SmallVector中SmallVectorBase占有內(nèi)存后就是SmallVectorStorage中InlineElts占有的內(nèi)存,因此FirstEl的偏移量也是InlineElts的偏移量。

template <class T, typename = void> struct SmallVectorAlignmentAndSize {
  alignas(SmallVectorBase

3.SmallVector迭代器

同std::Vector一樣,SmallVector維護的是一個連續(xù)的線性空間普通的指針都可以作為SmallVector的迭代器滿足所有的必要條件,例如operator*,operator++,operator--等。不需要額外的對這些操作符進行重載。

需要注意的是SmallVector同Vector一樣,當(dāng)發(fā)生擴容時其迭代器會失效。

4總結(jié)

  • SmallVector只定義了一系列構(gòu)造函數(shù),具體實現(xiàn)在SmallVectorImpl
  • SmallVectorStorage定義了存儲元素的數(shù)組
  • SmallVectorTemplateBase對是否為POD類型進行了偏特化
  • SmallVectorTemplateCommon是不依賴于是否為POD類型的公共部分
  • 元素的首地址通過getFirstEl()計算一個偏移量得到
  • SmallVector是std::array與std::vector的結(jié)合體,因此具備兩者共同的優(yōu)點。
  • SmallVector迭代器在發(fā)生擴容時會失效。

文章到這兒已經(jīng)結(jié)束啦,如果想要更深入的了解可以結(jié)合這篇文章深入了解一下源碼,這樣收獲會更大,沒有涉及到的地方歡迎留言討論。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2117

    瀏覽量

    74754
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4886

    瀏覽量

    70217
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1654

    瀏覽量

    49847
收藏 0人收藏

    評論

    相關(guān)推薦
    熱點推薦

    淺析uCosII

    淺析uCosII
    發(fā)表于 08-20 13:26

    LLVM編譯器編譯過程

    LLVM 編譯器 原理解析, 插件編寫
    發(fā)表于 04-28 08:15

    淺析Hadoop源碼的Partitioner類

    Hadoop源碼解析之Partitioner類
    發(fā)表于 03-27 09:41

    獲取源碼及Ubuntu編譯環(huán)境準(zhǔn)備

    系統(tǒng)要求:Ubuntu16.04及以上64位系統(tǒng)版本。編譯環(huán)境搭建分為如下幾步:獲取源碼安裝和配置python安裝gn安裝ninja安裝LLVM安裝hb須知:針對Ubuntu編譯環(huán)境我們提供了對應(yīng)
    發(fā)表于 08-19 11:10

    Niobe獲取源碼及Ubuntu編譯環(huán)境準(zhǔn)備

    開發(fā)參考源碼獲取必要的庫和工具編譯所需的必要工具和庫(如打包、鏡像制作等)通過互聯(lián)網(wǎng)獲取Python3.7+編譯構(gòu)建工具通過互聯(lián)網(wǎng)獲取LLVM(僅OpenHarmony_v1.x分支/標(biāo)簽需要)編譯工具鏈
    發(fā)表于 12-08 14:34

    Niobe獲取源碼及Ubuntu編譯環(huán)境準(zhǔn)備

    Niobe獲取源碼及Ubuntu編譯環(huán)境準(zhǔn)備獲取軟件獲取源碼安裝必要的庫和工具安裝Python3安裝LLVM(僅OpenHarmony_v1.x分支/標(biāo)簽需要)安裝hb前提條件安裝方法
    發(fā)表于 12-08 17:36

    LLVM clang 公開 -std=c++23

    合入 LLVM 17 倉庫的代碼對 Clang 編譯器使用 -std=c++23 代替了 -std=c++2b。 隨著 ISO C++ 委員會投票決定 C++23 標(biāo)準(zhǔn)已達到其技術(shù)完整狀態(tài)
    發(fā)表于 05-27 11:29

    在Swift中使用LLVM的四個要點

    本文主要內(nèi)容是演示如何在Swift中使用LLVM,其包含了如下四個要點: 獲取最新版本的LLVM使用CMake和llvm-config編譯程序編寫簡單的Swift程序,編譯并與LLVM
    發(fā)表于 10-13 16:55 ?0次下載
    在Swift中使用<b class='flag-5'>LLVM</b>的四個要點

    四個不同的系統(tǒng)上進行LLVM/Clang 6.0 和 5.0 的編譯器Benchmark測試

    參與測試的 LLVM 5.0.1 和 LLVM 6.0.0 穩(wěn)定版都是來自 apt.llvm.org。測試期間,每個系統(tǒng)都將其 CFLAGS/CXXFLAGS 設(shè)置為 "-O3 -march
    的頭像 發(fā)表于 03-29 15:25 ?7976次閱讀

    llvm-mctoll將二進制文件轉(zhuǎn)換為LLVM IR

    ./oschina_soft/llvm-mctoll.zip
    發(fā)表于 06-22 11:35 ?0次下載
    <b class='flag-5'>llvm</b>-mctoll將二進制文件轉(zhuǎn)換為<b class='flag-5'>LLVM</b> IR

    OLLVM和LLVM功能介紹

    LLVM是lowlevel virtual machine的簡稱,它誕生于2003.10伊利諾伊大學(xué)香檳分校,創(chuàng)始人是ChrisLattner,它是一個完整的編譯器框架,它兼容大部分主流開發(fā)語言例如
    的頭像 發(fā)表于 09-19 15:42 ?8240次閱讀

    LLVM國際開源軟件社區(qū)發(fā)布正式支持LoongArch架構(gòu)的版本

    前言 著名的LLVM國際開源軟件社區(qū)于2023年3月18日發(fā)布了16.0.0版本,以正式后端(official target)的級別實現(xiàn)了對LoongArch指令集架構(gòu)的完善支持。 至此,開源
    的頭像 發(fā)表于 03-21 09:45 ?1971次閱讀

    什么是LLVMLLVM的優(yōu)勢和特點有哪些?

    LLVM是一個開源的編譯器基礎(chǔ)設(shè)施項目,它以"Low-Level Virtual Machine"的縮寫命名,盡管名稱中包含了"虛擬機"一詞,但LLVM不僅僅是一個虛擬機,而是一個綜合的編譯器工具鏈。
    的頭像 發(fā)表于 06-11 15:54 ?1.1w次閱讀

    使用LLVM-embedded-toolchain-for-Arm-17.0.1開發(fā)STM32

    LLVM-embedded-toolchain-for-Arm 是一個 ARM 公司開源的適用于 32 位ARM芯片的工具鏈,支持多種ARM指令集架構(gòu),包括最新的 CM85 內(nèi)核。
    的頭像 發(fā)表于 10-23 16:46 ?2473次閱讀
    使用<b class='flag-5'>LLVM</b>-embedded-toolchain-for-Arm-17.0.1開發(fā)STM32

    陶瓷電容溫度系數(shù)淺析1類和2類電容有何差異?如何標(biāo)識?

    陶瓷電容溫度系數(shù)淺析1類和2類電容有何差異?如何標(biāo)識?
    的頭像 發(fā)表于 12-08 17:30 ?1661次閱讀
    陶瓷電容溫度系數(shù)<b class='flag-5'>淺析</b>:<b class='flag-5'>1</b>類和2類電容有何差異?如何標(biāo)識?
    主站蜘蛛池模板: 妇少水多18P蜜泬17P亚洲乱 | XXX国产麻豆HD真实乱 | 一本大道无码AV天堂欧美 | 中文字幕无码亚洲字幕成A人蜜桃 | proburn中文破解版下载 | 性美国人xxxxx18| 一级做a爰片久久毛片苍井优 | 男人脱女人衣服吃奶视频 | 国内精品视频久久久久免费 | 日韩欧美中文字幕一区 | 欧美日韩一区二区三区四区 | 免费人成视频X8X8国产更快乐 | 国产中文欧美日韩在线 | 色欲久久综合亚洲精品蜜桃 | 怡春院国产精品视频 | 日韩欧美精品有码在线播放 | 忘忧草在线影院WWW日本动漫 | 大陆午夜伦理 | 亚洲精品AV一二三区无码 | 中文国产成人精品久久免费 | 狠狠色狠狠色综合日日32 | 色欲人妻无码AV精品一区二区 | 日韩一区二区三区四区区区 | 亚洲精品久久久久久久蜜臀老牛 | 1a级毛片免费观看 | 久久中文字幕人妻熟AV女蜜柚M | 99久久国产露脸精品国产吴梦梦 | 全黄H全肉禁乱公 | 日本老师xxxxx18 | 动漫美女被羞羞动漫怪物 | 久久久GOGO无码啪啪艺术 | www.中文字幕在线观看 | 国产亚洲一区二区三区啪 | 国产 亚洲 中文字幕 久久网 | 无人区尖叫之夜美女姐姐视频 | 青青草在线视频 | 久久亚洲精品AV无码四区 | 欧美性FREE玩弄少妇 | 在线观看国产亚洲 | hdsex老太婆70 | 99re.05久久热最新地址 |

    電子發(fā)燒友

    中國電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會員交流學(xué)習(xí)
    • 獲取您個性化的科技前沿技術(shù)信息
    • 參加活動獲取豐厚的禮品