📄 decl.c
字号:
IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0; /* Put the labels into the "variables" of the top-level block, so debugger can see them. */ TREE_CHAIN (label) = BLOCK_VARS (block); BLOCK_VARS (block) = label; }#endif } /* Pop the current level, and free the structure for reuse. */ { register struct binding_level *level = current_binding_level; current_binding_level = current_binding_level->level_chain; level->level_chain = free_binding_level; free_binding_level = level; } /* Dispose of the block that we just made inside some higher level. */ if (functionbody) DECL_INITIAL (current_function_decl) = block; else if (block) { if (!block_previously_created) current_binding_level->blocks = chainon (current_binding_level->blocks, block); } /* If we did not make a block for the level just exited, any blocks made for inner levels (since they cannot be recorded as subblocks in that level) must be carried forward so they will later become subblocks of something else. */ else if (subblocks) current_binding_level->blocks = chainon (current_binding_level->blocks, subblocks); /* Set the TYPE_CONTEXTs for all of the tagged types belonging to this binding contour so that they point to the appropriate construct, i.e. either to the current FUNCTION_DECL node, or else to the BLOCK node we just constructed. Note that for tagged types whose scope is just the formal parameter list for some function type specification, we can't properly set their TYPE_CONTEXTs here, because we don't have a pointer to the appropriate FUNCTION_TYPE node readily available to us. For those cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set in `grokdeclarator' as soon as we have created the FUNCTION_TYPE node which will represent the "scope" for these "parameter list local" tagged types. */ if (block) TREE_USED (block) = 1; return block;}voidmaybe_pushlevels (pc) int pc;{ while (pending_local_decls != NULL_TREE && DECL_LOCAL_START_PC (pending_local_decls) <= pc) { tree *ptr = &pending_local_decls; tree decl = *ptr; int end_pc = DECL_LOCAL_END_PC (decl); while (*ptr != NULL_TREE && DECL_LOCAL_START_PC (*ptr) <= pc && DECL_LOCAL_END_PC (*ptr) == end_pc) ptr = &TREE_CHAIN (*ptr); pending_local_decls = *ptr; *ptr = NULL_TREE; /* Force non-nested range to be nested in current range. */ if (end_pc > current_binding_level->end_pc) end_pc = current_binding_level->end_pc; pushlevel (1); expand_start_bindings (0); current_binding_level->end_pc = end_pc; current_binding_level->names = decl; for ( ; decl != NULL_TREE; decl = TREE_CHAIN (decl)) { push_jvm_slot (DECL_LOCAL_SLOT_NUMBER (decl), decl); } }}voidmaybe_poplevels (pc) int pc;{ while (current_binding_level->end_pc <= pc) { expand_end_bindings (getdecls (), 1, 0); poplevel (1, 0, 0); }}/* Insert BLOCK at the end of the list of subblocks of the current binding level. This is used when a BIND_EXPR is expanded, to handle the BLOCK node inside the BIND_EXPR. */voidinsert_block (block) tree block;{ TREE_USED (block) = 1; abort (); current_binding_level->blocks = chainon (current_binding_level->blocks, block);}/* Set the BLOCK node for the innermost scope (the one we are currently in). */voidset_block (block) register tree block;{ current_binding_level->this_block = block;}/* integrate_decl_tree calls this function. */voidcopy_lang_decl (node) tree node;{ int lang_decl_size = TREE_CODE (node) == VAR_DECL ? sizeof (struct lang_decl_var) : sizeof (struct lang_decl); struct lang_decl *x = (struct lang_decl *) oballoc (lang_decl_size); bcopy ((PTR) DECL_LANG_SPECIFIC (node), (PTR) x, lang_decl_size); DECL_LANG_SPECIFIC (node) = x;}/* If DECL has a cleanup, build and return that cleanup here. This is a callback called by expand_expr. */treemaybe_build_cleanup (decl) tree decl ATTRIBUTE_UNUSED;{ /* There are no cleanups in Java (I think). */ return NULL_TREE;}voidgive_name_to_locals (jcf) JCF *jcf;{ int i, n = DECL_LOCALVARIABLES_OFFSET (current_function_decl); tree parm; pending_local_decls = NULL_TREE; if (n == 0) return; JCF_SEEK (jcf, n); n = JCF_readu2 (jcf); for (i = 0; i < n; i++) { int start_pc = JCF_readu2 (jcf); int length = JCF_readu2 (jcf); int name_index = JCF_readu2 (jcf); int signature_index = JCF_readu2 (jcf); int slot = JCF_readu2 (jcf); tree name = get_name_constant (jcf, name_index); tree type = parse_signature (jcf, signature_index); if (slot < DECL_ARG_SLOT_COUNT (current_function_decl) && start_pc == 0 && length == DECL_CODE_LENGTH (current_function_decl)) { tree decl = TREE_VEC_ELT (decl_map, slot); DECL_NAME (decl) = name; DECL_ASSEMBLER_NAME (decl) = name; if (TREE_CODE (decl) != PARM_DECL || TREE_TYPE (decl) != type) warning ("bad type in parameter debug info"); } else { tree *ptr; int end_pc = start_pc + length; tree decl = build_decl (VAR_DECL, name, type); if (end_pc > DECL_CODE_LENGTH (current_function_decl)) { warning_with_decl (decl, "bad PC range for debug info for local `%s'"); end_pc = DECL_CODE_LENGTH (current_function_decl); } DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) permalloc (sizeof (struct lang_decl_var)); DECL_LOCAL_SLOT_NUMBER (decl) = slot; DECL_LOCAL_START_PC (decl) = start_pc; DECL_LOCAL_END_PC (decl) = end_pc; /* Now insert the new decl in the proper place in pending_local_decls. We are essentially doing an insertion sort, which works fine, since the list input will normally already be sorted. */ ptr = &pending_local_decls; while (*ptr != NULL_TREE && (DECL_LOCAL_START_PC (*ptr) > start_pc || (DECL_LOCAL_START_PC (*ptr) == start_pc && DECL_LOCAL_END_PC (*ptr) < end_pc))) ptr = &TREE_CHAIN (*ptr); TREE_CHAIN (decl) = *ptr; *ptr = decl; } } pending_local_decls = nreverse (pending_local_decls); /* Fill in default names for the parameters. */ for (parm = DECL_ARGUMENTS (current_function_decl), i = 0; parm != NULL_TREE; parm = TREE_CHAIN (parm), i++) { if (DECL_NAME (parm) == NULL_TREE) { int arg_i = METHOD_STATIC (current_function_decl) ? i+1 : i; if (arg_i == 0) DECL_NAME (parm) = get_identifier ("this"); else { char buffer[12]; sprintf (buffer, "ARG_%d", arg_i); DECL_NAME (parm) = get_identifier (buffer); } DECL_ASSEMBLER_NAME (parm) = DECL_NAME (parm); } }}treebuild_result_decl (fndecl) tree fndecl;{ tree restype = TREE_TYPE (TREE_TYPE (fndecl)); /* To be compatible with C_PROMOTING_INTEGER_TYPE_P in cc1/cc1plus. */ if (INTEGRAL_TYPE_P (restype) && TYPE_PRECISION (restype) < TYPE_PRECISION (integer_type_node)) restype = integer_type_node; return (DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, restype));}voidcomplete_start_java_method (fndecl) tree fndecl;{ if (! flag_emit_class_files) { /* Initialize the RTL code for the function. */ init_function_start (fndecl, input_filename, lineno); /* Set up parameters and prepare for return, for the function. */ expand_function_start (fndecl, 0); } /* Allocate further tree nodes temporarily during compilation of this function only. */ temporary_allocation ();#if 0 /* If this fcn was already referenced via a block-scope `extern' decl (or an implicit decl), propagate certain information about the usage. */ if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl))) TREE_ADDRESSABLE (current_function_decl) = 1;#endif if (METHOD_STATIC (fndecl) && ! METHOD_PRIVATE (fndecl) && ! flag_emit_class_files && ! CLASS_INTERFACE (TYPE_NAME (current_class))) { tree clas = DECL_CONTEXT (fndecl); tree init = build (CALL_EXPR, void_type_node, build_address_of (soft_initclass_node), build_tree_list (NULL_TREE, build_class_ref (clas)), NULL_TREE); TREE_SIDE_EFFECTS (init) = 1; expand_expr_stmt (init); } /* Push local variables. Function compiled from source code are using a different local variables management, and for them, pushlevel shouldn't be called from here. */ if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (fndecl))) { pushlevel (2); if (! flag_emit_class_files) expand_start_bindings (1); } if (METHOD_SYNCHRONIZED (fndecl) && ! flag_emit_class_files) { /* Warp function body with a monitorenter plus monitorexit cleanup. */ tree enter, exit, lock; if (METHOD_STATIC (fndecl)) lock = build_class_ref (DECL_CONTEXT (fndecl)); else lock = DECL_ARGUMENTS (fndecl); BUILD_MONITOR_ENTER (enter, lock); BUILD_MONITOR_EXIT (exit, lock); if (!CLASS_FROM_SOURCE_P (DECL_CONTEXT (fndecl))) { expand_expr_stmt (enter); expand_decl_cleanup (NULL_TREE, exit); } else { tree function_body = DECL_FUNCTION_BODY (fndecl); tree body = BLOCK_EXPR_BODY (function_body); lock = build (WITH_CLEANUP_EXPR, void_type_node, enter, NULL_TREE, exit); TREE_SIDE_EFFECTS (lock) = 1; lock = build (COMPOUND_EXPR, TREE_TYPE (body), lock, body); TREE_SIDE_EFFECTS (lock) = 1; lock = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (body), lock); TREE_SIDE_EFFECTS (lock) = 1; BLOCK_EXPR_BODY (function_body) = lock; } }}voidstart_java_method (fndecl) tree fndecl;{ tree tem, *ptr; int i; current_function_decl = fndecl; announce_function (fndecl); i = DECL_MAX_LOCALS(fndecl) + DECL_MAX_STACK(fndecl); decl_map = make_tree_vec (i); type_map = (tree *) oballoc (i * sizeof (tree)); pushlevel (1); /* Push parameters. */ ptr = &DECL_ARGUMENTS (fndecl); for (tem = TYPE_ARG_TYPES (TREE_TYPE (fndecl)), i = 0; tem != end_params_node; tem = TREE_CHAIN (tem), i++) { tree parm_name = NULL_TREE, parm_decl; tree parm_type = TREE_VALUE (tem); if (i >= DECL_MAX_LOCALS(fndecl)) fatal ("function has more parameters than local slots"); parm_decl = build_decl (PARM_DECL, parm_name, parm_type); DECL_CONTEXT (parm_decl) = fndecl;#ifdef PROMOTE_PROTOTYPES if (TYPE_PRECISION (parm_type) < TYPE_PRECISION (integer_type_node) && INTEGRAL_TYPE_P (parm_type)) parm_type = integer_type_node;#endif DECL_ARG_TYPE (parm_decl) = parm_type; *ptr = parm_decl; ptr = &TREE_CHAIN (parm_decl); /* Add parm_decl to the decl_map. */ push_jvm_slot (i, parm_decl); type_map[i] = TREE_TYPE (parm_decl); if (TYPE_IS_WIDE (TREE_TYPE (parm_decl))) { i++; type_map[i] = void_type_node; } } *ptr = NULL_TREE; DECL_ARG_SLOT_COUNT (current_function_decl) = i; while (i < DECL_MAX_LOCALS(fndecl)) type_map[i++] = NULL_TREE; build_result_decl (fndecl); complete_start_java_method (fndecl);}voidend_java_method (){ tree fndecl = current_function_decl; int flag_asynchronous_exceptions = asynchronous_exceptions; expand_end_bindings (getdecls (), 1, 0); /* pop out of function */ poplevel (1, 1, 0); /* pop out of its parameters */ poplevel (1, 0, 1); BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; emit_handlers (); /* Generate rtl for function exit. */ expand_function_end (input_filename, lineno, 0); /* FIXME: If the current method contains any exception handlers, force asynchronous_exceptions: this is necessary because signal handlers in libjava may throw exceptions. This is far from being a perfect solution, but it's better than doing nothing at all.*/ if (catch_clauses) asynchronous_exceptions = 1; /* Run the optimizers and output assembler code for this function. */ rest_of_compilation (fndecl); current_function_decl = NULL_TREE; permanent_allocation (1); asynchronous_exceptions = flag_asynchronous_exceptions;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -