📄 varasm.c
字号:
return 0; p += sizeof length; /* For record constructors, insist that the types match. For arrays, just verify both constructors are for arrays. */ if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) type = TREE_TYPE (exp); else type = 0; if (bcmp (&type, p, sizeof type)) return 0; p += sizeof type; for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0) return 0; return p; } else if (code == ADDR_EXPR) { struct addr_const value; decode_addr_const (exp, &value); strp = (char *) &value; len = sizeof value; /* Compare SYMBOL_REF address and offset. */ while (--len >= 0) if (*p++ != *strp++) return 0; /* Compare symbol name. */ strp = XSTR (value.base, 0); len = strlen (strp) + 1; } else if (code == PLUS_EXPR || code == MINUS_EXPR) { if (*p++ != (char) code) return 0; p = compare_constant_1 (TREE_OPERAND (exp, 0), p); if (p == 0) return 0; p = compare_constant_1 (TREE_OPERAND (exp, 1), p); return p; } else if (code == NOP_EXPR || code == CONVERT_EXPR) { if (*p++ != (char) code) return 0; p = compare_constant_1 (TREE_OPERAND (exp, 0), p); return p; } /* Compare constant contents. */ while (--len >= 0) if (*p++ != *strp++) return 0; return p;}/* Construct a constant descriptor for the expression EXP. It is up to the caller to enter the descriptor in the hash table. */static struct constant_descriptor *record_constant (exp) tree exp;{ struct constant_descriptor *ptr = 0; int buf; obstack_grow (&permanent_obstack, &ptr, sizeof ptr); obstack_grow (&permanent_obstack, &buf, sizeof buf); record_constant_1 (exp); return (struct constant_descriptor *) obstack_finish (&permanent_obstack);}/* Add a description of constant expression EXP to the object growing in `permanent_obstack'. No need to return its address; the caller will get that from the obstack when the object is complete. */static voidrecord_constant_1 (exp) tree exp;{ register char *strp; register int len; register enum tree_code code = TREE_CODE (exp); obstack_1grow (&permanent_obstack, (unsigned int) code); if (code == INTEGER_CST) { obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp))); strp = (char *) &TREE_INT_CST_LOW (exp); len = 2 * sizeof TREE_INT_CST_LOW (exp); } else if (code == REAL_CST) { obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp))); strp = (char *) &TREE_REAL_CST (exp); len = sizeof TREE_REAL_CST (exp); } else if (code == STRING_CST) { if (flag_writable_strings) return; strp = TREE_STRING_POINTER (exp); len = TREE_STRING_LENGTH (exp); obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp), sizeof TREE_STRING_LENGTH (exp)); } else if (code == COMPLEX_CST) { record_constant_1 (TREE_REALPART (exp)); record_constant_1 (TREE_IMAGPART (exp)); return; } else if (code == CONSTRUCTOR) { register tree link; int length = list_length (CONSTRUCTOR_ELTS (exp)); tree type; obstack_grow (&permanent_obstack, (char *) &length, sizeof length); /* For record constructors, insist that the types match. For arrays, just verify both constructors are for arrays. */ if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE) type = TREE_TYPE (exp); else type = 0; obstack_grow (&permanent_obstack, (char *) &type, sizeof type); for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) record_constant_1 (TREE_VALUE (link)); return; } else if (code == ADDR_EXPR) { struct addr_const value; decode_addr_const (exp, &value); /* Record the SYMBOL_REF address and the offset. */ obstack_grow (&permanent_obstack, (char *) &value, sizeof value); /* Record the symbol name. */ obstack_grow (&permanent_obstack, XSTR (value.base, 0), strlen (XSTR (value.base, 0)) + 1); return; } else if (code == PLUS_EXPR || code == MINUS_EXPR) { obstack_1grow (&permanent_obstack, (int) code); record_constant_1 (TREE_OPERAND (exp, 0)); record_constant_1 (TREE_OPERAND (exp, 1)); return; } else if (code == NOP_EXPR || code == CONVERT_EXPR) { obstack_1grow (&permanent_obstack, (int) code); record_constant_1 (TREE_OPERAND (exp, 0)); return; } /* Record constant contents. */ obstack_grow (&permanent_obstack, strp, len);}/* Return the constant-label-string for constant value EXP. If no constant equal to EXP has yet been output, define a new label and output assembler code for it. The const_hash_table records which constants already have label strings. */static char *get_or_assign_label (exp) tree exp;{ register int hash, i, align; register struct constant_descriptor *desc; char label[256]; /* Make sure any other constants whose addresses appear in EXP are assigned label numbers. */ output_addressed_constants (exp); /* Compute hash code of EXP. Search the descriptors for that hash code to see if any of them describes EXP. If yes, the descriptor records the label number already assigned. */ hash = const_hash (exp) % MAX_HASH_TABLE; for (desc = const_hash_table[hash]; desc; desc = desc->next) if (compare_constant (exp, desc)) return desc->label; /* No constant equal to EXP is known to have been output. Make a constant descriptor to enter EXP in the hash table. Assign the label number and record it in the descriptor for future calls to this function to find. */ desc = record_constant (exp); desc->next = const_hash_table[hash]; const_hash_table[hash] = desc; /* Now output assembler code to define that label and follow it with the data of EXP. */ /* First switch to text section, except for writable strings. */#ifdef SELECT_SECTION SELECT_SECTION (exp);#else if ((TREE_CODE (exp) == STRING_CST) && flag_writable_strings) data_section (); else text_section ();#endif /* Align the location counter as required by EXP's data type. */#ifdef CONSTANT_ALIGNMENT align = CONSTANT_ALIGNMENT (TREE_CODE (exp), TYPE_ALIGN (TREE_TYPE (exp)));#else align = TYPE_ALIGN (TREE_TYPE (exp));#endif for (i = 0; align >= BITS_PER_UNIT << (i + 1); i++); if (i > 0) ASM_OUTPUT_ALIGN (asm_out_file, i); /* Output the label itself. */ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", const_labelno); /* Output the value of EXP. */ output_constant (exp, (TREE_CODE (exp) == STRING_CST ? TREE_STRING_LENGTH (exp) : int_size_in_bytes (TREE_TYPE (exp)))); /* Create a string containing the label name, in LABEL. */ ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno); ++const_labelno; desc->label = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label)); return desc->label;}/* Return an rtx representing a reference to constant data in memory for the constant expression EXP. If assembler code for such a constant has already been output, return an rtx to refer to it. Otherwise, output such a constant in memory and generate an rtx for it. The TREE_CST_RTL of EXP is set up to point to that rtx. */rtxoutput_constant_def (exp) tree exp;{ register rtx def; int temp_p = allocation_temporary_p (); if (TREE_CODE (exp) == INTEGER_CST) abort (); /* No TREE_CST_RTL slot in these. */ if (TREE_CST_RTL (exp)) return TREE_CST_RTL (exp); if (TREE_PERMANENT (exp)) end_temporary_allocation (); def = gen_rtx (SYMBOL_REF, Pmode, get_or_assign_label (exp)); TREE_CST_RTL (exp) = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), def); RTX_UNCHANGING_P (TREE_CST_RTL (exp)) = 1; if (temp_p && TREE_PERMANENT (exp)) resume_temporary_allocation (); return TREE_CST_RTL (exp);}/* Similar hash facility for making memory-constants from constant rtl-expressions. It is used on RISC machines where immediate integer arguments and constant addresses are restricted so that such constants must be stored in memory. This pool of constants is reinitialized for each function so each function gets its own constants-pool that comes right before it. */#define MAX_RTX_HASH_TABLE 61static struct constant_descriptor *const_rtx_hash_table[MAX_RTX_HASH_TABLE];voidinit_const_rtx_hash_table (){ bzero (const_rtx_hash_table, sizeof const_rtx_hash_table);}struct rtx_const{ enum kind { RTX_DOUBLE, RTX_INT } kind : 16; enum machine_mode mode : 16; union { union real_extract du; struct addr_const addr; } un;};/* Express an rtx for a constant integer (perhaps symbolic) as the sum of a symbol or label plus an explicit integer. They are stored into VALUE. */static voiddecode_rtx_const (mode, x, value) enum machine_mode mode; rtx x; struct rtx_const *value;{ /* Clear the whole structure, including any gaps. */ { int *p = (int *) value; int *end = (int *) (value + 1); while (p < end) *p++ = 0; } value->kind = RTX_INT; /* Most usual kind. */ value->mode = mode; switch (GET_CODE (x)) { case CONST_DOUBLE: value->kind = RTX_DOUBLE; value->mode = GET_MODE (x); bcopy (&CONST_DOUBLE_LOW (x), &value->un.du, sizeof value->un.du); break; case CONST_INT: value->un.addr.offset = INTVAL (x); break; case SYMBOL_REF: value->un.addr.base = x; break; case LABEL_REF: value->un.addr.base = x; break; case CONST: x = XEXP (x, 0); if (GET_CODE (x) == PLUS) { value->un.addr.base = XEXP (XEXP (x, 0), 0); if (GET_CODE (XEXP (x, 1)) != CONST_INT) abort (); value->un.addr.offset = INTVAL (XEXP (x, 1)); } else if (GET_CODE (x) == MINUS) { value->un.addr.base = XEXP (x, 0); if (GET_CODE (XEXP (x, 1)) != CONST_INT) abort (); value->un.addr.offset = - INTVAL (XEXP (x, 1)); } else abort (); break; default: abort (); } if (value->kind == RTX_INT && value->un.addr.base != 0) switch (GET_CODE (value->un.addr.base)) { case SYMBOL_REF: case LABEL_REF: /* Use the string's address, not the SYMBOL_REF's address, for the sake of addresses of library routines. For a LABEL_REF, compare labels. */ value->un.addr.base = XEXP (value->un.addr.base, 0); }}/* Compute a hash code for a constant RTL expression. */intconst_hash_rtx (mode, x) enum machine_mode mode; rtx x;{ register int hi, i; struct rtx_const value; decode_rtx_const (mode, x, &value); /* Compute hashing function */ hi = 0; for (i = 0; i < sizeof value / sizeof (int); i++) hi += ((int *) &value)[i]; hi &= (1 << HASHBITS) - 1; hi %= MAX_RTX_HASH_TABLE; return hi;}/* Compare a constant rtl object X with a constant-descriptor DESC. Return 1 if DESC describes a constant with the same value as X. */static intcompare_constant_rtx (mode, x, desc) enum machine_mode mode; rtx x; struct constant_descriptor *desc;{ register int *p = (int *) desc->contents; register int *strp; register int len; struct rtx_const value; decode_rtx_const (mode, x, &value); strp = (int *) &value; len = sizeof value / sizeof (int); /* Compare constant contents. */ while (--len >= 0) if (*p++ != *strp++) return 0; return 1;}/* Construct a constant descriptor for the rtl-expression X. It is up to the caller to enter the descriptor in the hash table. */static struct constant_descriptor *record_constant_rtx (mode, x) enum machine_mode mode; rtx x;{ struct constant_descriptor *ptr = 0; int buf; struct rtx_const value; decode_rtx_const (mode, x, &value); obstack_grow (saveable_obstack, &ptr, sizeof ptr); obstack_grow (saveable_obstack, &buf, sizeof buf); /* Record constant contents. */ obstack_grow (saveable_obstack, &value, sizeof value); return (struct constant_descriptor *) obstack_finish (saveable_obstack);}/* Given a constant rtx X, make (or find) a memory constant for its value and return a MEM rtx to refer to it in memory. */rtxforce_const_mem (mode, x) enum machine_mode mode; rtx x;{ register int hash; register struct constant_descriptor *desc; char label[256]; char *found = 0; rtx def; if (GET_CODE (x) == CONST_DOUBLE && GET_CODE (CONST_DOUBLE_MEM (x)) == MEM) return CONST_DOUBLE_MEM (x); /* Compute hash code of X. Search the descriptors for that hash code to see if any of them describes X. If yes, the descriptor records the label number already assigned. */ hash = const_hash_rtx (mode, x); for (desc = const_rtx_hash_table[hash]; desc; desc = desc->next) if (compare_constant_rtx (mode, x, desc)) { found = desc->label; break; } if (found == 0) { int align; /* No constant equal to X is known to have been output. Make a constant descriptor to enter X in the hash table. Assign the label number and record it in the descriptor for future calls to this function to find. */ desc = record_constant_rtx (mode, x); desc->next = const_rtx_hash_table[hash]; const_rtx_hash_table[hash] = desc; /* Now output assembler code to define that label and follow it with the data of EXP. */ /* First switch to text section. */#ifdef SELECT_RTX_SECTION SELECT_RTX_SECTION (mode, x);#else text_section ();#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -