LCC編譯器的源程式分析 21 區域性變數的宣告

2021-04-13 02:02:50 字數 4619 閱讀 4537

區域性變數的處理是比較特別,它是複雜語句裡面宣告,作用域也只限於復合語句裡。如下面的例子:

上面的a

就是區域性變數的宣告。

現在再來仔細地分析

compound

裡處理區域性變數的**。如下:

#031  //

區域性變數宣告處理.

#032  while ( kind[t] == char || kind[t] == static

#033               || istypename(t, tsym) && getchr() != ':')

#034  

上面呼叫函式

decl

來處理宣告,跟前面介紹過的宣告是一樣的。只有乙個地方不同,它是呼叫函式

dcllocal

來分析區域性變數的。下面再來回顧一下

decl

函式:

#001 static void decl(symbol (*dcl)(int, char *, type, coordinate *))

#002 

#048         else

#049        

在以前處理的變數宣告全是全域性變數,因此不會執行到第

50行的**。 …

#076               else

#077               在第

78行裡是呼叫區域性變數宣告函式

dcllocal

來分析區域性變數。

那麼區域性變數函式又是怎麼樣處理區域性變數的呢?前面已經分析了全域性變數,引數變數,現在就來分析

dcllocal

的**,如下:

#001 //

區域性變數宣告.

#002 static symbol dcllocal(int sclass, char *id, type ty, coordinate *pos)

#003 

#014  else if (sclass == register

#015         && (isvolatile(ty) || isstruct(ty) || isarray(ty)))

#016  

#021  第

6行到第

20行處理區域性變數的儲存型別。

#022  //

查詢是否已經宣告。

#023  q = lookup(id, identifiers);

#024  if (q && q->scope >= level

#025         || q && q->scope == param && level == local)

#026         if (sclass == extern && q->sclass == extern

#027               && eqtype(q->type, ty, 1))

#028               ty = compose(ty, q->type);

#029         else

#030               error("redeclaration of `%s' previously declared at %w/n", q->name, &q->src);

#031  第

23行是查詢區域性變數是否已經宣告過。 在第

24行是判斷這個型別是否復合型別,如果不是就會出錯處理;如果是的話,就進行復合型別處理。

#032  //

儲存到區域性變數表。

#033  assert(level >= local);

#034  p = install(id, &identifiers, level,

#035         sclass == static || sclass == extern ? perm : func);

#036  p->type = ty;

#037  p->sclass = sclass;

#038  p->src = *pos;

#039  第

34行是儲存區域性變數到

identifiers

符號表。 第

36行到第

38行儲存區域性變數的屬性。

#040  switch (sclass)

#041  

#055         }

#056 

#057         if (!eqtype(p->type, q->type, 1))

#058               warning("declaration of `%s' does not match previous declaration at %w/n", q->name, &q->src);

#059 

#060         p->u.alias = q;

#061         break; 第

42行處理宣告為外面定義的區域性變數處理。

#062  case static:  

#063         (*ir->defsymbol)(p);

#064         initglobal(p, 0);

#065         if (!p->defined)

#066               if (p->type->size > 0)

#067              

#071               else

#072                    error("undefined size for `%t %s'/n",

#073                    p->type, p->name);

#074         p->defined = 1;

#075         break;

上面的**是處理靜態區域性變數。

#076  case register:

#078         regcount++;

#079         p->defined = 1;

#080         break;

上面的**是處理暫存器型別的區域性變數,新增到

registers

列表。

#081  case auto:    

#083         p->defined = 1;

#084         if (isarray(ty))

#085               p->addressed = 1;

#086 

#087         break;

上面的**是處理一般最常用的

auto

型別區域性變數,並且新增到

autos

列表。

#088  default: assert(0);

#089  }

#090 

#091 

下面的**開始處理區域性變數定義時的初始化行為。

#092  //

區域性變數的初始化處理。

#093  if (t == '=')

#094  ');

#110               }

#111               else

#112                    e = expr1(0); 第

102行是判斷簡單型別的初始化,還是陣列的初始化。 第

105行到第

110行是處理結構的初始化。 第

112行是處理簡單的表示式初始化。表示式函式

expr1

是乙個複雜的處理函式,後面再仔細地分析它的實現。

#113         }

#114         else

#115        

#131  第

115行到

130行是處理陣列的初始化。

#132         walk(root(asgn(p, e)), 0, 0);

#133         p->ref = 1;

#134  }

#135  第

132行是先呼叫函式

asgn

生成賦值語法樹,並且作為中間表示。接著呼叫函式

walk

去遍歷整個賦值樹,進行

dag處理,刪除一些公共表示式。後面再細述這些處理。

#136  if (!isfunc(p->type) && p->defined && p->type->size <= 0)

#137         error("undefined size for `%t %s'/n", p->type, id);

#138 

#139  return p;

#140 } 第

136行是處理區域性變數型別出錯。 在第

139行裡返回這個區域性變數的符號表示。

像第一節裡的例子:

int ntest1 = 1;

int ntest2 = 2;

int ntest3;

int i;

上面這些區域性變數都是通過上面的函式來處理完成的。

dcllocal

函式主要分析了區域性變數是否合法,然後新增到合適的區域性變數列表裡,最後分析區域性變數的初始化賦值。

LCC編譯器的源程式分析 12 13

語法分析是比較複雜的處理,下面再來分析乙個例子,它的 如下 typedef unsigned short wchar t typedef wchar t wint t 第一句語句在lcc裡的處理,前面已經解釋清楚,主要生成wchar t儲存符號表裡,並且記錄這個id的型別屬性。那麼第二句是怎麼樣通過...

LCC編譯器的源程式分析 18 19

lcc編譯器的源程式分析 19 全域性函式的定義 函式定義funcdefn處理裡,已經準備好呼叫引數和引數返回,接著就是呼叫全域性函式宣告來處理。如下面的 132 宣告函式。133 cfunc dclglobal sclass,id,ty,pt 134 上面的 是處理函式全域性定義。現在就去就分析d...

LCC編譯器的源程式分析 21 區域性變數的宣告

區域性變數的處理是比較特別,它是複雜語句裡面宣告,作用域也只限於復合語句裡。如下面的例子 上面的a 就是區域性變數的宣告。現在再來仔細地分析 compound 裡處理區域性變數的 如下 031 區域性變數宣告處理.032while kind t char kind t static 033 isty...