📄 symtab.c
字号:
}
// no function decl
// so only add def to function definition
add_symbol_to_symtab(sg_function_symtab, func);
return func;
}
// only declaration
// add or only check parameter type
// not overwrite parameter's type
void add_function_decl_to_functab(symbol *decl)
{
symbol *func;
if ( !IS_FUNCTION(decl) )
{
yyerror("not function in add_function_decl_to_functab()");
user_exit(1);
}
if ( func = search_symbol_in_symtab(sg_function_symtab, decl->name) )
{
// first check type....
if ( check_func_args_type(func, decl) )
{
// mismatch
yyerror("function definition or declaration mismatch");
user_exit(1);
}
// match
// however is definition or declaration
// the decl need not be added
// so return
return;
}
// no pre decl or definition
// so add it
add_symbol_to_symtab(sg_function_symtab, decl);
}
// check function return value
// array can't be return value
void check_function_retval(symbol *func)
{
assert( IS_FUNCTION(func) );
if ( IS_ARRAY(func) )
{
yyerror("function returns array");
user_exit(1);
}
if ( func->NOUN == SPEC_LABEL )
{
yyerror("function returns label");
user_exit(1);
}
}
// get symbol 's size
int get_symbol_size(symbol *p)
{
// ingore the is_long
// in bytes
int sym_size;
assert( p );
switch(p->NOUN)
{
case SPEC_CHAR:
sym_size = 1;
break;
case SPEC_FLOAT: // just as int
case SPEC_DOUBLE:// just as int
case SPEC_INT:
sym_size = 2;
break;
default:
yyerror("can't get symbol's size");
user_exit(1);
}
if ( IS_ARRAY(p) )
sym_size *= p->num_ele;
return sym_size;
}
// set local value or args rname
void set_local_or_args_rname(symbol *p)
{
assert(p);
sprintf(p->rname, get_asm_attri(p), abs(p->offset));
}
// get local value or args asm attrib "word ptr [bp-%d]" or "byte ptr [bp-%d]"
// or "word ptr [bp+%d]" or "byte ptr [bp+%d]"
char *get_asm_attri(symbol *p)
{
static char buf[NAME_LEN];
// ingore the is_long
// in bytes
assert( p );
// can used in gen code in array[],so...
// assert( !IS_ARRAY(p) );
switch(p->NOUN)
{
case SPEC_CHAR:
strcpy(buf, "byte ptr [bp");
break;
case SPEC_FLOAT: // just as int
case SPEC_DOUBLE:// just as int
case SPEC_INT:
strcpy(buf, "word ptr [bp");
break;
default:
yyerror("can't get asm attrib");
user_exit(1);
}
if (p->offset < 0)
// local value
strcat(buf, "-%d]");
else if (p->offset > 0)
strcat(buf, "+%d]");
else
{
yyerror("symbol->offset is 0, not local value or args, error!");
user_exit(1);
}
return buf;
}
// assign parameters rname
void assign_parameters_rname(symbol *args_list)
{
/* symbol *tmp;
// for ip,bp[old] in stack, so offset start value 4
// right args pus to stack first
int offset = 4;
assert( args_list );
// calculate the total offset
tmp = args_list;
while (tmp)
{
// must conside string , string can't be args
assert( IS_ARGUMENT(tmp) );
tmp->offset = offset;
if ( !IS_ARRAY(tmp) )
{
offset += get_symbol_size(tmp);
set_local_or_args_rname(tmp);
}
else
{
// note : array push address of the array, so...
// offset += 2, and it argument rname is word ptr [bp+...]
offset += 2;
sprintf(tmp->rname, "word ptr [bp+%d]", tmp->offset);
}
ALIGN_OFFSET(offset)
tmp = tmp->next;
}
*/
// left args push to stack first
symbol *tmp;
int offset = 0;
assert( args_list );
// calculate the total offset
tmp = args_list;
while (tmp)
{
// must conside string , string can't be args
assert( IS_ARGUMENT(tmp) );
if ( !IS_ARRAY(tmp) )
offset += get_symbol_size(tmp);
else
{
// note : array push address of the array, so...
// offset += 2, and it argument rname is word ptr [bp+...]
offset += 2;
}
ALIGN_OFFSET(offset)
tmp->offset = offset;
tmp = tmp->next;
}
offset += 4;
tmp = args_list;
while (tmp)
{
// must consider string , string can't be args
assert( IS_ARGUMENT(tmp) );
tmp->offset = offset - tmp->offset;
if ( !IS_ARRAY(tmp) )
set_local_or_args_rname(tmp);
else
sprintf(tmp->rname, "word ptr [bp+%d]", tmp->offset);
tmp = tmp->next;
}
}
// assign symbol a unused name
void assign_symbol_unusedname(symbol *p)
{
static int unuse_count = 0;
assert(p);
sprintf(p->name, _UNUSED_SYM_NAME, unuse_count++);
}
// set function 's offset to sub sp, offset
void set_func_offset(symbol *func)
{
assert( func );
if ( !IS_FUNCTION(func) )
{
yyerror("not function in set_func_offset()");
user_exit(1);
}
func->offset = sg_local_offset_top;
// reset sg_local_offset_top
sg_local_offset_top = 0;
}
// change cl value if necessary
void cast_cl_type(symbol *c1, symbol *c2)
{
symbol *d, *s;
assert(c1);
assert(c2);
assert( IS_CL(c1) && IS_CL(c2) );
if ( c1->NOUN == c2->NOUN )
return;
if ( c1->NOUN > c2->NOUN )
{
s = c1;
d = c2;
}
else
{
s = c2;
d = c1;
}
switch(s->NOUN)
{
// can't be char
case SPEC_INT:
d->V_I = (int)d->V_C;
break;
case SPEC_FLOAT:
switch(d->NOUN)
{
case SPEC_CHAR:
d->V_F = (float)d->V_C;
break;
case SPEC_INT:
d->V_F = (float)d->V_I;
break;
}
break;
case SPEC_DOUBLE:
switch(d->NOUN)
{
case SPEC_CHAR:
d->V_LF = (double)d->V_C;
break;
case SPEC_INT:
d->V_LF = (double)d->V_I;
break;
case SPEC_FLOAT:
d->V_LF = (double)d->V_F;
break;
}
break;
default:
yyerror("can not do cast cl type");
user_exit(1);
}
d->NOUN = s->NOUN;
}
// get symbol value as int
int get_sym_value(symbol *c)
{
int value;
assert(c);
// ingore double && float to int
switch( c->NOUN )
{
case SPEC_CHAR:
value = c->V_C;
break;
case SPEC_INT:
value = c->V_I;
break;
case SPEC_FLOAT:
value = (int)c->V_F;
break;
case SPEC_DOUBLE:
value = (int)c->V_LF;
break;
default:
yyerror("can't get value in get_sym_value()");
user_exit(1);
}
return value;
}
// clone a symbol with symbol
symbol *clone_symbol(symbol *p)
{
symbol *tmp;
assert(p);
tmp = new_symbol();
memcpy(tmp, p, sizeof(symbol));
// keep ->args for function
tmp->next = NULL;
tmp->lchild = NULL;
tmp->rchild = NULL;
return tmp;
}
// calcu function argument size
int get_function_args_size(symbol *func)
{
symbol *tmp;
int f_size = 0;
assert( func );
assert( IS_FUNCTION(func) );
tmp = func->args;
while ( tmp )
{
if ( !IS_ARRAY(tmp) )
f_size += get_symbol_size(tmp);
else
// for array send it address
f_size += 2;
tmp = tmp->next;
}
return f_size;
}
// create goto label symtab
void create_goto_label_symtab()
{
assert( !sg_goto_label_symtab );
sg_goto_label_symtab = create_symtab(_GOTO_LABEL_SYMTAB_NAME);
}
static void check_label_define(symbol *lb)
{
if ( !lb )
return;
assert( lb->NOUN == SPEC_LABEL );
if ( IS_LAB_DECL(lb) )
{
parse_error(lb->name, " label was undefined");
user_exit(1);
}
if ( lb->lchild )
check_label_define(lb->lchild);
if ( lb->rchild )
check_label_define(lb->rchild);
}
// destory goto label symtab
void destory_goto_label_symtab()
{
assert( sg_goto_label_symtab );
// check the label that not define
check_label_define(sg_goto_label_symtab->lchild);
check_label_define(sg_goto_label_symtab->rchild);
remove_symtab(sg_goto_label_symtab);
sg_goto_label_symtab = NULL;
}
// found the goto label in goto label symtab
symbol *search_goto_label(char *name)
{
assert( sg_goto_label_symtab );
return search_symbol_in_symtab(sg_goto_label_symtab, name);
}
// add goto label to goto label symtab
void add_goto_label(symbol *lb)
{
assert( sg_goto_label_symtab );
add_symbol_to_symtab(sg_goto_label_symtab, lb);
}
// operation for init_compound_stack
// create golbe symtab
static void init_compound_stack()
{
sg_compound_stack_sp = -1;
// new globe symtab
new_compound_symtab();
}
// destory golbe symbol
static void destory_compound_stack()
{
if ( sg_compound_stack_sp )
{
yyerror("compound statement exist except globe values, in destory_compound_stack()");
user_exit(1);
}
// delete globe symtab
del_compound_symtab();
}
static void create_function_symtab()
{
sg_function_symtab = create_symtab(_FUNCTION_SYMTAB_NAME);
}
static void destory_function_symtab()
{
remove_function_symtab_include_args(sg_function_symtab->lchild);
remove_function_symtab_include_args(sg_function_symtab->rchild);
del_symbol(sg_function_symtab);
sg_function_symtab = NULL;
}
void InitSymTab()
{
sg_local_offset = 0;
sg_local_offset_top = 0;
sg_goto_label_symtab = NULL;
// create globe symtab
init_compound_stack();
// init function symtab
create_function_symtab();
}
void DestorySymTab()
{
//Testing
dump_current_symtab();
dump_function_symtab();
// destory function symtab
destory_function_symtab();
// destory compound stack
destory_compound_stack();
}
// dump symbol for debug
static char *noun_info(unsigned noun)
{
switch( noun )
{
case SPEC_UNKNOW:
return "SPEC_UNKNOW";
case SPEC_VOID:
return "SPEC_VOID";
case SPEC_CHAR:
return "SPEC_CHAR";
case SPEC_INT:
return "SPEC_INT";
case SPEC_FLOAT:
return "SPEC_FLOAT";
case SPEC_DOUBLE:
return "SPEC_DOUBLE";
case SPEC_LABEL:
return "SPEC_LABEL";
}
return "not define noun";
}
static char *sclass_info(unsigned sclass)
{
switch( sclass )
{
case SPEC_UNKNOW:
return "SPEC_UNKNOW";
case SPEC_AUTO:
return "SPEC_AUTO";
case SPEC_REGISTER:
return "SPEC_REGISTER";
case SPEC_CONSTANT:
return "SPEC_CONSTANT";
case SPEC_TYPEDEF:
return "SPEC_TYPEDEF";
}
return "not define sclass";
}
void dump_symbol(symbol *p)
{
char buf[20];
if ( !p )
return;
StrToDebug( p->name, "\n=== DUMP SYMBOL :", " START....");
StrToDebug( p->rname, "\n ->rname :", NULL);
StrToDebug( itoa(p->is_symtab, buf, 10), "\n ->is_symtab :", NULL);
StrToDebug( itoa(p->is_function, buf, 10), "\n ->is_function :", NULL);
StrToDebug( itoa(p->is_declaration, buf, 10), "\n ->is_declaration :", NULL);
StrToDebug( itoa(p->is_array, buf, 10), "\n ->is_array :", NULL);
StrToDebug( itoa(p->is_argument, buf, 10), "\n ->is_argument :", NULL);
StrToDebug( itoa(p->is_assign, buf, 10), "\n ->is_assign :", NULL);
StrToDebug( itoa(p->is_cl, buf, 10), "\n ->is_cl :", NULL);
StrToDebug( itoa(p->is_rvalue, buf, 10), "\n ->is_rvalue :", NULL);
StrToDebug( itoa(p->is_pushed, buf, 10), "\n ->is_pushed :", NULL);
StrToDebug( itoa(p->num_ele, buf, 10), "\n ->num_ele :", NULL);
StrToDebug( itoa(p->offset, buf, 10), "\n ->offset :", NULL);
StrToDebug( noun_info(p->NOUN), "\n ->NOUN :", NULL );
StrToDebug( sclass_info(p->SCLASS), "\n ->SCLASS :", NULL );
StrToDebug( itoa(p->IS_LONG, buf, 10), "\n ->IS_LONG :", NULL);
StrToDebug( itoa(p->IS_UNSIGNED, buf, 10), "\n ->IS_UNSIGNED :", NULL);
StrToDebug( itoa(p->IS_STATIC, buf, 10), "\n ->IS_STATIC :", NULL);
StrToDebug( itoa(p->IS_EXTERN, buf, 10), "\n ->IS_EXTERN :", NULL);
// show const in later
// V_C
// V_UC
// V_I
// V_UI
// V_F
// V_LF
// V_STR
}
void dump_function(symbol *func)
{
symbol *tmp;
assert( IS_FUNCTION(func) );
StrToDebug( "\n FUNCTION : -> ", NULL, NULL);
dump_symbol(func);
StrToDebug( "\n arguments : -----", NULL, NULL);
tmp = func->args;
while ( tmp )
{
dump_symbol(tmp);
tmp = tmp->next;
}
StrToDebug( "\n ----- arguments end", NULL, NULL);
StrToDebug( "\n FUNCTION end <-", NULL, NULL);
}
static void dump_symtab( symbol *head, void (*p_dump_func)(symbol *) )
{
if ( !head ) //eg . dump_symtab(NULL)
return;
if ( head->lchild )
dump_symtab(head->lchild, p_dump_func);
(*p_dump_func)(head);
if ( head->rchild )
dump_symtab(head->rchild, p_dump_func);
}
void dump_current_symtab()
{
dump_symtab(sg_compound_stack[sg_compound_stack_sp].p_symtab, dump_symbol);
}
void dump_function_symtab()
{
dump_symtab(sg_function_symtab->lchild, dump_function);
dump_symtab(sg_function_symtab->rchild, dump_function);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -