LCC編譯器的源程式分析 69 全域性變數的初始化

2021-04-13 08:17:09 字數 4090 閱讀 8900

前面已經介紹了全域性函式和全域性變數的宣告處理,但全域性變數的初始化,還沒有詳細地分析,現在就來幹這件事情。比如編寫

c的程式,有如下的**:

#001 

#002 int g_ntest = 100;

#003 

#004 int main(void)

#005 

#014  else if (t == '=')

#015  

#023  }

#024  else if (p->sclass == static && !isfunc(p->type)

#025         && p->type->size == 0)

#026  

#030  在第

14行裡,就會把

g_ntest

變數後面的等號識別出來,然後就進入處理後面常量表示式的流程了。也就是呼叫函式

initglobal

來處理常量表示式的一大堆的工作,比如常量的計算,常量的型別,常量的儲存位置等等。

initglobal

函式如下:

#001 //

初始化全域性變數.

#002 static void initglobal(symbol p, int flag)

#003 

#015         else

#016        

#020 

#021         if (t == '=')

#022        

#025 

#026         //

常量初始化處理.

#027         ty = initializer(p->type, 0);

#028 

#029 

#030         if (isarray(p->type) && p->type->size == 0)

#031        

#034 

#035         if (p->sclass == extern)

#036        

#039 

#040  }

#041 }

在初始化

initglobal

函式裡,呼叫函式

defglobal

來儲存這個全域性變數符號到彙編不同的段裡,比如在資料段,還是在常量段。最後呼叫函式

initializer

來處理常量表示式,當然常量的值也需要儲存到資料區的。 函式

initializer

是用來處理常量表示式的,它的**如下:

#001 /*

常量表示式的處理

- constexpr | */

#002 type initializer(type ty, int lev)

#003 ;

#008 

#009  ty = unqual(ty);

#010  if (isscalar(ty))

#011  

#023         else

#024        

#028 

#029         //

返回基本型別的表示式樹.

#030         e = pointer(e);

#031 

#032         //

根據左邊型別和右邊的型別來選擇合適的返回型別.

#033         if ((aty = assign(ty, e)) != null)

#034        

#038         else

#039        

#043 

#044         //

根據常量表示式生成**.

#045         n = genconst(e, 1);

#046 

#047 

#048         deallocate(stmt);

#049         needconst--;

#050  }

#051 

#052  if ((isunion(ty) || isstruct(ty)) && ty->size == 0)

#053  ;

#056         error("cannot initialize undefined `%t'/n", ty);

#057         skipto(';', follow);

#058         return ty;

#059  }

#060  else if (isunion(ty))

#061  

#069         else

#070        

#076  }

#077  else if (isstruct(ty))

#078  ', follow);

#085         }

#086         else if (lev > 0)

#087            

#090         else

#091        

#095  }

#096 

#097  if (isarray(ty))

#098      

#101 

#102  if (isarray(ty) && ischar(aty))

#103  

#113         else if (t == '

#122 

#123               n = initchar(0, aty);

#124               test('}', follow);

#125         }

#126         else if (lev > 0 && ty->size > 0)

#127               n = initchar(ty->size, aty);

#128         else

#129        

#133  }

#134  else if (isarray(ty))

#135  

#151  

#152               t = ccaicompiler::instance()->getlex()->gettoken();

#153         }

#154         else if (t == '

#163 

#164               n = initarray(0, aty, lev + 1);

#165               test('}', follow);

#166         }

#167         else if (lev > 0 && ty->size > 0)

#168               n = initarray(ty->size, aty, lev + 1);

#169         else

#170        

#174  }   

#175 

#176  //

#177  if (ty->size)

#178  

#185  else if (isarray(ty) && ty->ptype->size > 0)

#186         ty = array(ty->ptype, n/ty->ptype->size, 0);

#187  else

#188  

#191 

#192  //

返回型別.

#193  return ty;

#194 }

通過呼叫表示式處理函式

expr1

來計算常量的值,然後呼叫後端介面

genconst

來生成儲存常量的**,並且設定變數

g_ntest

的初始化為常量表示式的值。這樣就把全域性變數初始化的**分析完成。

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編譯器的源程式分析 20 復合語句

在 c語言裡,有一種語句叫做復合語句。它是由 把一些語句括起來的,如下面的例子 在lcc 裡處理這樣的復合語句的函式是 compound 它在上面函式定義函式 funcdefn 是這樣呼叫的 150labels table null,labels 151stmtlabs table null,lab...