📄 varasm.c
字号:
switch (TREE_CODE (type)) { case POINTER_TYPE: case REFERENCE_TYPE: /* I'm not sure whether OFFSET_TYPE needs this treatment, so I'll play safe and return 1. */ case OFFSET_TYPE: return 1; case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: { tree fields; /* For a type that has fields, see if the fields have pointers. */ for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) if (TREE_CODE (fields) == FIELD_DECL && contains_pointers_p (TREE_TYPE (fields))) return 1; return 0; } case ARRAY_TYPE: /* An array type contains pointers if its element type does. */ return contains_pointers_p (TREE_TYPE (type)); default: return 0; }}/* Output text storage for constructor CONSTR. */voidbc_output_constructor (constr, size) tree constr; int size;{ int i; /* Must always be a literal; non-literal constructors are handled differently. */ if (!TREE_CONSTANT (constr)) abort (); /* Always const */ text_section (); /* Align */ for (i = 0; TYPE_ALIGN (constr) >= BITS_PER_UNIT << (i + 1); i++) ; if (i > 0) BC_OUTPUT_ALIGN (asm_out_file, i); /* Output data */ output_constant (constr, size);}/* Create storage for constructor CONSTR. */voidbc_output_data_constructor (constr) tree constr;{ int i; /* Put in data section */ data_section (); /* Align */ for (i = 0; TYPE_ALIGN (constr) >= BITS_PER_UNIT << (i + 1); i++); if (i > 0) BC_OUTPUT_ALIGN (asm_out_file, i); /* The constructor is filled in at runtime. */ BC_OUTPUT_SKIP (asm_out_file, int_size_in_bytes (TREE_TYPE (constr)));}/* Output something to declare an external symbol to the assembler. (Most assemblers don't need this, so we normally output nothing.) Do nothing if DECL is not external. */voidassemble_external (decl) tree decl;{ if (output_bytecode) return;#ifdef ASM_OUTPUT_EXTERNAL if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd' && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)) { rtx rtl = DECL_RTL (decl); if (GET_CODE (rtl) == MEM && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF && ! SYMBOL_REF_USED (XEXP (rtl, 0))) { /* Some systems do require some output. */ SYMBOL_REF_USED (XEXP (rtl, 0)) = 1; ASM_OUTPUT_EXTERNAL (asm_out_file, decl, XSTR (XEXP (rtl, 0), 0)); } }#endif}/* Similar, for calling a library function FUN. */voidassemble_external_libcall (fun) rtx fun;{#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL if (!output_bytecode) { /* Declare library function name external when first used, if nec. */ if (! SYMBOL_REF_USED (fun)) { SYMBOL_REF_USED (fun) = 1; ASM_OUTPUT_EXTERNAL_LIBCALL (asm_out_file, fun); } }#endif}/* Declare the label NAME global. */voidassemble_global (name) char *name;{ ASM_GLOBALIZE_LABEL (asm_out_file, name);}/* Assemble a label named NAME. */voidassemble_label (name) char *name;{ if (output_bytecode) BC_OUTPUT_LABEL (asm_out_file, name); else ASM_OUTPUT_LABEL (asm_out_file, name);}/* Output to FILE a reference to the assembler name of a C-level name NAME. If NAME starts with a *, the rest of NAME is output verbatim. Otherwise NAME is transformed in an implementation-defined way (usually by the addition of an underscore). Many macros in the tm file are defined to call this function. */voidassemble_name (file, name) FILE *file; char *name;{ char *real_name; int save_warn_id_clash = warn_id_clash; STRIP_NAME_ENCODING (real_name, name); /* Don't warn about an identifier name length clash on this name, since it can be a user symbol suffixed by a number. */ warn_id_clash = 0; TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1; warn_id_clash = save_warn_id_clash; if (name[0] == '*') { if (output_bytecode) bc_emit_labelref (name, 0); else fputs (&name[1], file); } else { if (output_bytecode) BC_OUTPUT_LABELREF (file, name); else ASM_OUTPUT_LABELREF (file, name); }}/* Allocate SIZE bytes writable static space with a gensym name and return an RTX to refer to its address. */rtxassemble_static_space (size) int size;{ char name[12]; char *namestring; rtx x; /* Round size up to multiple of BIGGEST_ALIGNMENT bits so that each uninitialized object starts on such a boundary. */ int rounded = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1) / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));#if 0 if (flag_shared_data) data_section ();#endif ASM_GENERATE_INTERNAL_LABEL (name, "LF", const_labelno); ++const_labelno; namestring = (char *) obstack_alloc (saveable_obstack, strlen (name) + 2); strcpy (namestring, name); if (output_bytecode) x = bc_gen_rtx (namestring, 0, (struct bc_label *) 0); else x = gen_rtx (SYMBOL_REF, Pmode, namestring); 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, BIGGEST_ALIGNMENT);#else ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);#endif } return x;}/* Assemble the static constant template for function entry trampolines. This is done at most once per compilation. Returns an RTX for the address of the template. */rtxassemble_trampoline_template (){ char label[256]; char *name; int align; /* Shouldn't get here */ if (output_bytecode) abort (); /* By default, put trampoline templates in read-only data section. */#ifdef TRAMPOLINE_SECTION TRAMPOLINE_SECTION ();#else readonly_data_section ();#endif /* Write the assembler code to define one. */ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); if (align > 0) ASM_OUTPUT_ALIGN (asm_out_file, align); ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LTRAMP", 0); TRAMPOLINE_TEMPLATE (asm_out_file); /* Record the rtl to refer to it. */ ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0); name = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label)); return gen_rtx (SYMBOL_REF, Pmode, name);}/* Assemble the integer constant X into an object of SIZE bytes. X must be either a CONST_INT or CONST_DOUBLE. Return 1 if we were able to output the constant, otherwise 0. If FORCE is non-zero, abort if we can't output the constant. */intassemble_integer (x, size, force) rtx x; int size; int force;{ /* First try to use the standard 1, 2, 4, 8, and 16 byte ASM_OUTPUT... macros. */ switch (size) {#ifdef ASM_OUTPUT_CHAR case 1: ASM_OUTPUT_CHAR (asm_out_file, x); return 1;#endif#ifdef ASM_OUTPUT_SHORT case 2: ASM_OUTPUT_SHORT (asm_out_file, x); return 1;#endif#ifdef ASM_OUTPUT_INT case 4: ASM_OUTPUT_INT (asm_out_file, x); return 1;#endif#ifdef ASM_OUTPUT_DOUBLE_INT case 8: ASM_OUTPUT_DOUBLE_INT (asm_out_file, x); return 1;#endif#ifdef ASM_OUTPUT_QUADRUPLE_INT case 16: ASM_OUTPUT_QUADRUPLE_INT (asm_out_file, x); return 1;#endif } /* If we couldn't do it that way, there are two other possibilities: First, if the machine can output an explicit byte and this is a 1 byte constant, we can use ASM_OUTPUT_BYTE. */#ifdef ASM_OUTPUT_BYTE if (size == 1 && GET_CODE (x) == CONST_INT) { ASM_OUTPUT_BYTE (asm_out_file, INTVAL (x)); return 1; }#endif /* Finally, if SIZE is larger than a single word, try to output the constant one word at a time. */ if (size > UNITS_PER_WORD) { int i; enum machine_mode mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0); rtx word; for (i = 0; i < size / UNITS_PER_WORD; i++) { word = operand_subword (x, i, 0, mode); if (word == 0) break; if (! assemble_integer (word, UNITS_PER_WORD, 0)) break; } if (i == size / UNITS_PER_WORD) return 1; /* If we output at least one word and then could not finish, there is no valid way to continue. */ if (i > 0) abort (); } if (force) abort (); return 0;}/* Assemble the floating-point constant D into an object of size MODE. */voidassemble_real (d, mode) REAL_VALUE_TYPE d; enum machine_mode mode;{ jmp_buf output_constant_handler; if (setjmp (output_constant_handler)) { error ("floating point trap outputting a constant");#ifdef REAL_IS_NOT_DOUBLE bzero ((char *) &d, sizeof d); d = dconst0;#else d = 0;#endif } set_float_handler (output_constant_handler); switch (mode) {#ifdef ASM_OUTPUT_BYTE_FLOAT case QFmode: ASM_OUTPUT_BYTE_FLOAT (asm_out_file, d); break;#endif#ifdef ASM_OUTPUT_SHORT_FLOAT case HFmode: ASM_OUTPUT_SHORT_FLOAT (asm_out_file, d); break;#endif#ifdef ASM_OUTPUT_THREE_QUARTER_FLOAT case TQFmode: ASM_OUTPUT_THREE_QUARTER_FLOAT (asm_out_file, d); break;#endif#ifdef ASM_OUTPUT_FLOAT case SFmode: ASM_OUTPUT_FLOAT (asm_out_file, d); break;#endif#ifdef ASM_OUTPUT_DOUBLE case DFmode: ASM_OUTPUT_DOUBLE (asm_out_file, d); break;#endif#ifdef ASM_OUTPUT_LONG_DOUBLE case XFmode: case TFmode: ASM_OUTPUT_LONG_DOUBLE (asm_out_file, d); break;#endif default: abort (); } set_float_handler (NULL_PTR);}/* Here we combine duplicate floating constants to make CONST_DOUBLE rtx's, and force those out to memory when necessary. *//* Chain of all CONST_DOUBLE rtx's constructed for the current function. They are chained through the CONST_DOUBLE_CHAIN. A CONST_DOUBLE rtx has CONST_DOUBLE_MEM != cc0_rtx iff it is on this chain. In that case, CONST_DOUBLE_MEM is either a MEM, or const0_rtx if no MEM has been made for this CONST_DOUBLE yet. (CONST_DOUBLE_MEM is used only for top-level functions. See force_const_mem for explanation.) */static rtx const_double_chain;/* Return a CONST_DOUBLE or CONST_INT for a value specified as a pair of ints. For an integer, I0 is the low-order word and I1 is the high-order word. For a real number, I0 is the word with the low address and I1 is the word with the high address. */rtximmed_double_const (i0, i1, mode) HOST_WIDE_INT i0, i1; enum machine_mode mode;{ register rtx r; int in_current_obstack; if (GET_MODE_CLASS (mode) == MODE_INT || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT) { /* We clear out all bits that don't belong in MODE, unless they and our sign bit are all one. So we get either a reasonable negative value or a reasonable unsigned value for this mode. */ int width = GET_MODE_BITSIZE (mode); if (width < HOST_BITS_PER_WIDE_INT && ((i0 & ((HOST_WIDE_INT) (-1) << (width - 1)))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -