📄 gen.cc
字号:
if (curr_nesting_level == 0 && skipped_top_block) { skipped_top_block = 0; } else { // otherwise, pop parent block from stack tree_node_list *next_list = list_stack_pop(); curr_list = next_list; curr_symtab = symtab_stack_pop(); curr_nesting_level--; } } else assert(0); }/******************************************************************** * LCC BACK-END FUNCTIONS FOR DEFINING SYMBOLS, ETC. * ********************************************************************//* * This function is called by lcc to define constants, globals, and statics. */void defsymbol(Symbol s) { assert(s->name != NULL); // if already processed, ignore it, except for special cases if (s->suif_symbol != NULL) { if (s->type != NULL && s->type->unqual()->is_func() && s->scope == GLOBAL && s->suif_symbol != NULL) { // check if the type has been completed if (s->suif_symbol->is_var()) { var_sym *v = (var_sym *)s->suif_symbol; type_node *curr_type = s->type; if (curr_type->size() > v->type()->size()) { boolean vis = v->parent()->make_type_visible(curr_type); assert(vis); v->set_type(curr_type); } } } return; } /* * all functions declared are entered in global symbol table; if this * function is actually defined later, it will be looked up and * filled in */ if (s->type != NULL && isfunc(s->type)) { /* * lcc seems to have a bug that causes it to generate multiple symbols * for the same procedure in certain circumstances so we have to check * for duplicates here */ proc_sym *p = outf->symtab()->lookup_proc(s->name); if (!p) { func_type *ft = (func_type *)s->type; fflush(stdout); global_symtab *the_symtab; if (s->sclass == STATIC) the_symtab = outf->symtab(); else the_symtab = fileset->globals(); boolean vis = the_symtab->make_type_visible(ft); assert(vis); p = the_symtab->new_proc(ft, src_unknown, s->name); proc_symtab *st = new proc_symtab(s->name); p->set_block(new tree_proc(new tree_node_list, st)); outf->symtab()->add_child(st); p->set_userdef(); } s->suif_symbol = p; } // constants get no symbol table entry else if (s->scope == CONSTANTS) ; /* * global non-function symbols get same name (or generated name), * put in global symbol table */ else if (s->scope == GLOBAL) { global_symtab *the_symtab; if (s->sclass == STATIC) the_symtab = outf->symtab(); else the_symtab = fileset->globals(); boolean vis = the_symtab->make_type_visible(s->type); assert(vis); var_sym *v = the_symtab->new_var(s->type, s->name); v->set_userdef(); if (s->sclass != STATIC) v->set_addr_taken(); else v->reset_addr_taken(); if (s->sclass != EXTERN) outf->symtab()->define_var(v, get_alignment(v->type())); s->suif_symbol = v; } /* * look up local externs to see if they are already declared at * global level; if not, declare them at global level */ else if (s->scope >= LOCAL && s->sclass == EXTERN) { var_sym *v = fileset->globals()->lookup_var(s->name); if (v == NULL) { boolean vis = fileset->globals()->make_type_visible(s->type); assert(vis); v = fileset->globals()->new_var(s->type, s->name); v->set_userdef(); v->set_addr_taken(); } s->suif_symbol = v; } /* * local statics get a symbol but are not entered in symbol table * yet, and get put in locals_without_a_home list until their home * block is determined */ else if (s->scope >= LOCAL && s->sclass == STATIC) { var_sym *v = curr_symtab->new_var(s->type, s->name); v->set_userdef(); curr_symtab->define_var(v, get_alignment(v->type())); s->suif_symbol = v; } // there better not be any other kinds of symbols else assert(0); }/* * Return a system defined static global variable. */extern var_sym *gen_static_global(type_node *ty) { char *name = stringf("%s%d", tmp_string_prefix, ++curr_tmp_global); boolean vis = outf->symtab()->make_type_visible(ty); assert(vis); var_sym *the_var = outf->symtab()->new_var(ty, name); the_var->reset_userdef(); the_var->reset_addr_taken(); outf->symtab()->define_var(the_var, get_alignment(ty)); return the_var; }/* * Return a system defined static local in the top level symbol table of the * current function. */extern var_sym *gen_static_local(type_node *ty, char *name) { assert(curr_proc != NULL); boolean vis = curr_proc->block()->proc_syms()->make_type_visible(ty); assert(vis); var_sym *the_var = curr_proc->block()->proc_syms()->new_var(ty, name); the_var->reset_userdef(); the_var->reset_addr_taken(); curr_proc->block()->proc_syms()->define_var(the_var, get_alignment(ty)); return the_var; }extern var_def *global(Symbol s) { /* * all this is used for is data initialization, so we only want * non-extern globals and local statics */ assert((s->scope == GLOBAL) || (s->scope >= LOCAL && s->sclass == STATIC)); /* * should have already been handled by defsymbol; make sure and * set up initialization stuff */ assert(s->suif_symbol != NULL); assert(s->suif_symbol->is_var()); return begin_initialization((var_sym *)(s->suif_symbol)); }extern var_def *begin_initialization(var_sym *to_initialize) { /* * If we have the case of a declaration that uses the ``extern'' * keyword, but which also has an initializer, we won't think it * needs a definition in the code that would otherwise define it * because at that point we haven't seen the initialization yet. * So here we need to explicityly check for and add a definition * if necessary. */ if (!to_initialize->has_var_def()) outf->symtab()->define_var(to_initialize, get_alignment(to_initialize->type())); var_def *the_def = to_initialize->definition(); assert(the_def != NULL); the_def->set_alignment(get_alignment(to_initialize->type())); return the_def; }/******************************************************************** * DATA INITIALIZATION FUNCTIONS * * attach initialization annotations to symbol that global() was * * just called on * ********************************************************************/// initialize current global symbol with constant of type ty and value vvoid defconst(var_def *the_def, type_node *the_type, immed value) { if (the_def == NULL) return; if (value.is_symbol()) { sym_node *symbol = value.symbol(); assert(symbol != NULL); if (symbol->is_var()) { var_sym *the_var = (var_sym *)symbol; the_var->set_addr_taken(); } } annote_list *current_annotes = the_def->annotes(); annote_list_e *tail_e = current_annotes->tail(); if (tail_e != NULL) { annote *last_annote = tail_e->contents; assert(last_annote != NULL); if (strcmp(last_annote->name(), k_repeat_init) == 0) { immed_list *immeds = last_annote->immeds(); immed_list_iter the_iter(immeds); if (!the_iter.is_empty()) { immed count_value = the_iter.step(); if (count_value.is_int_const() && !the_iter.is_empty()) { immed size_value = the_iter.step(); if (size_value.is_int_const() && !the_iter.is_empty()) { immed old_value = the_iter.step(); i_integer count = immed_to_ii(count_value); if ((old_value == value) && (size_value == immed(the_type->size())) && the_iter.is_empty()) { ++count; immed_list *new_list = new immed_list; new_list->append(ii_to_immed(count)); new_list->append(immed(the_type->size())); new_list->append(value); last_annote->set_data(new_list); return; } } } } } } annote *a = new annote(k_repeat_init); a->immeds()->append(immed(1)); a->immeds()->append(immed(the_type->size())); a->immeds()->append(value); the_def->annotes()->append(a); }// initialize current global symbol with string of character valuesvoid defstring(var_def *the_def, int len, char *s, type_node *the_type) { if (the_def == NULL) return; int n; annote *a = new annote(k_multi_init); a->immeds()->append(immed(the_type->size())); assert(the_type->unqual()->op() == TYPE_INT); base_type *the_base = (base_type *)(the_type->unqual()); for (n=0; n<len; n++) { a->immeds()->append(immed(the_base->is_signed() ? (signed char)s[n] : (unsigned char)s[n])); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -