📄 fileset.cc
字号:
error_line(1, NULL, "File '%s' has non-integer symtab pointer", is->name()); } if (!position_immed.is_long_int()) { error_line(1, NULL, "File '%s' is too big -- symtab pointer out of range of " "file indexing on this machine", is->name()); } long pos = position_immed.long_int(); delete an; delete mrk; if (pos == -1) { error_line(1, NULL, "File '%s' has no symtab pointer -- probably the result " "of a SUIF file which was never completely written out", is->name()); } is->setpos(pos); /* read the global symtab (temporarily make the new global symtab a child of the existing one so that it can access the predefined types while it is being read in) */ global_symtab *tmp_globals = new global_symtab("globals"); parent()->globals()->add_child(tmp_globals); tmp_globals->read(is); parent()->globals()->remove_child(tmp_globals); if (parent()->read_a_file) { /* make sure the new symbol table matches and delete it */ if (!disable_global_symtab_check) check_global_symtab(tmp_globals); delete tmp_globals; } else { /* move the file_symtab to be a child of tmp_globals */ parent()->globs->remove_child(symtab()); tmp_globals->add_child(symtab()); /* make sure the existing symbol table is empty (except possibly for some predefined types) and replace it */ assert_msg(parent()->globs->symbols()->is_empty() && parent()->globs->children()->is_empty(), ("global symbol table not empty")); delete parent()->globs; parent()->globs = tmp_globals; } /* read the file symtab */ symtab()->read(is); /* no need to restore the stream position */}/* * Make sure that a new global symtab matches the existing global symtab. * (The files in a file_set must be "linked" together by a separate SUIF * pass to match up the global symtab entries.) */voidfile_set_entry::check_global_symtab (global_symtab *newglobs){ global_symtab *globals = parent()->globals(); type_node_list_iter type_iter(newglobs->types()); while (!type_iter.is_empty()) { type_node *newtyp = type_iter.step(); type_node *oldtyp = globals->lookup_type_id(newtyp->type_id()); /* make sure they're equivalent */ if (!oldtyp || (oldtyp->op() != newtyp->op()) || (oldtyp->size() != newtyp->size())) { error_line(-1, NULL, "type in global symbol table does not match"); } } sym_node_list_iter sym_iter(newglobs->symbols()); while (!sym_iter.is_empty()) { sym_node *newsym = sym_iter.step(); sym_node *oldsym = globals->lookup_sym_id(newsym->sym_id()); /* make sure they're equivalent */ if (!oldsym || (oldsym->kind() != newsym->kind()) || (oldsym->name() != newsym->name())) { error_line(-1, NULL, "symbol in global symtab does not match"); } }}/* * Several kinds of information are included as annotations on the * file_set_entries. These annotations are stripped off when the file * is first opened. First, the target machine parameters are read. If * this is the first input file to be read, the global "target" structure * is updated. Otherwise, the parameters are checked against the existing * ones. Second, the file_set_entry contains annotations to identify * procedure symbols whose bodies are defined within the file. This * information is read and used to set the "file" pointers in the proc_syms. */voidfile_set_entry::get_contents (){ /* read the target machine parameters */ get_machine_param((int*)&target.is_big_endian, k_is_big_endian, FALSE, parent()->read_a_file); get_machine_param(&target.addressable_size, k_addressable_size, FALSE, parent()->read_a_file); get_machine_param((int*)&target.char_is_signed, k_char_is_signed, FALSE, parent()->read_a_file); while (get_machine_param(&target.size[0], k_C_type_size, TRUE, parent()->read_a_file)) { } while (get_machine_param(&target.align[0], k_C_type_align, TRUE, parent()->read_a_file)) { } get_machine_param(&target.array_align, k_array_align, FALSE, parent()->read_a_file); get_machine_param(&target.struct_align, k_struct_align, FALSE, parent()->read_a_file); int tmp_pdiff_type = target.ptr_diff_type; get_machine_param(&tmp_pdiff_type, k_ptr_diff_type, FALSE, parent()->read_a_file); target.ptr_diff_type = (C_types)tmp_pdiff_type; /* check if this is the first input file */ if (!parent()->read_a_file) { parent()->read_a_file = TRUE; /* reset the predefined type pointers to use the new parameters */ parent()->globals()->predefine_types(); } /* find out which procedure bodies are contained in this file */ immed_list *iml; while ((iml = (immed_list *)get_annote(k_proc_in_file))) { proc_sym *psym = (proc_sym *)iml->pop().symbol(); assert(psym->is_proc()); psym->set_extern(FALSE); psym->fse = this; psym->file_pos = iml->pop().long_int(); delete iml; }}/* * Read a machine parameter annotation from the file_set_entry. If this * is the first entry in the file_set, the parameter overrides the default * value. Otherwise, this just checks that all of the parameters match * the values specified in the first file_set_entry. */booleanfile_set_entry::get_machine_param (int *flag, char *annote_name, boolean is_array, boolean read_a_file){ immed_list *iml = (immed_list *)get_annote(annote_name); if (iml) { int val = iml->pop().integer(); if (is_array) { flag += val; val = iml->pop().integer(); } delete iml; if (read_a_file) { if (*flag != val) { error_line(1, NULL, "machine parameter annotation '%s' " "does not match", annote_name); } } else { *flag = val; } return TRUE; } return FALSE;}/* * Write out the global and file symbol tables. */voidfile_set_entry::write_table (){ /* get the file position where the symtab will be written */ long current_pos = os->getpos(); /* create a mark to record the symtab position */ instruction *symtab_ptr = new in_rrr(io_mrk); annote *an = new annote(k_file_symtab_ptr); an->immeds()->append(immed(current_pos)); symtab_ptr->annotes()->append(an); /* write the mark at the beginning of the file */ os->flush_cache(); os->setpos(symtab_ptr_loc); symtab_ptr->write(os); delete symtab_ptr; /* go back and write out the symtab */ os->setpos(current_pos); os->flush_cache(); parent()->globals()->write(os); symtab()->write(os);}/* * File_set_entry destructor. If necessary, write out the file_symtab * and file_set_entry annotations. Close the i/o streams. */file_set_entry::~file_set_entry (){ delete global_proc_iter; delete static_proc_iter; /* close the i/o streams */ if (is) { parent()->close_stream(is); delete is; } if (os) { parent()->open_stream(os, this); assert(write_scope == NULL); write_scope = symtab(); /* write the file symtab */ write_table(); /* save the target machine parameters on the file_set_entry */ save_machine_param(target.is_big_endian, k_is_big_endian, -1); save_machine_param(target.addressable_size, k_addressable_size, -1); save_machine_param(target.char_is_signed, k_char_is_signed, -1); for (int i = 0; i < num_C_types; i++) { save_machine_param(target.size[i], k_C_type_size, i); save_machine_param(target.align[i], k_C_type_align, i); } save_machine_param(target.array_align, k_array_align, -1); save_machine_param(target.struct_align, k_struct_align, -1); save_machine_param(target.ptr_diff_type, k_ptr_diff_type, -1); if (file_id() != 0) { immed_list *file_num_immeds = new immed_list; file_num_immeds->append(immed(file_id())); append_annote(k_file_num, file_num_immeds); } /* write the file_set_entry annotations */ instruction *mrk = new in_rrr(io_mrk); copy_annotes(mrk); mrk->write(os); delete mrk; /* write the end-of-stream marker */ os->write_int((int)io_eos); assert(write_scope == symtab()); write_scope = NULL; parent()->close_stream(os); delete os; } /* remove the symtab from its parent's child list */ if (symtab()) { assert_msg(symtab()->parent(), ("symbol table has no parent!")); symtab()->parent()->remove_child(symtab()); delete symtab(); }}/* * Save one of the target machine parameters as an annotation on the * file_set_entry. If the "ndx" parameter is non-negative, store it * as the first immed value on the annotation. */voidfile_set_entry::save_machine_param (int val, char *annote_name, int ndx){ annote *an = new annote(annote_name); if (ndx >= 0) { an->immeds()->append(immed(ndx)); } an->immeds()->append(immed(val)); annotes()->append(an);}/* * Find the name of the file. If there is no input stream, use the * name from the output stream. */char *file_set_entry::name (){ if (is) return is->name(); return os->name();}voidfile_set_entry::add_outfile (char *outn){ assert(os == NULL); assert(outn != NULL); os = new out_stream(lexicon->enter(outn)->sp); /* write the header for the output stream */ par->open_stream(os, this); assert(write_scope == NULL); write_scope = table; /* write out a mark to record the position of the file symtab */ instruction *mrk = new in_rrr(io_mrk); annote *an = new annote(k_file_symtab_ptr); an->immeds()->append(immed(-1)); mrk->annotes()->append(an); symtab_ptr_loc = os->getpos(); mrk->write(os); delete mrk; assert(write_scope == table); write_scope = NULL;}/* * Reset the procedure iterators. */voidfile_set_entry::reset_proc_iter (){ global_proc_iter->reset(parent()->globals()->symbols()); static_proc_iter->reset(symtab()->symbols());}/* * Find the next proc_sym that is defined (not extern). Because * proc_syms may appear in either the global or file symtabs, we * actually need two iterators here. */proc_sym *file_set_entry::next_proc (){ /* first check the file symtab */ while (!static_proc_iter->is_empty()) { sym_node *sn = static_proc_iter->step(); if (sn->is_proc()) return (proc_sym *)sn; } /* next check the global symtab */ while (!global_proc_iter->is_empty()) { sym_node *sn = global_proc_iter->step(); if (sn->is_proc()) { proc_sym *psym = (proc_sym *)sn; if (psym->file() == this) return psym; } } return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -