📄 gen.cc
字号:
/* file "gen.cc" of the snoot program for SUIF *//* Copyright (c) 1994 Stanford University All rights reserved. This software is provided under the terms described in the "suif_copyright.h" include file. */#include <suif_copyright.h>/* * The back end of the front end. * * For help in understanding this code, read the documentation contained * in this file after reading "A Code Generation Interface for ANSI C" * by Fraser and Hanson from the lcc documentation. * * History: * * ? - 12/1992 Originally written and maintained for Old SUIF * by Rob French <rfrench@cs.stanford.edu>. * 12/1992 - 8/1993 Maintained and rewritten for New SUIF by * Todd Smith <tsmith@cs.stanford.edu>. * 8/1993 - ? Maintained and rewritten for even newer SUIF by * Chris Wilson <cwilson@cs.stanford.edu> * */#define RCS_BASE_FILE gen_cc#include <stdlib.h>#include <string.h>#include <ctype.h>#include <suif1.h>#include "c.h"RCS_BASE( "$Id: gen.cc,v 1.2 1999/08/25 03:28:20 brm Exp $")/* * Some symbol names will have to be generated. The following * prefixes are used in naming various types of symbols. If the * "passing type" of a parameter is not the same as the type inside * the called function, then it sends us the "passed parameter" and * the "real parameter"; the passed parameter gets a prefix and is * converted to the real one at the beginning of the function. * Temporary globals are given numbers in defsymbol(), to which the * prefix is prepended. The last number given is kept in * curr_tmp_global. */static char *tmp_string_prefix = "__tmp_string_";static char *tmp_param_prefix = "__tmp_param_";int curr_tmp_global = -1;file_set_entry *outf; // this is where all the output goesproc_sym *curr_proc = NULL; // pointer to object for current procedure/* * The Stacks * * We need three stacks to keep track of necessary information in a * procedure: * 1) list_stack * This is the stack of nested instruction lists which have * currently been suspended. The one in current use is stored * in curr_list. New lists are created for new blocks and for * the various parts of SUIF macros (if's, loop's, and for's, * via domacrocmd()). curr_list is used for appending * instructions as they are created. * 2) symtab_stack * This is the stack of nested symbol tables which have * currently been suspended, which corresponds exactly to the * stack of currently suspended blocks. The one in current use * is stored in curr_symtab. New symbol tables are created * only for new blocks. curr_symtab and symbol tables in the * stack are used for entering local variables. * 3) block_num_stack * This stack is a stack of block numbers that coincides with * symtab_stack. A sequence of blocks with the same parent * block is numbered 0...? in the position in this stack * corresponding to that nesting depth; thus, the numbers on * the stack up to the current nesting depth give each block a * unique hierarchical name. symtab_stack functions handle * this stuff and always keep the current number for use in * curr_block_num. */const int MAX_NESTING = 1000; // Maximum number of nested lists or // symbol tablestree_node_list *curr_list = NULL;tree_node_list *list_stack[MAX_NESTING];int list_stack_ptr = -1;block_symtab *curr_symtab = NULL;block_symtab *symtab_stack[MAX_NESTING];int symtab_stack_ptr = -1;int block_num_stack[MAX_NESTING+2];int curr_block_num = -1;/* * The top block of a function is created in start_function(), so * when stabblock() is called the first time, we don't want to create * it again. This boolean tells if stabblock() has skipped it yet. * It is also used at the end of functions when blocks are ended. */int skipped_top_block = 0;int curr_nesting_level = -1; // 0 == top block of a function#define MAXARGS 1000 // Maximum number of procedure argumentsint num_args = 0;operand args[MAXARGS]; // store up the arguments before a callvoid append_instr(instruction *instr);static void finalize_suif_proc(proc_sym *the_proc);static void finalize_suif_node(tree_node *the_node, void *);static void finalize_suif_instr(instruction *the_instr, void *);static annote *make_line_annote(Coordinate *location);/******************************************************************** * FUNCTIONS FOR HANDLING STACKS * ********************************************************************/void symtab_stack_init(void) { block_num_stack[1] = -1; }int symtab_stack_empty(void) { return (symtab_stack_ptr == -1); }void symtab_stack_push(block_symtab *b) { assert(symtab_stack_ptr < MAX_NESTING-1); symtab_stack[++symtab_stack_ptr] = b; curr_block_num = ++(block_num_stack[symtab_stack_ptr+1]); block_num_stack[symtab_stack_ptr+2] = -1; }block_symtab *symtab_stack_pop(void) { assert(symtab_stack_ptr > -1); curr_block_num = block_num_stack[symtab_stack_ptr]; return symtab_stack[symtab_stack_ptr--]; }void list_stack_push(tree_node_list *tnl) { assert(list_stack_ptr < MAX_NESTING-1); list_stack[++list_stack_ptr] = tnl; }tree_node_list *list_stack_pop(void) { assert(list_stack_ptr > -1); return list_stack[list_stack_ptr--]; }/******************************************************************** * MISCELLANEOUS USEFUL FUNCTIONS * * 1. functions dealing with scopes and symbol tables * ********************************************************************/// returns currently active symbol tableextern base_symtab *get_current_symtab(void) { return ((curr_symtab == NULL) ? ((base_symtab *)(outf->symtab())) : ((base_symtab *)curr_symtab)); }/******************************************************************** * LCC BACK-END FUNCTIONS FOR FUNCTION DEFINITION * ********************************************************************//* * addition to lcc interface; called a little while before function() * in order to set up the current procedure before defsymbol() is * called with some important information */extern void start_function(Symbol f, Symbol callee[], type_node *caller_types[], int num_params, Coordinate *block_location) { assert(f->suif_symbol != NULL); /* * function symbol should have already been sent to defsymbol(); * set up all its characteristics, and make sure it isn't marked as * extern */ curr_proc = (proc_sym *) f->suif_symbol; curr_proc->set_src_lang(src_c); assert(symtab_stack_empty()); assert(curr_nesting_level == -1); // set up function to receive symbols, types, code tree_block *b = curr_proc->block(); curr_list = b->body(); curr_symtab = b->symtab(); symtab_stack_init(); curr_nesting_level = 0; skipped_top_block = 0; b->annotes()->append(make_line_annote(block_location)); /* parameters are in reverse order */ for (int param_num = num_params; param_num > 0; --param_num) { Symbol s = callee[param_num - 1]; var_sym *the_var = curr_symtab->new_var(s->type, s->name); the_var->set_userdef(); s->suif_symbol = the_var; if (s->sclass == REGISTER) the_var->append_annote(k_is_declared_reg, new immed_list); var_sym *the_param = the_var; if (s->type->unqual() != caller_types[param_num - 1]->unqual()) { char *temp_name = new char[strlen(tmp_param_prefix) + strlen(s->name) + 1]; strcpy(temp_name, tmp_param_prefix); strcat(temp_name, s->name); the_param = curr_symtab->new_var(caller_types[param_num - 1], temp_name); operand param_op = fold_real_1op_rrr(io_cvt, the_var->type()->unqual(), operand(the_param)); curr_list->append(create_assignment(the_var, param_op)); delete[] temp_name; } the_param->set_param(); curr_proc->block()->proc_syms()->params()->append(the_param); } annote *a = new annote(k_enable_exceptions); a->immeds()->append("int_divide-by-0"); curr_proc->block()->annotes()->append(a); }void function(void) { // clean up after the function curr_symtab = NULL; curr_list = NULL; assert(symtab_stack_empty()); assert(curr_nesting_level == 0); curr_nesting_level = -1; finalize_suif_proc(curr_proc); curr_proc->write_proc(outf); curr_proc->flush_proc(); }/******************************************************************** * BEGINNING/END OF BLOCK FUNCTIONS * ********************************************************************/// enter/exit a block in the emit phase, with its user-defined localsvoid stabblock(int enter_or_exit) { // block entry code if (enter_or_exit == '{') { // if we just started a procedure and created its top block, // then skip it and don't do anything here if (curr_nesting_level == 0 && !skipped_top_block) skipped_top_block = 1; // otherwise, push current list/symtab and create a child block else { list_stack_push(curr_list); symtab_stack_push(curr_symtab); tree_node_list *new_list = new tree_node_list; block_symtab *new_symtab = new block_symtab(stringf("%d", curr_block_num)); tree_block *b = new tree_block(new_list, new_symtab); curr_list->append(b); curr_list = new_list; if (curr_symtab != NULL) curr_symtab->add_child(new_symtab); curr_symtab = new_symtab; curr_nesting_level++; } } // block exit code else if (enter_or_exit == '}') { // if we are ending a procedure, then reset skipped_top_block // and don't do anything yet
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -