📄 symbol.c
字号:
#include <string.h>
#include <stdio.h>
#include "symbol.h"
#include "utility.h"
#include "genasm.h"
struct _node *symtab[SYMTABSIZE];
struct _node *typetab[TYPETABSIZE];
struct _sym *current_func = NULL;
typedef struct _defines{
List add;
List dup;
}LocalDefines;
static LocalDefines *current_block;
static List block_list;
List const_list; //const string, or like that
List data_list;//data
List bss_list;//data?
List extern_list; //extern var and all function decl
static List label_list;
struct _datatype *newType(
char *name,
int bt,
struct _expnode *array_vol
)
{
Type *type;
type = dmalloc(sizeof(Type), true);
type->tname = name;
type->basic_type= bt;
if(array_vol)
{
type->array_vol= UNKNOWN;//set the default value for easy analysis
if(array_vol->exptype == exp_const)
{
bt = array_vol->datatype->basic_type;
if(bt == bt_pointer)
generror(ERR_TYPE_CONFLICT, "in dimension size");
else if(bt == bt_double)
type->array_vol = (unsigned)array_vol->val.f;
else
{//ignore the sign bit
if(array_vol->val.i<=0)
generror(ERR_EXPECT_POSITIVE, "in dimension size");
else
type->array_vol=array_vol->val.i;
}
}
else if(array_vol->exptype != exp_void)//only void are temp allowed ?????
generror(ERR_EXPECT_CONST, "in dimension size");
}
else type->array_vol=0;
type->memlist = NULL;
type->arglist = NULL;
switch(bt)
{
case bt_void:
case bt_ellipsis:
type->size = 0;
break;
case bt_char:
case bt_unsignedchar:
type->size =1;
break;
case bt_short:
case bt_unsignedshort:
type->size = 2;
break;
case bt_int:
case bt_unsignedint:
case bt_long:
case bt_unsignedlong:
case bt_float:
case bt_enum:
case bt_func://need to convert to bt_funcptr later
case bt_funcptr:
type->size = 4;
break;
case bt_double:
type->size = 8;
break;
case bt_struct:
case bt_union:
case bt_typedef:
type->size = UNKNOWN;
break;
case bt_pointer:
type->size = array_vol?UNKNOWN:4;
break;
}
type->subtype = NULL;
return type;
}
int check_basictype(
int prefix,
int origin
)//lots of bug, just for simple use
{
if(prefix == bt_long)
{
if(origin == bt_int)
return bt_long;
else if(origin == bt_unsignedint)
return bt_unsignedlong;
else if(origin == bt_double)
return bt_double;
}
else if(prefix == bt_short)
{
if(origin == bt_int)
return bt_short;
else if(origin == bt_unsignedint)
return bt_unsignedshort;
}
else if(prefix == bt_unsignedint)
{
if(origin == bt_long)
return bt_unsignedlong;
else if(origin == bt_short)
return bt_unsignedshort;
else if(origin == bt_char)
return bt_unsignedchar;
else if(origin == bt_int)
return bt_unsignedint;
}
else if(prefix == bt_int)//signed
{
if(origin != bt_unsignedchar ||origin !=bt_unsignedint
||origin != bt_unsignedshort ||origin!=bt_unsignedlong)
return origin;
}
generror(ERR_WRONG_BASIC_TYPE, NULL);
return origin;
}
//when and only when in function argument list declaration, the name can be null
struct _sym *newSymbol(
char *name,
int sc,
Type *datatype
)
{
Symbol *sym = dmalloc(sizeof(Symbol), true);
//to ensure every symbol have a name
sym->name = name?name:"parameter";
sym->storage_class =sc;
sym->datatype = datatype;
sym->init = NULL;
sym->next = NULL;
sym->refcount = 0;
//all member in value have the same size
sym->value.linkname = NULL;
return sym;
}
struct _sym *newEnumerator(
char *name,
struct _expnode * val)
{
Symbol *sym = newSymbol(name, sc_member, newType(NULL, bt_long, NULL));
HashNode *hashnode;
sym->const_flag =1;
if(val == NULL)
sym->value.i = UNKNOWN;
else if(val->exptype == exp_const)
{
sym->value.i = val->val.i;
}
else
{
sym->value.i = UNKNOWN;
generror(ERR_EXPECT_CONST, name);
}
//add to symbol table;
hashnode =add_node(symtab, SYMTABSIZE, name, sym);
if(hashnode)
{
generror(ERR_REDEF_VAR, name);
}
return sym;
}
struct _supertype *newSuperType(
int sc,
struct _datatype *type
)
{
struct _supertype *one = dmalloc(sizeof(SuperType), true);
one->sc = sc;
one->datatype = type;
return one;
}
struct _node **member_declare(
int bt,
struct _stmtnode *declaration_list,
int *size //out
)
{
SuperType *spec;
Symbol *dec; //dec means declarator
HashNode **memlist=dmalloc(sizeof(HashNode*)*MEMTABSIZE, false);
*size=0;
memset(memlist, 0, sizeof(HashNode*)*MEMTABSIZE);
for(;declaration_list;declaration_list=declaration_list->next)
{
spec = declaration_list->spec;
dec = declaration_list->declist;
for(;dec;dec=dec->next)
{
dec->storage_class = sc_member;
dec->datatype = compoundType(dec->datatype, spec->datatype);
checkTypeSize(dec->datatype);
if(add_node(memlist, MEMTABSIZE, dec->name, dec))
{
generror(ERR_REDEF_MEMBER, dec->name);
}
if(bt == bt_struct)
{
*size = align_add(*size, dec->datatype->size);
dec->value.offset=*size-dec->datatype->size;
}
else
{
*size = MAX(*size, dec->datatype->size);
dec->value.offset =0;
}
}
}
if(*size&3)
*size = (*size&~3)+4;
return memlist;
}
struct _datatype *new_sameType(
struct _datatype *type,
bool auto_flag
)
{
Type *same = NULL, *p, *q;
for(;type;type=type->subtype)
{
q=dmalloc(sizeof(Type), auto_flag);
memcpy(q, type, sizeof(Type));
if(!same)same = p =q;
else p =p->subtype = q;
}
return same;
}
struct _datatype *compoundType(
struct _datatype *origin,
struct _datatype *extra
)
{
Type *p=origin;
if(!origin)
return extra;
for(p=origin;p->subtype;p=p->subtype);
//for function pointer convert
if(extra->basic_type == bt_func)
{
if(p->basic_type == bt_pointer)
{
if(p->array_vol)
generror(ERR_ARRAY_FUNC, NULL);
else
{
memcpy(p, extra, sizeof(Type));
p->basic_type = bt_funcptr;
}
}
else
debug("compoumdType error\n");
}
else if(p->basic_type == bt_pointer
||p->basic_type == bt_func
||p->basic_type == bt_funcptr
||p->basic_type == bt_typedef)
p->subtype = extra;
else debug("compoumdType error\n");
return origin;
}
//check and return the size of this type
int checkTypeSize(
struct _datatype* type
)//all member in type should be ready
{
if(!type)
debug("[checkTypeSize] fatal error, null pointer input\n");
//if(type->size != UNKNOWN)
// return type->size;
switch(type->basic_type)
{
case bt_struct:
case bt_union:
//in C struct/union is just a label
// if(!type->memlist)
// generror(ERR_STRUCT_VACANT, type->tname);
break;
case bt_typedef:
case bt_pointer:
checkTypeSize(type->subtype);
if(type->basic_type == bt_typedef)
type->size = type->subtype->size;
else if(type->array_vol != 0)
type->size = type->array_vol * type->subtype->size;
break;
default:
break;
}
if(!type->size)
generror(ERR_ZERO_SIZE, type->tname);
else if(type->size == UNKNOWN)
generror(ERR_UNKNOWN_SIZE, type->tname);
return type->size;
}
//sometimes it will do some modify
//return status 0 is ok, 1 is almost ok, 2 is not ok
int checkTypeSame(
struct _datatype *t1,
struct _datatype *t2
)
{
Symbol *sym1,*sym2;
//t1, t2 are all valid
if(!t1||!t2)
{
debug("[checkType] null pointer input\n");
return 2;
}
if(t1 == t2
||t1->basic_type == bt_ellipsis
||t2->basic_type == bt_ellipsis)
return 0;
if(t1->memlist && t2->memlist && t1->memlist != t2->memlist)
return 2;
if(t1->basic_type!=t2->basic_type)
{
if(is_real(t1->basic_type)&&is_real(t2->basic_type))
return 1;
else
return 2;
}
switch(t1->basic_type)
{
case bt_struct:
case bt_union:
if(t1->tname&&t2->tname
&&strcmp(t1->tname,t2->tname))
return 2;
if(t1->memlist)
{
t2->memlist = t1->memlist;
t2->size = t1->size;
}
else
{
t1->memlist = t2->memlist;
t1->size = t2->size;
}
break;
case bt_funcptr:
if(t1->arglist == t2->arglist)
break;
sym1= t1->arglist;
sym2= t2->arglist;
while(sym2&&sym1)
{
if(checkTypeSame(sym1->datatype, sym2->datatype)>1)break;
sym1->name = sym2->name;//....
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -