LCC编译器的源程序分析(20)复合语句

C 语言里,有一种语句叫做复合语句。它是由 { } 把一些语句括起来的,如下面的例子:
{
 y = x + 1;
 z = y + 2;
}
LCC 里处理这样的复合语句的函数是 compound ,它在上面函数定义函数 funcdefn 是这样调用的:
#150  labels   = table(NULL, LABELS);
#151  stmtlabs = table(NULL, LABELS);
#152  refinc = 1.0;
#153  regcount = 0;
#154  codelist = &codehead;
#155  codelist->next = NULL;
#156 
#157  if (!IR->wants_callb && isstruct(rty))
#158         retv = genident(AUTO, ptr(unqual(rty)), PARAM);
#159 
上面的代码是准备生成代码。
 
#160  // 分析函数定义里的复合语句。
#161  compound(0, NULL, 0);
 
在第 161 行里就是调用 compound 函数,第一个参数设置为 0 ,第二个参数也是设置为空 NULL ,第三个参数是 0 。那么 compound 又是怎么样去分析复合语句,以及生成什么样的中间表示,以便后面生成汇编代码的呢?带着这几个疑问去看它的代码,就很容易理解了。
它的代码如下:
#001 // 复合语句分析函数。
#002 void compound(int loop, struct swtch *swp, int lev)
#003 {
#004  Code cp;
#005  int nregs;
#006 
#007  walk(NULL, 0, 0);
#008 
在第 7 行里调用函数 walk 来复位一些前面使用过的全局变量,以便后面可以正确地分析。
 
 
#009  // 代码块开始。
#010  cp = code(Blockbeg);
10 行是创建代码开始块 cp ,并保存这块代码块到代码列表 codelist 里。
 
 
#011  enterscope();
#012  assert(level >= LOCAL);
#013  
#014  if (level == LOCAL && events.entry)
#015         apply(events.entry, cfunc, NULL);
#016 
#017  definept(NULL);
#018 
11 行是增加复合语句的作用域。
14 行处理事件入口。
17 行是保存一个定义点,什么叫做定义点呢?它其实是为了调试使用的,比如在 C 源程序里,不是所有的行都可以设置断点的,而是有代码生成的行才能设置断点。当然定义点还可以作其它使用,比如调试时运行一句,跳到下一句,就需要使用到定义来同步。
 
 
#019  // 复合语句开始字符。
#020  expect('{');
#021  autos = registers = NULL;
#022  if (level == LOCAL && IR->wants_callb
#023         && isstruct(freturn(cfunc->type)))
#024  {
#025         retv = genident(AUTO, ptr(unqual(freturn(cfunc->type))), level);
#026         retv->defined = 1;
#027         retv->ref = 1;
#028         registers = append(retv, registers);
#029  }
#030 
20 行是测试是否复合语句的开始。
22 行到第 29 行是处理函数返回值。
 
 
#031  // 局部变量声明处理 .
#032  while ( kind[t] == CHAR || kind[t] == STATIC
#033               || istypename(t, tsym) && getchr() != ':')
#034  {
#035         decl(dcllocal);
#036  }   
#037 
32 行到第 36 行就是处理复合语句里所有局部变量的声明,局部变量的声明跟前面分析全局变量的声明是差不多的,不过它是调用函数 dcllocal 来处理局部变量的。这里也是递归地调用 decl 来处理声明。后面再仔细地分析局部变量的声明。
 
 
#038  //
#039  {
#040         int i;
#041         Symbol *a = ltov(&autos, STMT);
#042         nregs = length(registers);
#043         for (i = 0; a[i]; i++)
#044               registers = append(a[i], registers);
#045         cp->u.block.locals = ltov(&registers, FUNC);
#046  }
#047 
上面代码是处理自动类型和寄存器类型的局部变量的。
 
#048 
#049  if (events.blockentry)
#050         apply(events.blockentry, cp->u.block.locals, NULL);
#051  
上面处理定义了事件响应处理。
 
#052  while (kind[t] == IF || kind[t] == ID)
#053  {
#054         statement(loop, swp, lev);
#055  }   
#056  
上面代码是调用语句分析函数 statement 来处理,当然它也递归调用的。
 
#057  walk(NULL, 0, 0);
#058  
#059  foreach(identifiers, level, checkref, NULL);
#060  {
#061         int i = nregs, j;
#062         Symbol p;
#063         for ( ; (p = cp->u.block.locals[i]) != NULL; i++) {
#064               for (j = i; j > nregs
#065                    && cp->u.block.locals[j-1]->ref < p->ref; j--)
#066                    cp->u.block.locals[j] = cp->u.block.locals[j-1];
#067               cp->u.block.locals[j] = p;
#068         }
#069  }
#070 
57 行复位所有使用全部变量。
59 行到第 69 行是统计变量的引用计数。
 
 
#071  if (level == LOCAL)
#072  {
#073         Code cp;
#074         for (cp = codelist; cp->kind < Label; cp = cp->prev)
#075               ;
#076 
#077         if (cp->kind != Jump)
#078         {
#079               if (freturn(cfunc->type) != voidtype)
#080               {
#081                    warning("missing return value/n");
#082                    retcode(cnsttree(inttype, 0L));
#083               }
#084               else
#085                    retcode(NULL);
#086         }
#087  }
#088 
71 行处理局部函数返回值,如果在第 77 行里代码的类型不是跳转,就需生成返回代码。
 
 
#089  if (events.blockexit)
#090         apply(events.blockexit, cp->u.block.locals, NULL);
#091 
#092  cp->u.block.level = level;
#093  cp->u.block.identifiers = identifiers;
#094  cp->u.block.types = types;
#095  
#096  code(Blockend)->u.begin = cp;
#097  
#098  if (reachable(Gen))
#099         definept(NULL);
#100  
#101  if (level > LOCAL)
#102  {
#103         exitscope();
#104         expect('}');
#105  }
#106 }
上面保存复合语句的代码属性,就处理完成了复合语句。
 
这样就可以把复合语句分析完成,下一次再去仔细地分析在复合语句实现局部变量和简单语句的分析。 

你可能感兴趣的:(struct,汇编,table,null,编译器,Types)