📄 varasm.c
字号:
/* Likewise for global constructors. */voidassemble_constructor (name) char *name;{#ifdef ASM_OUTPUT_CONSTRUCTOR ASM_OUTPUT_CONSTRUCTOR (asm_out_file, name);#else if (flag_gnu_linker) { /* Now tell GNU LD that this is part of the static constructor set. */ /* This code works for any machine provided you use GNU as/ld. */ fprintf (asm_out_file, "%s \"___CTOR_LIST__\",22,0,0,", ASM_STABS_OP); assemble_name (asm_out_file, name); fputc ('\n', asm_out_file); }#endif}/* Likewise for entries we want to record for garbage collection. Garbage collection is still under development. */voidassemble_gc_entry (name) char *name;{#ifdef ASM_OUTPUT_GC_ENTRY ASM_OUTPUT_GC_ENTRY (asm_out_file, name);#else if (flag_gnu_linker) { /* Now tell GNU LD that this is part of the static constructor set. */ fprintf (asm_out_file, "%s \"___PTR_LIST__\",22,0,0,", ASM_STABS_OP); assemble_name (asm_out_file, name); fputc ('\n', asm_out_file); }#endif}/* Output assembler code for the constant pool of a function and associated with defining the name of the function. DECL describes the function. NAME is the function's name. For the constant pool, we use the current constant pool data. */voidassemble_start_function (decl, fnname) tree decl; char *fnname;{ int align; /* The following code does not need preprocessing in the assembler. */ app_disable (); output_constant_pool (fnname, decl); text_section (); /* Tell assembler to move to target machine's alignment for functions. */ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); if (align > 0) ASM_OUTPUT_ALIGN (asm_out_file, align);#ifdef ASM_OUTPUT_FUNCTION_PREFIX ASM_OUTPUT_FUNCTION_PREFIX (asm_out_file, fnname);#endif#ifdef SDB_DEBUGGING_INFO /* Output SDB definition of the function. */ if (write_symbols == SDB_DEBUG) sdbout_mark_begin_function ();#endif#ifdef DBX_DEBUGGING_INFO /* Output DBX definition of the function. */ if (write_symbols == DBX_DEBUG) dbxout_begin_function (decl);#endif /* Make function name accessible from other files, if appropriate. */ if (TREE_PUBLIC (decl)) { if (!first_global_object_name) STRIP_NAME_ENCODING (first_global_object_name, fnname); ASM_GLOBALIZE_LABEL (asm_out_file, fnname); } /* Do any machine/system dependent processing of the function name */#ifdef ASM_DECLARE_FUNCTION_NAME ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);#else /* Standard thing is just output label for the function. */ ASM_OUTPUT_LABEL (asm_out_file, fnname);#endif /* ASM_DECLARE_FUNCTION_NAME */}/* Output assembler code associated with defining the size of the function. DECL describes the function. NAME is the function's name. */voidassemble_end_function (decl, fnname) tree decl; char *fnname;{#ifdef ASM_DECLARE_FUNCTION_SIZE ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl);#endif}/* Assemble code to leave SIZE bytes of zeros. */voidassemble_zeros (size) int size;{#ifdef ASM_NO_SKIP_IN_TEXT /* The `space' pseudo in the text section outputs nop insns rather than 0s, so we must output 0s explicitly in the text section. */ if (ASM_NO_SKIP_IN_TEXT && in_text_section ()) { int i; for (i = 0; i < size - 20; i += 20) {#ifdef ASM_BYTE_OP fprintf (asm_out_file, "%s 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n", ASM_BYTE_OP);#else fprintf (asm_out_file, "\tbyte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n");#endif } if (i < size) {#ifdef ASM_BYTE_OP fprintf (asm_out_file, "%s 0", ASM_BYTE_OP);#else fprintf (asm_out_file, "\tbyte 0");#endif i++; for (; i < size; i++) fprintf (asm_out_file, ",0"); fprintf (asm_out_file, "\n"); } } else#endif ASM_OUTPUT_SKIP (asm_out_file, size);}/* Assemble a string constant with the specified C string as contents. */voidassemble_string (p, size) unsigned char *p; int size;{ register int i; int pos = 0; int maximum = 2000; /* If the string is very long, split it up. */ while (pos < size) { int thissize = size - pos; if (thissize > maximum) thissize = maximum; ASM_OUTPUT_ASCII (asm_out_file, p, thissize); pos += thissize; p += thissize; }}/* 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. */voidassemble_variable (decl, top_level, at_end) tree decl; int top_level; int at_end;{ register char *name; int align; tree size_tree; int reloc = 0; 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 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 for external references, since assembler considers all undefined symbols external. */ 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 (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))); 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;#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 storage size is erroneously variable, just continue. Error message was already made. */ if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) goto finish; app_disable (); /* 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. */ if (! flag_no_common && (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));#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#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#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) STRIP_NAME_ENCODING(first_global_object_name, name); 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)) reloc = output_addressed_constants (DECL_INITIAL (decl)); /* Switch to the proper section for this data. */#ifdef SELECT_SECTION SELECT_SECTION (decl, reloc);#else if (TREE_READONLY (decl) && ! TREE_THIS_VOLATILE (decl) && ! (flag_pic && reloc)) readonly_data_section (); else data_section ();#endif /* Compute and output the alignment of this data. */ align = DECL_ALIGN (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) 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 ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);#else /* Standard thing is just output label for the object. */ ASM_OUTPUT_LABEL (asm_out_file, name);#endif /* ASM_DECLARE_OBJECT_NAME */#if 0 for (d = equivalents; d; d = TREE_CHAIN (d)) { tree e = TREE_VALUE (d); ASM_OUTPUT_LABEL (asm_out_file, XSTR (XEXP (DECL_RTL (e), 0), 0)); }#endif if (DECL_INITIAL (decl)) /* Output the actual data. */ output_constant (DECL_INITIAL (decl), int_size_in_bytes (TREE_TYPE (decl))); else /* Leave space for it. */ assemble_zeros (int_size_in_bytes (TREE_TYPE (decl))); 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -