您的位置:首页 > 其它

LCC编译器的源程序分析(69)全局变量的初始化

2007-12-17 10:26 459 查看
前面已经介绍了全局函数和全局变量的声明处理,但全局变量的初始化,还没有详细地分析,现在就来干这件事情。比如编写C的程序,有如下的代码:#001 #002 int g_nTest = 100;#003 #004 int main(void)#005 {#006 int nTest1 = 1;#007 int nTest2 = 2;像第2行代码就是全局变量的声明和初始化在一起的,那么在LCC里是怎么样处理它的呢?它的具体的分析流程是这样的:先调用函数dclglobal,其代码如下:#001 //保存符号的类型.#002 p->type = ty;#003 #004 //保存符号的位置#005 p->src = *pos;#006 #007 //是否函数非法初始化.#008 if (t == '=' && isfunc(p->type)) #009 {#010 error("illegal initialization for `%s'\n", p->name);#011 t = CCaiCompiler::Instance()->GetLex()->GetToken();#012 initializer(p->type, 0);#013 } #014 else if (t == '=') #015 {#016 //全局变量初始化.#017 initglobal(p, 0);#018 if (glevel > 0 && IR->stabsym) #019 {#020 (*IR->stabsym)(p); #021 swtoseg(p->u.seg); #022 }#023 } #024 else if (p->sclass == STATIC && !isfunc(p->type)#025 && p->type->size == 0)#026 {#027 //错误大小.#028 error("undefined size for `%t %s'\n", p->type, p->name);#029 }#030 在第14行里,就会把g_nTest变量后面的等号识别出来,然后就进入处理后面常量表达式的流程了。也就是调用函数initglobal来处理常量表达式的一大堆的工作,比如常量的计算,常量的类型,常量的保存位置等等。 initglobal函数如下:#001 //初始化全局变量.#002 static void initglobal(Symbol p, int flag) #003 {#004 Type ty;#005 #006 if (t == '=' || flag) #007 {#008 if (p->sclass == STATIC) #009 {#010 //静态变量分配在常量区或者数据区.#011 for (ty = p->type; isarray(ty); ty = ty->pType)#012 ;#013 defglobal(p, isconst(ty) ? LIT : DATA);#014 } #015 else#016 {#017 //分配在数据区.#018 defglobal(p, DATA);#019 }#020 #021 if (t == '=')#022 {#023 t = CCaiCompiler::Instance()->GetLex()->GetToken();#024 }#025 #026 //常量初始化处理.#027 ty = initializer(p->type, 0);#028 #029 #030 if (isarray(p->type) && p->type->size == 0)#031 {#032 p->type = ty;#033 }#034 #035 if (p->sclass == EXTERN)#036 {#037 p->sclass = AUTO;#038 }#039 #040 }#041 }在初始化initglobal函数里,调用函数defglobal来保存这个全局变量符号到汇编不同的段里,比如在数据段,还是在常量段。最后调用函数initializer来处理常量表达式,当然常量的值也需要保存到数据区的。 函数initializer是用来处理常量表达式的,它的代码如下:#001 /* 常量表达式的处理 - constexpr | { constexpr ( , constexpr )* [ , ] } */#002 Type initializer(Type ty, int lev) #003 {#004 int n = 0;#005 Tree e;#006 Type aty = NULL;#007 static char follow[] = { IF, CHAR, STATIC, 0 };#008 #009 ty = unqual(ty);#010 if (isscalar(ty)) #011 {#012 //基本类型初始化. #013 needconst++;#014 #015 //#016 if (t == '{')#017 {#018 //复合表达式的分析.#019 t = CCaiCompiler::Instance()->GetLex()->GetToken();#020 e = expr1(0);#021 initend(lev, follow);#022 }#023 else#024 {#025 //表达式分析1.#026 e = expr1(0);#027 }#028 #029 //返回基本类型的表达式树.#030 e = pointer(e);#031 #032 //根据左边类型和右边的类型来选择合适的返回类型.#033 if ((aty = assign(ty, e)) != NULL)#034 {#035 //类型转换.#036 e = cast(e, aty);#037 }#038 else#039 {#040 error("invalid initialization type; found `%t' expected `%t'\n",#041 e->type, ty);#042 }#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 {#054 //联合或结果初始化出错.#055 static char follow[] = { CHAR, STATIC, 0 };#056 error("cannot initialize undefined `%t'\n", ty);#057 skipto(';', follow);#058 return ty;#059 }#060 else if (isunion(ty)) #061 {#062 //联合的初始化.#063 if (t == '{') #064 {#065 t = CCaiCompiler::Instance()->GetLex()->GetToken();#066 n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);#067 initend(lev, follow);#068 }#069 else #070 {#071 if (lev == 0)#072 error("missing { in initialization of `%t'\n", ty);#073 #074 n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);#075 }#076 }#077 else if (isstruct(ty)) #078 {#079 //结构初始化.#080 if (t == '{') #081 {#082 t = CCaiCompiler::Instance()->GetLex()->GetToken();#083 n = initstruct(0, ty, lev + 1);#084 test('}', follow);#085 } #086 else if (lev > 0)#087 {#088 n = initstruct(ty->size, ty, lev + 1);#089 } #090 else #091 {#092 error("missing { in initialization of `%t'\n", ty);#093 n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);#094 }#095 }#096 #097 if (isarray(ty))#098 {#099 aty = unqual(ty->pType); #100 } #101 #102 if (isarray(ty) && ischar(aty)) #103 {#104 if (t == SCON) #105 {#106 if (ty->size > 0 && ty->size == tsym->type->size - 1)#107 tsym->type = array(chartype, ty->size, 0);#108 #109 n = tsym->type->size;#110 (*IR->defstring)((int)tsym->type->size, (char*)tsym->u.c.v.p);#111 t = CCaiCompiler::Instance()->GetLex()->GetToken();#112 }#113 else if (t == '{') #114 {#115 t = CCaiCompiler::Instance()->GetLex()->GetToken();#116 if (t == SCON) #117 {#118 ty = initializer(ty, lev + 1);#119 initend(lev, follow);#120 return ty;#121 }#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 { /* eg, char c[] = 0; */#130 error("missing { in initialization of `%t'\n", ty);#131 n = initchar(1, aty);#132 }#133 } #134 else if (isarray(ty)) #135 {#136 //数组初始化.#137 if (t == SCON && aty == widechar) #138 {#139 int i;#140 unsigned int *s = (unsigned int *)tsym->u.c.v.p;#141 if (ty->size > 0 && ty->size == tsym->type->size - widechar->size)#142 tsym->type = array(widechar, ty->size/widechar->size, 0);#143 #144 n = tsym->type->size;#145 for (i = 0; i < n; i += widechar->size) #146 {#147 Value v;#148 v.u = *s++;#149 (*IR->defconst)(widechar->op, widechar->size, v);#150 }#151 #152 t = CCaiCompiler::Instance()->GetLex()->GetToken();#153 } #154 else if (t == '{') #155 {#156 t = CCaiCompiler::Instance()->GetLex()->GetToken();#157 if (t == SCON && aty == widechar) #158 {#159 ty = initializer(ty, lev + 1);#160 initend(lev, follow);#161 return ty;#162 }#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 {#171 error("missing { in initialization of `%t'\n", ty);#172 n = initarray(aty->size, aty, lev + 1);#173 }#174 } #175 #176 //#177 if (ty->size) #178 {#179 //类型大小是否合适.#180 if (n > ty->size)#181 error("too many initializers\n");#182 else if (n < ty->size)#183 (*IR->space)(ty->size - n);#184 }#185 else if (isarray(ty) && ty->pType->size > 0)#186 ty = array(ty->pType, n/ty->pType->size, 0);#187 else#188 {#189 ty->size = n;#190 }#191 #192 //返回类型.#193 return ty;#194 } 通过调用表达式处理函数expr1来计算常量的值,然后调用后端接口genconst来生成保存常量的代码,并且设置变量g_nTest的初始化为常量表达式的值。这样就把全局变量初始化的代码分析完成。

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1767691
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: