📄 tree.c
字号:
saveable_allocation (){ /* Note that function_obstack at top level points to temporary_obstack. But within a nested function context, it is a separate obstack. */ expression_obstack = current_obstack = saveable_obstack;}/* Switch to current obstack CURRENT and maybepermanent obstack SAVEABLE, recording the previously current obstacks on a stack. This does not free any storage in any obstack. */voidpush_obstacks (current, saveable) struct obstack *current, *saveable;{ struct obstack_stack *p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack, (sizeof (struct obstack_stack))); p->current = current_obstack; p->saveable = saveable_obstack; p->expression = expression_obstack; p->rtl = rtl_obstack; p->next = obstack_stack; obstack_stack = p; current_obstack = current; expression_obstack = current; rtl_obstack = saveable_obstack = saveable;}/* Save the current set of obstacks, but don't change them. */voidpush_obstacks_nochange (){ struct obstack_stack *p = (struct obstack_stack *) obstack_alloc (&obstack_stack_obstack, (sizeof (struct obstack_stack))); p->current = current_obstack; p->saveable = saveable_obstack; p->expression = expression_obstack; p->rtl = rtl_obstack; p->next = obstack_stack; obstack_stack = p;}/* Pop the obstack selection stack. */voidpop_obstacks (){ struct obstack_stack *p = obstack_stack; obstack_stack = p->next; current_obstack = p->current; saveable_obstack = p->saveable; expression_obstack = p->expression; rtl_obstack = p->rtl; obstack_free (&obstack_stack_obstack, p);}/* Nonzero if temporary allocation is currently in effect. Zero if currently doing permanent allocation. */intallocation_temporary_p (){ return current_obstack != &permanent_obstack;}/* Go back to allocating on the permanent obstack and free everything in the temporary obstack. FUNCTION_END is true only if we have just finished compiling a function. In that case, we also free preserved initial values on the momentary obstack. */voidpermanent_allocation (function_end) int function_end;{ /* Free up previous temporary obstack data */ obstack_free (&temporary_obstack, temporary_firstobj); if (function_end) { obstack_free (&momentary_obstack, momentary_function_firstobj); momentary_firstobj = momentary_function_firstobj; } else obstack_free (&momentary_obstack, momentary_firstobj); obstack_free (function_maybepermanent_obstack, maybepermanent_firstobj); obstack_free (&temp_decl_obstack, temp_decl_firstobj); /* Free up the maybepermanent_obstacks for any of our nested functions which were compiled at a lower level. */ while (inline_obstacks) { struct simple_obstack_stack *current = inline_obstacks; inline_obstacks = current->next; obstack_free (current->obstack, 0); free (current->obstack); free (current); } current_obstack = &permanent_obstack; expression_obstack = &permanent_obstack; rtl_obstack = saveable_obstack = &permanent_obstack;}/* Save permanently everything on the maybepermanent_obstack. */voidpreserve_data (){ maybepermanent_firstobj = (char *) obstack_alloc (function_maybepermanent_obstack, 0);}voidpreserve_initializer (){ struct momentary_level *tem; char *old_momentary; temporary_firstobj = (char *) obstack_alloc (&temporary_obstack, 0); maybepermanent_firstobj = (char *) obstack_alloc (function_maybepermanent_obstack, 0); old_momentary = momentary_firstobj; momentary_firstobj = (char *) obstack_alloc (&momentary_obstack, 0); if (momentary_firstobj != old_momentary) for (tem = momentary_stack; tem; tem = tem->prev) tem->base = momentary_firstobj;}/* Start allocating new rtl in current_obstack. Use resume_temporary_allocation to go back to allocating rtl in saveable_obstack. */voidrtl_in_current_obstack (){ rtl_obstack = current_obstack;}/* Start allocating rtl from saveable_obstack. Intended to be used after a call to push_obstacks_nochange. */voidrtl_in_saveable_obstack (){ rtl_obstack = saveable_obstack;}/* Allocate SIZE bytes in the current obstack and return a pointer to them. In practice the current obstack is always the temporary one. */char *oballoc (size) int size;{ return (char *) obstack_alloc (current_obstack, size);}/* Free the object PTR in the current obstack as well as everything allocated since PTR. In practice the current obstack is always the temporary one. */voidobfree (ptr) char *ptr;{ obstack_free (current_obstack, ptr);}/* Allocate SIZE bytes in the permanent obstack and return a pointer to them. */char *permalloc (size) int size;{ return (char *) obstack_alloc (&permanent_obstack, size);}/* Allocate NELEM items of SIZE bytes in the permanent obstack and return a pointer to them. The storage is cleared before returning the value. */char *perm_calloc (nelem, size) int nelem; long size;{ char *rval = (char *) obstack_alloc (&permanent_obstack, nelem * size); bzero (rval, nelem * size); return rval;}/* Allocate SIZE bytes in the saveable obstack and return a pointer to them. */char *savealloc (size) int size;{ return (char *) obstack_alloc (saveable_obstack, size);}/* Print out which obstack an object is in. */voidprint_obstack_name (object, file, prefix) char *object; FILE *file; char *prefix;{ struct obstack *obstack = NULL; char *obstack_name = NULL; struct function *p; for (p = outer_function_chain; p; p = p->next) { if (_obstack_allocated_p (p->function_obstack, object)) { obstack = p->function_obstack; obstack_name = "containing function obstack"; } if (_obstack_allocated_p (p->function_maybepermanent_obstack, object)) { obstack = p->function_maybepermanent_obstack; obstack_name = "containing function maybepermanent obstack"; } } if (_obstack_allocated_p (&obstack_stack_obstack, object)) { obstack = &obstack_stack_obstack; obstack_name = "obstack_stack_obstack"; } else if (_obstack_allocated_p (function_obstack, object)) { obstack = function_obstack; obstack_name = "function obstack"; } else if (_obstack_allocated_p (&permanent_obstack, object)) { obstack = &permanent_obstack; obstack_name = "permanent_obstack"; } else if (_obstack_allocated_p (&momentary_obstack, object)) { obstack = &momentary_obstack; obstack_name = "momentary_obstack"; } else if (_obstack_allocated_p (function_maybepermanent_obstack, object)) { obstack = function_maybepermanent_obstack; obstack_name = "function maybepermanent obstack"; } else if (_obstack_allocated_p (&temp_decl_obstack, object)) { obstack = &temp_decl_obstack; obstack_name = "temp_decl_obstack"; } /* Check to see if the object is in the free area of the obstack. */ if (obstack != NULL) { if (object >= obstack->next_free && object < obstack->chunk_limit) fprintf (file, "%s in free portion of obstack %s", prefix, obstack_name); else fprintf (file, "%s allocated from %s", prefix, obstack_name); } else fprintf (file, "%s not allocated from any obstack", prefix);}voiddebug_obstack (object) char *object;{ print_obstack_name (object, stderr, "object"); fprintf (stderr, ".\n");}/* Return 1 if OBJ is in the permanent obstack. This is slow, and should be used only for debugging. Use TREE_PERMANENT for other purposes. */intobject_permanent_p (obj) tree obj;{ return _obstack_allocated_p (&permanent_obstack, obj);}/* Start a level of momentary allocation. In C, each compound statement has its own level and that level is freed at the end of each statement. All expression nodes are allocated in the momentary allocation level. */voidpush_momentary (){ struct momentary_level *tem = (struct momentary_level *) obstack_alloc (&momentary_obstack, sizeof (struct momentary_level)); tem->prev = momentary_stack; tem->base = (char *) obstack_base (&momentary_obstack); tem->obstack = expression_obstack; momentary_stack = tem; expression_obstack = &momentary_obstack;}/* Set things up so the next clear_momentary will only clear memory past our present position in momentary_obstack. */voidpreserve_momentary (){ momentary_stack->base = (char *) obstack_base (&momentary_obstack);}/* Free all the storage in the current momentary-allocation level. In C, this happens at the end of each statement. */voidclear_momentary (){ obstack_free (&momentary_obstack, momentary_stack->base);}/* Discard a level of momentary allocation. In C, this happens at the end of each compound statement. Restore the status of expression node allocation that was in effect before this level was created. */voidpop_momentary (){ struct momentary_level *tem = momentary_stack; momentary_stack = tem->prev; expression_obstack = tem->obstack; /* We can't free TEM from the momentary_obstack, because there might be objects above it which have been saved. We can free back to the stack of the level we are popping off though. */ obstack_free (&momentary_obstack, tem->base);}/* Pop back to the previous level of momentary allocation, but don't free any momentary data just yet. */voidpop_momentary_nofree (){ struct momentary_level *tem = momentary_stack; momentary_stack = tem->prev; expression_obstack = tem->obstack;}/* Call when starting to parse a declaration: make expressions in the declaration last the length of the function. Returns an argument that should be passed to resume_momentary later. */intsuspend_momentary (){ register int tem = expression_obstack == &momentary_obstack; expression_obstack = saveable_obstack; return tem;}/* Call when finished parsing a declaration: restore the treatment of node-allocation that was in effect before the suspension. YES should be the value previously returned by suspend_momentary. */voidresume_momentary (yes) int yes;{ if (yes) expression_obstack = &momentary_obstack;}/* Init the tables indexed by tree code. Note that languages can add to these tables to define their own codes. */voidinit_tree_codes (){ tree_code_type = (char **) xmalloc (sizeof (standard_tree_code_type)); tree_code_length = (int *) xmalloc (sizeof (standard_tree_code_length)); tree_code_name = (char **) xmalloc (sizeof (standard_tree_code_name)); bcopy ((char *) standard_tree_code_type, (char *) tree_code_type, sizeof (standard_tree_code_type)); bcopy ((char *) standard_tree_code_length, (char *) tree_code_length, sizeof (standard_tree_code_length)); bcopy ((char *) standard_tree_code_name, (char *) tree_code_name, sizeof (standard_tree_code_name));}/* Return a newly allocated node of code CODE. Initialize the node's unique id and its TREE_PERMANENT flag. For decl and type nodes, some other fields are initialized. The rest of the node is initialized to zero. Achoo! I got a code in the node. */treemake_node (code) enum tree_code code;{ register tree t; register int type = TREE_CODE_CLASS (code); register int length; register struct obstack *obstack = current_obstack; register int i; register tree_node_kind kind; switch (type) { case 'd': /* A decl node */#ifdef GATHER_STATISTICS kind = d_kind;#endif length = sizeof (struct tree_decl); /* All decls in an inline function need to be saved. */ if (obstack != &permanent_obstack) obstack = saveable_obstack; /* PARM_DECLs go on the context of the parent. If this is a nested function, then we must allocate the PARM_DECL on the parent's obstack, so that they will live to the end of the parent's closing brace. This is necessary in case we try to inline the function into its parent. PARM_DECLs of top-level functions do not have this problem. However, we allocate them where we put the FUNCTION_DECL for languages such as Ada that need to consult some flags in the PARM_DECLs of the function when calling it. See comment in restore_tree_status for why we can't put this in function_obstack. */ if (code == PARM_DECL && obstack != &permanent_obstack) { tree context = 0; if (current_function_decl) context = decl_function_context (current_function_decl); if (context) obstack = find_function_data (context)->function_maybepermanent_obstack; } break; case 't': /* a type node */#ifdef GATHER_STATISTICS kind = t_kind;#endif length = sizeof (struct tree_type); /* All data types are put where we can preserve them if nec. */ if (obstack != &permanent_obstack) obstack = all_types_permanent ? &permanent_obstack : saveable_obstack; break; case 'b': /* a lexical block */#ifdef GATHER_STATISTICS kind = b_kind;#endif length = sizeof (struct tree_block);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -