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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 综合教程 >内容正文

综合教程

Clang AST介绍

發(fā)布時(shí)間:2023/12/13 综合教程 46 生活家
生活随笔 收集整理的這篇文章主要介紹了 Clang AST介绍 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

AST(Abstracted Syntax Tree)即抽象語(yǔ)法樹(shù),對(duì)于任何一門編程語(yǔ)言來(lái)說(shuō)都是非常重要的工具,對(duì)于一般的compiler來(lái)說(shuō),都是將源碼轉(zhuǎn)換為AST,之后經(jīng)由AST轉(zhuǎn)換到特定的IR,在IR上進(jìn)行一些與硬件特性無(wú)關(guān)的優(yōu)化,之后再將優(yōu)化后的IR轉(zhuǎn)換為對(duì)應(yīng)的匯編。因此AST直觀的反應(yīng)了使用者的編程思想。AST上一般進(jìn)行的轉(zhuǎn)換和優(yōu)化不多,更多的是對(duì)語(yǔ)言特性的支持和檢查。AST的中文介紹https://blog.csdn.net/philosophyatmath/article/details/38170131(入門介紹)

對(duì)于AST是如何構(gòu)建的,之前的詞法token分析是如何進(jìn)行的,在https://www.twilio.com/blog/abstract-syntax-trees中已經(jīng)進(jìn)行了很好的說(shuō)明,不在進(jìn)行贅述。一般而言,每種編程語(yǔ)言都有對(duì)應(yīng)的ast,包括Python,Perl,F(xiàn)ortran,C,Java等,也有很多開(kāi)源的AST Viewer工具可供使用,比如https://astexplorer.net/。

本文主要針對(duì)LLVM的前端進(jìn)行介紹。在現(xiàn)有LLVM的版本中,默認(rèn)使用的前端是Clang,Clang包含token和AST構(gòu)建的全過(guò)程。(Clang官方的introduction:https://clang.llvm.org/docs/IntroductionToTheClangAST.html)

AST樹(shù)是源代碼抽象語(yǔ)法結(jié)構(gòu),以樹(shù)的形式表示語(yǔ)言的語(yǔ)法結(jié)構(gòu)。樹(shù)的每個(gè)節(jié)點(diǎn)都有相對(duì)應(yīng)的源碼的支持,樹(shù)節(jié)點(diǎn)以不同的類型進(jìn)行區(qū)分,下邊將分別進(jìn)行介紹。

對(duì)于LLVM Clang來(lái)說(shuō),頂層結(jié)構(gòu)是TranslationUnitDecl,對(duì)AST樹(shù)的遍歷,實(shí)際上是遍歷整個(gè)TranslationUnitDecl。遍歷它的方式,一般通過(guò):

DeclContext::decl_iterator D = Context.getTranslationUnitDecl()->decls_begin();
DeclContext::decl_iterator DEnd = Context.getTranslationUnitDecl()->decls_end();
while (D != DEnd)

的方式進(jìn)行。

Clang的使用命令

Clang盡最大可能兼容了gcc,因此將gcc修改為Clang,大概率只是換個(gè)名字就行,現(xiàn)在也有人嘗試使用Clang編譯一般的庫(kù),一般都能編過(guò),而且代碼運(yùn)行效率一般不會(huì)特別差。有些系統(tǒng)下可能會(huì)面臨std庫(kù)無(wú)法找到的問(wèn)題,需要額外添加-I和-L選項(xiàng)。

Clang相比gcc,額外增加了很多功能,比如AST樹(shù)的打印。對(duì)于源文件test.cpp:

void foo(int* a, int *b) {
      if (a[0] > 1)
      {
           b[0] = 2;
      }
}

使用Clang -fsyntax-only -Xclang -ast-dump test.cpp

簡(jiǎn)單解釋下這里的命令,-fsyntax-only意味著只解析語(yǔ)法,不進(jìn)行編譯和鏈接;

-Xclang 是要使用clang特定的Xclang功能

-ast-dump是要打印AST

這里會(huì)得到一個(gè)額外著色的ast,在源碼中,使用dump是沒(méi)有額外著色的,需要使用dumpColor()得到。

2. AST樹(shù)節(jié)點(diǎn)一般介紹(LangOptions()是CPP)

我會(huì)以這樣一段程序?qū)ST樹(shù)節(jié)點(diǎn)進(jìn)行介紹,包含了函數(shù)聲明、函數(shù)調(diào)用、變量聲明、for循環(huán)、if語(yǔ)句、指針變量等。

 1 int foo(int a, int b,int *c){
 2     int ret = 0;
 3     if(a > b){
 4         ret = a;
 5     }
 6     else {
 7         ret = b;
 8     }
 9     for(int temp=0; temp<100; ++temp){
10         *c = (*c + temp);
11     }
12     return ret;
13 }
14 
15 int main(){
16     int a = 1, b = 2;
17     int c =0;
18     int d = foo(a, b, &c);
19     return 0;
20 }

FunctionDeclaration

ParmVarDecl是參數(shù)節(jié)點(diǎn)

在AST層級(jí),不區(qū)分函數(shù)聲明和函數(shù)定義,統(tǒng)一用FunctionDecl來(lái)標(biāo)識(shí),兩個(gè)區(qū)分主要看是否有函數(shù)體(Body),可以使用bool hasBody()來(lái)進(jìn)行判斷。

CompoundStmt

代表大括號(hào),函數(shù)實(shí)現(xiàn)、struct、enum、for的body等一般用此包起來(lái)。

DeclStmt

定義語(yǔ)句,里邊可能有VarDecl等類型的定義

VarDecl

變量定義,如果有初始化,可以通過(guò)getInit()獲取到對(duì)應(yīng)的初始化Expr

IfStmt

If語(yǔ)句,包括三部分Cond、TrueBody、FalseBody三部分,分別可以通過(guò)getCond(),getThen(), getElse()三部分獲取,Cond和Then是必須要有的,Else可能為空

BinaryOperator

二元操作Op,=,>,<,<=,>=,==等各種二元操作都繼承它,從繼承關(guān)系來(lái)說(shuō):

通常通過(guò)getLHS()和getRHS()來(lái)分別獲得其左右子節(jié)點(diǎn)

ImplicitCastExpr

隱形轉(zhuǎn)換表達(dá)式,在左右值轉(zhuǎn)換和函數(shù)調(diào)用等各個(gè)方面都會(huì)用到。

IntegerLiteral

定點(diǎn)Integer值

UnaryOperator

一元操作

CallExpr

函數(shù)調(diào)用Expr,子節(jié)點(diǎn)有調(diào)用的參數(shù)列表

ReturnStmt

返回語(yǔ)句

ForStmt

For語(yǔ)句對(duì)應(yīng),包括Init/Cond/Inc 對(duì)應(yīng)(int a=0;a<mm;a++)這三部分,還有一部分是body,可以分別使用getInit() / getCond() / getInc() / getBody()來(lái)分別進(jìn)行獲取

ParenExpr

括號(hào)表達(dá)式

對(duì)于一些結(jié)構(gòu)體的操作,比如struct或者enum,有自己的格式。

比如

struct dict {
    int a;
    int b;
};

void vpp(){
    struct dict news;
    struct dict olds = {1,2};
    news.a = 1;
    news.b = b + 2;
}

RecordDecl首先是struct的聲明,采用的是RecordDecl的形式。

后邊會(huì)出現(xiàn)對(duì)應(yīng)的struct dict的類型

在使用時(shí)會(huì)發(fā)現(xiàn),仍然使用DeclStmt的形式去聲明使用InitExpr的方式來(lái)初始化,只不過(guò)這種特殊的格式是使用了InitListExpr的方式。

對(duì)于成員變量的使用,采用MemberExpr的方式來(lái)取值。

Reference:

https://clang.llvm.org/docs/index.html

https://clang.llvm.org/docs/UsersManual.html

https://www.twilio.com/blog/abstract-syntax-trees

https://astexplorer.net/

總結(jié)

以上是生活随笔為你收集整理的Clang AST介绍的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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