📄 varasm.c
字号:
if (output_bytecode) bc_output_ascii (asm_out_file, p, thissize); else { ASM_OUTPUT_ASCII (asm_out_file, p, thissize); } pos += thissize; p += thissize; }}static voidbc_output_ascii (file, p, size) FILE *file; char *p; int size;{ BC_OUTPUT_ASCII (file, p, size);}/* Assemble everything that is needed for a variable or function declaration. Not used for automatic variables, and not used for function definitions. Should not be called for variables of incomplete structure type. TOP_LEVEL is nonzero if this variable has file scope. AT_END is nonzero if this is the special handling, at end of compilation, to define things that have had only tentative definitions. DONT_OUTPUT_DATA if nonzero means don't actually output the initial value (that will be done by the caller). */voidassemble_variable (decl, top_level, at_end, dont_output_data) tree decl; int top_level; int at_end; int dont_output_data;{ register char *name; int align; tree size_tree; int reloc = 0; enum in_section saved_in_section; last_assemble_variable_decl = 0; if (output_bytecode) return; if (GET_CODE (DECL_RTL (decl)) == REG) { /* Do output symbol info for global register variables, but do nothing else for them. */ if (TREE_ASM_WRITTEN (decl)) return; TREE_ASM_WRITTEN (decl) = 1; if (!output_bytecode) {#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO) /* File-scope global variables are output here. */ if ((write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG) && top_level) dbxout_symbol (decl, 0);#endif#ifdef SDB_DEBUGGING_INFO if (write_symbols == SDB_DEBUG && top_level /* Leave initialized global vars for end of compilation; see comment in compile_file. */ && (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0)) sdbout_symbol (decl, 0);#endif } /* Don't output any DWARF debugging information for variables here. In the case of local variables, the information for them is output when we do our recursive traversal of the tree representation for the entire containing function. In the case of file-scope variables, we output information for all of them at the very end of compilation while we are doing our final traversal of the chain of file-scope declarations. */ return; } /* Normally no need to say anything here for external references, since assemble_external is called by the language-specific code when a declaration is first seen. */ if (DECL_EXTERNAL (decl)) return; /* Output no assembler code for a function declaration. Only definitions of functions output anything. */ if (TREE_CODE (decl) == FUNCTION_DECL) return; /* If type was incomplete when the variable was declared, see if it is complete now. */ if (DECL_SIZE (decl) == 0) layout_decl (decl, 0); /* Still incomplete => don't allocate it; treat the tentative defn (which is what it must have been) as an `extern' reference. */ if (!dont_output_data && DECL_SIZE (decl) == 0) { error_with_file_and_line (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl), "storage size of `%s' isn't known", IDENTIFIER_POINTER (DECL_NAME (decl))); TREE_ASM_WRITTEN (decl) = 1; return; } /* The first declaration of a variable that comes through this function decides whether it is global (in C, has external linkage) or local (in C, has internal linkage). So do nothing more if this function has already run. */ if (TREE_ASM_WRITTEN (decl)) return; TREE_ASM_WRITTEN (decl) = 1; app_disable (); if (! dont_output_data) { if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) goto finish; /* This is better than explicit arithmetic, since it avoids overflow. */ size_tree = size_binop (CEIL_DIV_EXPR, DECL_SIZE (decl), size_int (BITS_PER_UNIT)); if (TREE_INT_CST_HIGH (size_tree) != 0) { error_with_decl (decl, "size of variable `%s' is too large"); goto finish; } } name = XSTR (XEXP (DECL_RTL (decl), 0), 0); /* Handle uninitialized definitions. */ /* ANSI specifies that a tentative definition which is not merged with a non-tentative definition behaves exactly like a definition with an initializer equal to zero. (Section 3.7.2) -fno-common gives strict ANSI behavior. Usually you don't want it. This matters only for variables with external linkage. */ if ((! flag_no_common || ! TREE_PUBLIC (decl)) && DECL_COMMON (decl) && ! dont_output_data && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)) { int size = TREE_INT_CST_LOW (size_tree); int rounded = size; if (TREE_INT_CST_HIGH (size_tree) != 0) error_with_decl (decl, "size of variable `%s' is too large"); /* Don't allocate zero bytes of common, since that means "undefined external" in the linker. */ if (size == 0) rounded = 1; /* Round size up to multiple of BIGGEST_ALIGNMENT bits so that each uninitialized object starts on such a boundary. */ rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));#ifdef DBX_DEBUGGING_INFO /* File-scope global variables are output here. */ if (write_symbols == DBX_DEBUG && top_level) dbxout_symbol (decl, 0);#endif#ifdef SDB_DEBUGGING_INFO if (write_symbols == SDB_DEBUG && top_level /* Leave initialized global vars for end of compilation; see comment in compile_file. */ && (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0)) sdbout_symbol (decl, 0);#endif /* Don't output any DWARF debugging information for variables here. In the case of local variables, the information for them is output when we do our recursive traversal of the tree representation for the entire containing function. In the case of file-scope variables, we output information for all of them at the very end of compilation while we are doing our final traversal of the chain of file-scope declarations. */#if 0 if (flag_shared_data) data_section ();#endif if (TREE_PUBLIC (decl)) {#ifdef ASM_OUTPUT_SHARED_COMMON if (flag_shared_data) ASM_OUTPUT_SHARED_COMMON (asm_out_file, name, size, rounded); else#endif if (output_bytecode) { BC_OUTPUT_COMMON (asm_out_file, name, size, rounded); } else {#ifdef ASM_OUTPUT_ALIGNED_COMMON ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size, DECL_ALIGN (decl));#else ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded);#endif } } else {#ifdef ASM_OUTPUT_SHARED_LOCAL if (flag_shared_data) ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded); else#endif if (output_bytecode) { BC_OUTPUT_LOCAL (asm_out_file, name, size, rounded); } else {#ifdef ASM_OUTPUT_ALIGNED_LOCAL ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, DECL_ALIGN (decl));#else ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);#endif } } goto finish; } /* Handle initialized definitions. */ /* First make the assembler name(s) global if appropriate. */ if (TREE_PUBLIC (decl) && DECL_NAME (decl)) { if (!first_global_object_name) { char *p; STRIP_NAME_ENCODING (p, name); first_global_object_name = permalloc (strlen (p) + 1); strcpy (first_global_object_name, p); }#ifdef ASM_WEAKEN_LABEL if (DECL_WEAK (decl)) ASM_WEAKEN_LABEL (asm_out_file, name); else#endif ASM_GLOBALIZE_LABEL (asm_out_file, name); }#if 0 for (d = equivalents; d; d = TREE_CHAIN (d)) { tree e = TREE_VALUE (d); if (TREE_PUBLIC (e) && DECL_NAME (e)) ASM_GLOBALIZE_LABEL (asm_out_file, XSTR (XEXP (DECL_RTL (e), 0), 0)); }#endif /* Output any data that we will need to use the address of. */ if (DECL_INITIAL (decl) == error_mark_node) reloc = contains_pointers_p (TREE_TYPE (decl)); else if (DECL_INITIAL (decl)) reloc = output_addressed_constants (DECL_INITIAL (decl)); /* Switch to the proper section for this data. */ if (IN_NAMED_SECTION (decl)) named_section (decl, NULL); else { /* C++ can have const variables that get initialized from constructors, and thus can not be in a readonly section. We prevent this by verifying that the initial value is constant for objects put in a readonly section. error_mark_node is used by the C front end to indicate that the initializer has not been seen yet. In this case, we assume that the initializer must be constant. */#ifdef SELECT_SECTION SELECT_SECTION (decl, reloc);#else if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && DECL_INITIAL (decl) && (DECL_INITIAL (decl) == error_mark_node || TREE_CONSTANT (DECL_INITIAL (decl))) && ! (flag_pic && reloc)) readonly_data_section (); else data_section ();#endif } /* dbxout.c needs to know this. */ if (in_text_section ()) DECL_IN_TEXT_SECTION (decl) = 1; /* Record current section so we can restore it if dbxout.c clobbers it. */ saved_in_section = in_section; /* Output the dbx info now that we have chosen the section. */#ifdef DBX_DEBUGGING_INFO /* File-scope global variables are output here. */ if (write_symbols == DBX_DEBUG && top_level) dbxout_symbol (decl, 0);#endif#ifdef SDB_DEBUGGING_INFO if (write_symbols == SDB_DEBUG && top_level /* Leave initialized global vars for end of compilation; see comment in compile_file. */ && (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0)) sdbout_symbol (decl, 0);#endif /* Don't output any DWARF debugging information for variables here. In the case of local variables, the information for them is output when we do our recursive traversal of the tree representation for the entire containing function. In the case of file-scope variables, we output information for all of them at the very end of compilation while we are doing our final traversal of the chain of file-scope declarations. */ /* If the debugging output changed sections, reselect the section that's supposed to be selected. */ if (in_section != saved_in_section) { /* Switch to the proper section for this data. */#ifdef SELECT_SECTION SELECT_SECTION (decl, reloc);#else if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && DECL_INITIAL (decl) && (DECL_INITIAL (decl) == error_mark_node || TREE_CONSTANT (DECL_INITIAL (decl))) && ! (flag_pic && reloc)) readonly_data_section (); else data_section ();#endif } /* Compute and output the alignment of this data. */ align = DECL_ALIGN (decl); /* In the case for initialing an array whose length isn't specified, where we have not yet been able to do the layout, figure out the proper alignment now. */ if (dont_output_data && DECL_SIZE (decl) == 0 && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) align = MAX (align, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl)))); /* Some object file formats have a maximum alignment which they support. In particular, a.out format supports a maximum alignment of 4. */#ifndef MAX_OFILE_ALIGNMENT#define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT#endif if (align > MAX_OFILE_ALIGNMENT) { warning_with_decl (decl, "alignment of `%s' is greater than maximum object file alignment"); align = MAX_OFILE_ALIGNMENT; }#ifdef DATA_ALIGNMENT /* On some machines, it is good to increase alignment sometimes. */ align = DATA_ALIGNMENT (TREE_TYPE (decl), align);#endif#ifdef CONSTANT_ALIGNMENT if (DECL_INITIAL (decl)) align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);#endif /* Reset the alignment in case we have made it tighter, so we can benefit from it in get_pointer_alignment. */ DECL_ALIGN (decl) = align; if (align > BITS_PER_UNIT) { if (output_bytecode) BC_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); else ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); } /* Do any machine/system dependent processing of the object. */#ifdef ASM_DECLARE_OBJECT_NAME last_assemble_variable_decl = decl; ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);#else /* Standard thing is just output label for the object. */ if (output_bytecode) BC_OUTPUT_LABEL (asm_out_file, name); else ASM_OUTPUT_LABEL (asm_out_file, name);#endif /* ASM_DECLARE_OBJECT_NAME */ if (!dont_output_data) { if (DECL_INITIAL (decl)) /* Output the actual data. */ output_constant (DECL_INITIAL (decl), TREE_INT_CST_LOW (size_tree)); else /* Leave space for it. */ assemble_zeros (TREE_INT_CST_LOW (size_tree)); } finish:#ifdef XCOFF_DEBUGGING_INFO /* Unfortunately, the IBM assembler cannot handle stabx before the actual declaration. When something like ".stabx "aa:S-2",aa,133,0" is emitted and `aa' hasn't been output yet, the assembler generates a stab entry with a value of zero, in addition to creating an unnecessary external entry for `aa'. Hence, we must postpone dbxout_symbol to here at the end. */ /* File-scope global variables are output here. */ if (write_symbols == XCOFF_DEBUG && top_level) { saved_in_section = in_section; dbxout_symbol (decl, 0); if (in_section != saved_in_section) { /* Switch to the proper section for this data. */#ifdef SELECT_SECTION SELECT_SECTION (decl, reloc);#else if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && DECL_INITIAL (decl) && (DECL_INITIAL (decl) == error_mark_node || TREE_CONSTANT (DECL_INITIAL (decl))) && ! (flag_pic && reloc)) readonly_data_section (); else data_section ();#endif } }#else /* There must be a statement after a label. */ ;#endif}/* Return 1 if type TYPE contains any pointers. */static intcontains_pointers_p (type) tree type;{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -