現代編譯原理--第五章(活動記錄)


  (轉載請表明出處  http://www.cnblogs.com/BlackWalnut/p/4559245.html )

      第五章是到目前位置最讓我頭疼的一章,不是因為難,是因為對最終的目的不太明確。整章前半部分用十分精簡的語言介紹了一個新的概念,活動記錄,也就是在函數調用時,一個調用棧究竟發生了什么事。但是,在最終編碼實現過程中,總不能理解作者為什么給了這些變量?或者說,完全不知道作者究竟想讓我完成一個怎樣的功能。糾結了好幾天,后來索性往后繼續看,看看能不能找到其他的線索。直到看完后一章,硬着頭皮寫了一半的時候,才豁然開朗。原來作者是這個意圖!所以,如果你也不知道這章程序最終要得到一個什么樣的結果,建議把后面一章也讀了,因為這兩章講的是同一個東西的不同部分。

  先看看一些理論知識吧。首先,這個活動記錄,就是我們通常意義上的函數調用堆棧,所以又叫棧幀。是內存中的一個區域,在這個區域中包含了一個函數中所有參數,局部變量,臨時變量,返回值等信息,如果這種語言還允許嵌套的函數聲明,那么,還要有一個叫做靜態鏈的東西。這些東西在不同的目標機器上對應的布局是不一樣的,書上介紹了一種標准布局。

  那么,一個函數怎么去訪問他自己的變量呢?用的是(棧指針+偏移量),因為對cpu而言,加法運算是比較簡單的,所以,在實際中,棧指針是位於低地址,表示棧的下界,而幀指針位於高地址,表示棧的上界。這樣就會發現,其實,棧頂的地址要比棧底的地址低。

  其實並不是所有參數都要放入棧(內存)中的,有些變量可以放入寄存器中,這樣可以省去很多的訪存時間。但是,一個程序可以有多個函數,寄存器的個數卻是有限。那么,當一個函數調用另一個函數,且都要使用同一個寄存器的時候,誰去將原來的寄存器中的內容的保存起來呢?如果是調用其他函數的函數負責,則成為調用者保護,如果是被調用函數負責,那么就是被調用者保護。

    通常情況下,我們會將傳入一個函數的參數放入寄存器中,但是,寄存器的數量是有限,放不下的怎么辦?例如,對於f(n1 , n2 , ...,nx)的函數,我們會將前k個,假如k為4,放入寄存器中,剩下的x-k個我們就放入調用函數f的函數的棧幀的末尾,緊鄰着棧指針,這x-k個區域就稱為傳出參數。但是這x-k塊區域對於被調用函數f來說就被稱為傳入參數。思考一下,如果f又去調用了其他函數呢?那么那k個參數就要被移出寄存器,放到f中稱為局部變量的區域中,這塊區域是緊挨着傳出參數(傳入參數,對函數f而言)。

  那么,除了以上參數傳遞過程中有變量要被移出寄存器,還有其他一些情況需要將寄存器中的參數放到內存中。比如,在一個函數定義中取了一個外部函數中的一個變量的地址(此時要求語言支持函數內部定義新的函數),那么這個變量就要寫回內存,要不然,你取到的地址是寄存器地址,如果在以后的處理過程中這個變量被移出了寄存器,豈不是就找不到了么。

  當然,還有很多情況需要考慮,這里就不一一列舉了,虎書上已經講的很明白了,並且,對於所有本來在寄存器中,后來被移動內存中的變量稱為逃逸。那么,如何在一個函數內部取用外部函數的變量呢?這就要用一個稱為靜態來鏈的東西,這個東西就是能讓你在一個函數內部順藤摸瓜的找到你需要的變量,類似於一個鏈表。

  好了,說了這么多,我們來看看最后的實現吧。本章要實現的,其實就是這個棧。在前幾次的數據結構中保留了一個稱為scape的區域沒有用,這是個bool變量,使用這個變量來標記tiger中一個變量是不是逃逸的。如何計算一個變量是不是逃逸的呢?因為這些逃逸信息只有在完成這個程序掃描后才能知道。所以,對得到的抽象語法樹進行兩次掃描,第一次得到變量的逃逸信息,第二次才是對對語法樹進行類型檢測,同時生成棧幀。

  我的代碼並沒有實現對抽象語法的逃逸變量檢測,我默認所有的變量都是可以逃逸的。所以本次代碼的主要部分就是frame.h以及frame.cpp,並且不涉及到對這frame.h中函數的真正使用。對其使用的部分將在下一章中體現。以下是源碼:

  

#ifndef FRAME_H_
#define FRAME_H_
#include "temp.h"
#include "util.h"
#include "tree.h"

const int F_wordSize = 4 ;
typedef struct F_frame_ *F_frame ;
typedef struct F_access_ *F_access ;
typedef struct F_accesslist_ *F_accesslist ;
struct F_accesslist_ { F_access head; F_accesslist tail; };
typedef struct F_frag_ *  F_frag ;
typedef struct F_fragList_ * F_fragList ;


struct F_frame_ { 
                 Temp_label name ; 
                 int framesize ;
                 F_accesslist formals; 
                 F_accesslist locals; 
                 };
struct F_access_ {
                  enum { inFrame , inReg } kind  ;
                  union{
                      int offset ;
                      Temp_temp reg ;
                       } u ;
                  };
struct F_frag_ {
                enum { F_stringFrag , F_procFrag } kind ;
                union {
                    struct { 
                             Temp_label label ;
                             string str ; 
                           } stringg ;
                    struct {
                             T_stm body ;
                             F_frame frame ;
                            } proc ;
                        }u ;
                };
struct F_fragList_{  F_frag head ; F_fragList tail; };

F_frag F_StringFrag( Temp_label label , string str) ;
F_frag F_ProcFrag ( T_stm stm , F_frame frame ) ;

F_fragList F_FragList(F_frag frag , F_fragList tail) ;


Temp_temp F_FP(void);   
Temp_temp F_RV(void) ;  



F_frame F_newframe(Temp_label name , U_boolList formals) ;
F_accesslist F_Accesslist(F_access head , F_accesslist tail) ;


Temp_label F_name(F_frame f) ;
F_accesslist F_formals(F_frame f) ;
F_access F_allocLoacl(F_frame f  , bool escape );

F_access InFrame(int offset) ;
F_access InReg(Temp_temp reg) ;

T_exp F_Exp(F_access acc, T_exp framePtr);
T_exp F_externalCall(string s , T_expList explist);

T_stm F_procEntryExit1(F_frame frame , T_stm stm) ;
#endif
#include "frame.h"
#include "tree.h"
const int offset = -4 ;


static Temp_temp fp = NULL;
Temp_temp F_FP()
{
    if(fp==NULL)
    {
        fp = Temp_newtemp();
        
    }
    return fp;
}
static Temp_temp rv = NULL ;
Temp_temp F_RV()
{
    if (rv == NULL )
    {
        rv = Temp_newtemp() ;
    }
    return rv ;
}
F_access F_allocLoacl(F_frame f , bool escape )
{
    F_access access ;
    if (escape == true)
    {
        access = InFrame(f->framesize) ;
        f->framesize -= offset;
    }
    else
    {
        access = InReg(Temp_newtemp()) ;
    }
    f->locals = F_Accesslist(access , f->locals) ;
    return access ;
}

F_access InFrame(int offset)
{
    F_access tmp = (F_access) checked_malloc(sizeof(*tmp)) ;
    tmp->kind = F_access_::inFrame ;
    tmp->u.offset = offset ;
    return tmp ;
}

F_access InReg(Temp_temp reg)
{
    F_access tmp = (F_access) checked_malloc(sizeof(*tmp)) ;
    tmp->kind = F_access_::inReg ;
    tmp->u.reg = reg ;
    return tmp ;
}

F_frame F_newframe(Temp_label name , U_boolList formals)
{
    F_frame frame =(F_frame) checked_malloc(sizeof(*frame)) ;
    frame->name = name ;
    frame->formals = NULL ;
    U_boolList par = formals ;
    F_access acc ;
    frame->framesize = 0 ;
    while(par != NULL)
    {
        if (par->head)
        {
          acc = InFrame(frame->framesize) ;   
          frame->framesize -= offset ;
        }
        else
        {
         acc = InReg(Temp_newtemp()) ;
        }
        frame->formals = F_Accesslist(acc , frame->formals) ;
        par = par->tail ;
    }
   frame->locals = NULL ;
   return frame ;
}

F_accesslist F_Accesslist(F_access head , F_accesslist tail)
{
    F_accesslist tmp = (F_accesslist)checked_malloc(sizeof(*tmp)) ;
    tmp->head = head ;
    tmp->tail = tail ;
    return tmp ;
}

T_exp F_Exp(F_access acc, T_exp framePtr)
{
    if (acc->kind == F_access_::inFrame )
    {
        return T_Mem(T_Binop(T_plus, framePtr, T_Const(acc->u.offset)));
    }
    return  T_Temp(acc->u.reg);
}

F_frag F_StringFrag(Temp_label label , string str)
{
    F_frag tmp = (F_frag) checked_malloc(sizeof(*tmp)) ;
    tmp->kind = F_frag_::F_stringFrag ;
    tmp->u.stringg.label = label ;
    tmp->u.stringg.str = str ;
    return tmp ;
}

F_frag F_ProcFrag( T_stm stm , F_frame frame )
{
    F_frag tmp = (F_frag) checked_malloc(sizeof(*tmp)) ;
    tmp->kind = F_frag_::F_procFrag ;
    tmp->u.proc.body = stm ;
    tmp->u.proc.frame = frame ;
    return tmp ;
}

F_fragList F_FragList(F_frag frag , F_fragList tail)
{
    F_fragList tmp = (F_fragList) checked_malloc(sizeof(*tmp)) ;
    tmp->head = frag ;
    tmp->tail = tail ;
    return tmp; 
}
T_stm F_procEntryExit1(F_frame frame , T_stm stm) 
{
    return stm ;
}


F_accesslist F_formals(F_frame frame)
{
    return frame->formals;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM