1. 程式人生 > >lcc原始碼解析之x86後端

lcc原始碼解析之x86後端

在前面的文章中已經介紹過,lcc中跟硬體平臺相關的配置由src中*.md配置,本文以x86為例,詳解這一部分的工作機制。

熟悉彙編的同學都知道32位x86機器有八個通用暫存器:

eax ebx ecx edx esi edi esp ebp

而ebp和esp兩個暫存器是有固定作用的,其儲存的幀指標和棧指標是組成棧幀的基本組成部分,所以這兩個暫存器不參與分配。

所以參與分配的通用暫存器只有六個,lcc用列舉將這兩個暫存器編號:

enum { EAX=0, ECX=1, EDX=2, EBX=3, ESI=6, EDI=7 };

在x86.md的最下面是一個Interface結構體的填充,關於Interface結構體中欄位的詳細作用,請看

這裡

其程式碼如下:

Interface x86IR = {
        1, 1, 0,  /* char */
        2, 2, 0,  /* short */
        4, 4, 0,  /* int */
        4, 4, 0,  /* long */
        4, 4, 0,  /* long long */
        4, 4, 1,  /* float */
        8, 4, 1,  /* double */
        8, 4, 1,  /* long double */
        4, 4, 0,  /* T * */
        0, 1, 0,  /* struct */
        1,        /* little_endian */
        0,        /* mulops_calls */
        0,        /* wants_callb */
        1,        /* wants_argb */
        0,        /* left_to_right */
        0,        /* wants_dag */
        0,        /* unsigned_char */
        address,
        blockbeg,
        blockend,
        defaddress,
        defconst,
        defstring,
        defsymbol,
        emit,
        export,
        function,
        gen,
        global,
        import,
        local,
        progbeg,
        progend,
        segment,
        space,
        0, 0, 0, 0, 0, 0, 0,
        {1, rmap,
            blkfetch, blkstore, blkloop,
            _label,
            _rule,
            _nts,
            _kids,
            _string,
            _templates,
            _isinstruction,
            _ntname,
            emit2,
            doarg,
            target,
            clobber,
}
};

這個結構體填充之後,一個完整的編譯器就可以工作了,前端就可以通過通過函式指標驅動後端生成程式碼了。

這裡要插入一個知識點Iburg的介紹,lburg是一個程式碼生成器的生成器,以lburg規範為語法,類似yacc和lex可以生成詞法分析器和語法分析器一樣。

lburg接收緊縮規範併產生一個用C語言編寫的樹分析程式,該程式為目標機器選擇指令。

lburg規範的核心是樹文法,與常規的文法類似,樹文法也是一個規則列表,每個規則的左邊是一個非終結符號,右邊是終結符號和非終結符號組成的模式。

具體EBNF表示如下(term表終結符號,nonterm表示非終結符號):

grammar:

'%{' configration '%}' { dcl } %% {rule} [%% C code]

dcl:

%start nonterm

%term { term = integer }

rule:

nonterm: tree template [ C expression ]

tree:

term[ '(' tree [, tree] ')']

nonterm

template:

" { any charactor except double quote} "

lburg以行為單位,%{  %[  %%必須單獨一行,configuration是C語言程式碼,每個dcl和rule必須出現在一行上。

lburg翻譯程式由lburg資料夾編譯生成,在一級目錄下執行make lburg即可,makefile中相關程式碼如下:

lburg:	$Blburg$E
$Blburg$E:	$Blburg$O $Bgram$O;	$(LD) $(LDFLAGS) -o [email protected] $Blburg$O $Bgram$O 

$Blburg$O $Bgram$O:	lburg/lburg.h

$Blburg$O:	lburg/lburg.c;	$(CC) $(CFLAGS) -c -Ilburg -o [email protected] lburg/lburg.c
$Bgram$O:	lburg/gram.c;	$(CC) $(CFLAGS) -c -Ilburg -o [email protected] lburg/gram.c
由於這一些列文章主要是研究編譯器本身的,對於lburg程式就不在繼續深入分享,有興趣的同學可以自己深入理解。

有了lburg,就可以將*.md翻譯.c檔案,makefile中相關部分程式碼如下:

$Bdagcheck.c:	$Blburg$E src/dagcheck.md; $Blburg src/dagcheck.md [email protected]
$Balpha.c:	$Blburg$E src/alpha.md;    $Blburg src/alpha.md    [email protected]
$Bmips.c:	$Blburg$E src/mips.md;     $Blburg src/mips.md     [email protected]
$Bsparc.c:	$Blburg$E src/sparc.md;    $Blburg src/sparc.md    [email protected]
$Bx86.c:	$Blburg$E src/x86.md;      $Blburg src/x86.md      [email protected]
$Bx86linux.c:	$Blburg$E src/x86linux.md; $Blburg src/x86linux.md [email protected]

可以看到x86.md和x86linux.md被翻譯成x86.c和x86linux.c,這就是本篇blog重點分析的部分。

下面就是生成的x86linux.c,這個檔案比較長,原因在於計算指令耗損的_label函式佔用了較大的篇幅,為了便於理解,下面的只挑出來一些重要的部分進行原始碼分析。

相關推薦

lcc原始碼解析x86

在前面的文章中已經介紹過,lcc中跟硬體平臺相關的配置由src中*.md配置,本文以x86為例,詳解這一部分的工作機制。 熟悉彙編的同學都知道32位x86機器有八個通用暫存器: eax ebx ecx edx esi edi esp ebp 而ebp和esp兩個暫存器是有固

1、[置頂] CAS單點登入原始碼解析【客戶

前期準備: 2.cas-client-3.2.1-release.zip 3.應用系統webapp(http://127.0.0.1:8090/webapp/main.do) 4.CAS單點登入伺服器端(http://127.0.0.1:8081/cas-server/)        

lcc原始碼解析sym.c

lcc是一款小巧的工業級編譯器,程式碼精簡,程式碼開源,相比gcc更適合編譯器初學者閱讀。 你可以在這裡搞到程式碼:https://github.com/drh/lcc 但是,怎麼說呢,這個程式碼防盜性較強,幾乎沒有註釋, 我在閱讀原始碼中參考了其他前輩關於lcc的文章以及

CAS單點登入原始碼解析【伺服器

前期準備: 2.應用系統webapp1(http://127.0.0.1:8090/webapp1/main.do) 3.應用系統webapp2(http://127.0.0.1:8091/webapp2/main.do) 4.CAS單點登入伺服器端(http://127

lcc原始碼解析expr.c

又憋了一個周天,終於大概搞明白了表示式解析這一編譯器中我個人認為也許最迷人的部分。 之所以程式碼讀起來費勁,主要還是在於理論上沒有搞清楚,確實很繞,需要反覆理解。 所以,打算在本篇之後寫一篇理論的科普文,儘管因為我文字表達能力太爛,這是我一直竭力避免的。 ---------

webpack4.0原始碼解析打包js檔案分析

首先,init之後建立一個簡單的webpack基本的配置,在src目錄下建立兩個js檔案(一個主入口檔案和一個非主入口檔案)和一個html檔案,package.json,webpack.config.js程式碼如下: var name=require('./index1.js') console.log('

Dubbo原始碼解析服務接收訊息

準備 dubbo 版本:2.5.4 服務端接收訊息流程 Handler鏈路 DubboProtocol private ExchangeServer createServer(URL url) { url = url.addParameterIfAbsent("c

hadoop原始碼解析hdfs寫資料全流程分析---客戶處理

DFSOutputStream介紹 DFSOutputStream概況介紹 這一節我們介紹hdfs寫資料過程中,客戶端的處理部分。客戶端的處理主要是用到了DFSOutputStream物件,從名字我們可以看出,這個是對dfs檔案系統輸出流的一個

kafka原始碼解析十六生產者流程(客戶如何向topic傳送資料)

客戶端向topic傳送資料分為兩種方式:1.非同步,2同步。其配置為producer.type,如果為sync,則是同步傳送;如果為async,則是非同步傳送。 客戶端程式碼如下: import kafka.javaapi.producer.Producer; import

kafka原始碼解析十七消費者流程(客戶如何獲取topic的資料)

Kafka消費資料的角色分為普通消費者和高階消費者,其介紹如下: 17.1 普通消費者 特點:1)一個訊息讀取多次    2)在一個處理過程中只消費某個broker上的partition的部分訊息    3)必須在程式中跟蹤offset值    4)必須找出指定Topi

Dubbo原始碼解析客戶初始化及服務呼叫

準備 dubbo 版本:2.5.4 客戶端初始化過程 初始化過程 先上時序圖,幫助理解客戶端初始化過程。 ReferenceBean 是客戶端初始化入口,其實現 InitializingBean 介面,在 bean 初始化過程中會呼叫其 afterProper

Spring Cloud系列(三):Eureka原始碼解析服務

一、自動裝配   1、根據自動裝配原理(詳見:Spring Boot系列(二):Spring Boot自動裝配原理解析),找到spring-cloud-starter-netflix-eureka-server.jar的spring.factories,檢視spring.factories如下:   2、進

webpack4.0原始碼解析CommonJS規範打包js檔案分析

首先,init之後建立一個簡單的webpack基本的配置,在src目錄下建立兩個js檔案(一個主入口檔案和一個非主入口檔案)和一個html檔案,package.json,webpack.config.js程式碼如下: var name=require('./index1.js') console.log('

Android實戰——第三方服務Bmob雲的推送服務的集成和使用(三)

第一篇 文章 href 第三方服務 log 集成 android實戰 https 分享 第三方服務之Bmob後端雲的推送服務的集成和使用(三) 事先說明:這裏的一切操作都是在集成了BmobSDK之後實現的,如果對Bmob還不了解的話,請關註我第一篇Bmob文章 步驟

Android實戰——第三方服務Bmob雲的增刪改查、上傳文件、獲取文件、修改密碼(二)

tid blank 生成 src 上傳圖片 放置 第三方 b數 net 第三方服務之Bmob後端雲的增刪改查、上傳文件、獲取文件、修改密碼(二) 事先說明:這裏的一切操作都是在集成了BmobSDK之後實現的,如果對Bmob還不了解的話,請關註我第一篇Bmob文章 步

Android框架原始碼解析(四)Picasso

這次要分析的原始碼是 Picasso 2.5.2 ,四年前的版本,用eclipse寫的,但不影響這次我們對其原始碼的分析 地址:https://github.com/square/picasso/tree/picasso-parent-2.5.2 Picasso的簡單使用

Android框架原始碼解析(三)ButterKnife

注:所有分析基於butterknife:8.4.0 原始碼目錄:https://github.com/JakeWharton/butterknife 其中最主要的3個模組是: Butterknife註解處理器https://github.com/JakeWharton/

Android框架原始碼解析(二)OKhttp

原始碼在:https://github.com/square/okhttp 包實在是太多了,OKhttp核心在這塊https://github.com/square/okhttp/tree/master/okhttp 直接匯入Android Studio中即可。 基本使用:

Android框架原始碼解析(一)Volley

前幾天面試CVTE,HR面掛了。讓內部一個學長幫我查看了一下面試官評價,發現二面面試官的評價如下: 廣度OK,但缺乏深究能力,深度與實踐不足 原始碼:只能說流程,細節程式碼不清楚,retrofit和volley都是。 感覺自己一方面:自己面試技巧有待提高吧(框

前後分離Java

前後端分離的思想由來已久,不妨嘗試一下,從上手開始,先把程式碼寫出來再究細節。 程式碼下載:https://github.com/jimolonely/AuthServer 前言 以前服務端為什麼能識別使用者呢?對,是session,每個session都存在服務端,瀏覽器每次請求都帶著ses