Commit ff8f4401 by Richard Stallman

(output_constant_def_contents): New function.

(output_constant_def): Use it.
(deferred_constants): New list of constants not yet output.
(defer_addressed_constants): New function.
(output_deferred_addressed_constants): New function.
(make_decl_rtl): Don't ever replace old rtl;
instead, change its mode if necessary.

From-SVN: r4974
parent de520661
...@@ -88,6 +88,8 @@ extern FILE *asm_out_file; ...@@ -88,6 +88,8 @@ extern FILE *asm_out_file;
static char *compare_constant_1 (); static char *compare_constant_1 ();
static void record_constant_1 (); static void record_constant_1 ();
static void output_constant_def_contents ();
void output_constant_pool (); void output_constant_pool ();
void assemble_name (); void assemble_name ();
int output_addressed_constants (); int output_addressed_constants ();
...@@ -313,11 +315,8 @@ make_decl_rtl (decl, asmspec, top_level) ...@@ -313,11 +315,8 @@ make_decl_rtl (decl, asmspec, top_level)
} }
/* For a duplicate declaration, we can be called twice on the /* For a duplicate declaration, we can be called twice on the
same DECL node. Don't alter the RTL already made same DECL node. Don't discard the RTL already made. */
unless the old mode is wrong (which can happen when if (DECL_RTL (decl) == 0)
the previous rtl was made when the type was incomplete). */
if (DECL_RTL (decl) == 0
|| GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
{ {
DECL_RTL (decl) = 0; DECL_RTL (decl) = 0;
...@@ -419,6 +418,12 @@ make_decl_rtl (decl, asmspec, top_level) ...@@ -419,6 +418,12 @@ make_decl_rtl (decl, asmspec, top_level)
#endif #endif
} }
} }
/* If the old RTL had the wrong mode, fix the mode. */
else if (GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
{
rtx rtl = DECL_RTL (decl);
PUT_MODE (rtl, DECL_MODE (decl));
}
} }
/* Make the rtl for variable VAR be volatile. /* Make the rtl for variable VAR be volatile.
...@@ -693,10 +698,12 @@ assemble_string (p, size) ...@@ -693,10 +698,12 @@ assemble_string (p, size)
TOP_LEVEL is nonzero if this variable has file scope. TOP_LEVEL is nonzero if this variable has file scope.
AT_END is nonzero if this is the special handling, at end of compilation, AT_END is nonzero if this is the special handling, at end of compilation,
to define things that have had only tentative definitions. */ 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). */
void void
assemble_variable (decl, top_level, at_end) assemble_variable (decl, top_level, at_end, dont_output_data)
tree decl; tree decl;
int top_level; int top_level;
int at_end; int at_end;
...@@ -763,7 +770,7 @@ assemble_variable (decl, top_level, at_end) ...@@ -763,7 +770,7 @@ assemble_variable (decl, top_level, at_end)
/* Still incomplete => don't allocate it; treat the tentative defn /* Still incomplete => don't allocate it; treat the tentative defn
(which is what it must have been) as an `extern' reference. */ (which is what it must have been) as an `extern' reference. */
if (DECL_SIZE (decl) == 0) if (!dont_output_data && DECL_SIZE (decl) == 0)
{ {
error_with_file_and_line (DECL_SOURCE_FILE (decl), error_with_file_and_line (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl), DECL_SOURCE_LINE (decl),
...@@ -785,19 +792,22 @@ assemble_variable (decl, top_level, at_end) ...@@ -785,19 +792,22 @@ assemble_variable (decl, top_level, at_end)
/* If storage size is erroneously variable, just continue. /* If storage size is erroneously variable, just continue.
Error message was already made. */ Error message was already made. */
if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST) if (DECL_SIZE (decl))
goto finish; {
if (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
goto finish;
app_disable (); app_disable ();
/* This is better than explicit arithmetic, since it avoids overflow. */ /* This is better than explicit arithmetic, since it avoids overflow. */
size_tree = size_binop (CEIL_DIV_EXPR, size_tree = size_binop (CEIL_DIV_EXPR,
DECL_SIZE (decl), size_int (BITS_PER_UNIT)); DECL_SIZE (decl), size_int (BITS_PER_UNIT));
if (TREE_INT_CST_HIGH (size_tree) != 0) if (TREE_INT_CST_HIGH (size_tree) != 0)
{ {
error_with_decl (decl, "size of variable `%s' is too large"); error_with_decl (decl, "size of variable `%s' is too large");
goto finish; goto finish;
}
} }
name = XSTR (XEXP (DECL_RTL (decl), 0), 0); name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
...@@ -809,6 +819,7 @@ assemble_variable (decl, top_level, at_end) ...@@ -809,6 +819,7 @@ assemble_variable (decl, top_level, at_end)
initializer equal to zero. (Section 3.7.2) initializer equal to zero. (Section 3.7.2)
-fno-common gives strict ANSI behavior. Usually you don't want it. */ -fno-common gives strict ANSI behavior. Usually you don't want it. */
if (! flag_no_common if (! flag_no_common
&& ! dont_output_data
&& (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)) && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
{ {
int size = TREE_INT_CST_LOW (size_tree); int size = TREE_INT_CST_LOW (size_tree);
...@@ -995,21 +1006,16 @@ assemble_variable (decl, top_level, at_end) ...@@ -995,21 +1006,16 @@ assemble_variable (decl, top_level, at_end)
ASM_OUTPUT_LABEL (asm_out_file, name); ASM_OUTPUT_LABEL (asm_out_file, name);
#endif /* ASM_DECLARE_OBJECT_NAME */ #endif /* ASM_DECLARE_OBJECT_NAME */
#if 0 if (!dont_output_data)
for (d = equivalents; d; d = TREE_CHAIN (d))
{ {
tree e = TREE_VALUE (d); if (DECL_INITIAL (decl))
ASM_OUTPUT_LABEL (asm_out_file, XSTR (XEXP (DECL_RTL (e), 0), 0)); /* 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)));
} }
#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: finish:
#ifdef XCOFF_DEBUGGING_INFO #ifdef XCOFF_DEBUGGING_INFO
...@@ -2004,19 +2010,70 @@ record_constant_1 (exp) ...@@ -2004,19 +2010,70 @@ record_constant_1 (exp)
obstack_grow (&permanent_obstack, strp, len); obstack_grow (&permanent_obstack, strp, len);
} }
/* Record a list of constant expressions that were passed to
output_constant_def but that could not be output right away. */
struct deferred_constant
{
struct deferred_constant *next;
tree exp;
int reloc;
int labelno;
};
static struct deferred_constant *deferred_constants;
/* Nonzero means defer output of addressed subconstants
(i.e., those for which output_constant_def is called.) */
static int defer_addressed_constants_flag;
/* Start deferring output of subconstants. */
void
defer_addressed_constants ()
{
defer_addressed_constants_flag++;
}
/* Stop deferring output of subconstants,
and output now all those that have been deferred. */
void
output_deferred_addressed_constants ()
{
struct deferred_constant *p, *next;
defer_addressed_constants_flag--;
if (defer_addressed_constants_flag > 0)
return;
for (p = deferred_constants; p; p = next)
{
output_constant_def_contents (p->exp, p->reloc, p->labelno);
next = p->next;
free (p);
}
deferred_constants = 0;
}
/* Return an rtx representing a reference to constant data in memory /* Return an rtx representing a reference to constant data in memory
for the constant expression EXP. for the constant expression EXP.
If assembler code for such a constant has already been output, If assembler code for such a constant has already been output,
return an rtx to refer to it. return an rtx to refer to it.
Otherwise, output such a constant in memory and generate Otherwise, output such a constant in memory (or defer it for later)
an rtx for it. The TREE_CST_RTL of EXP is set up to point to that rtx. and generate an rtx for it.
The TREE_CST_RTL of EXP is set up to point to that rtx.
The const_hash_table records which constants already have label strings. */ The const_hash_table records which constants already have label strings. */
rtx rtx
output_constant_def (exp) output_constant_def (exp)
tree exp; tree exp;
{ {
register int hash, align; register int hash;
register struct constant_descriptor *desc; register struct constant_descriptor *desc;
char label[256]; char label[256];
char *found = 0; char *found = 0;
...@@ -2090,44 +2147,77 @@ output_constant_def (exp) ...@@ -2090,44 +2147,77 @@ output_constant_def (exp)
ENCODE_SECTION_INFO (exp); ENCODE_SECTION_INFO (exp);
#endif #endif
/* If this is the first time we've seen this particular constant,
output it (or defer its output for later). */
if (found == 0) if (found == 0)
{ {
/* Now output assembler code to define that label if (defer_addressed_constants_flag)
and follow it with the data of EXP. */ {
struct deferred_constant *p;
p = (struct deferred_constant *) xmalloc (sizeof (struct deferred_constant));
/* We really should copy trees in depth here,
but since this case is the only one that should happen now,
let's do it later. */
if (TREE_CODE (exp) != STRING_CST)
abort ();
push_obstacks_nochange ();
suspend_momentary ();
p->exp = copy_node (exp);
pop_obstacks ();
p->reloc = reloc;
p->labelno = const_labelno++;
p->next = deferred_constants;
deferred_constants = p;
}
else
output_constant_def_contents (exp, reloc, const_labelno++);
}
return TREE_CST_RTL (exp);
}
/* Now output assembler code to define the label for EXP,
and follow it with the data of EXP. */
static void
output_constant_def_contents (exp, reloc, labelno)
tree exp;
int reloc;
int labelno;
{
int align;
/* First switch to text section, except for writable strings. */ /* First switch to text section, except for writable strings. */
#ifdef SELECT_SECTION #ifdef SELECT_SECTION
SELECT_SECTION (exp, reloc); SELECT_SECTION (exp, reloc);
#else #else
if (((TREE_CODE (exp) == STRING_CST) && flag_writable_strings) if (((TREE_CODE (exp) == STRING_CST) && flag_writable_strings)
|| (flag_pic && reloc)) || (flag_pic && reloc))
data_section (); data_section ();
else else
readonly_data_section (); readonly_data_section ();
#endif #endif
/* Align the location counter as required by EXP's data type. */ /* Align the location counter as required by EXP's data type. */
align = TYPE_ALIGN (TREE_TYPE (exp)); align = TYPE_ALIGN (TREE_TYPE (exp));
#ifdef CONSTANT_ALIGNMENT #ifdef CONSTANT_ALIGNMENT
align = CONSTANT_ALIGNMENT (exp, align); align = CONSTANT_ALIGNMENT (exp, align);
#endif #endif
if (align > BITS_PER_UNIT) if (align > BITS_PER_UNIT)
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
/* Output the label itself. */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", const_labelno);
/* Output the value of EXP. */ /* Output the label itself. */
output_constant (exp, ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", labelno);
(TREE_CODE (exp) == STRING_CST
? TREE_STRING_LENGTH (exp)
: int_size_in_bytes (TREE_TYPE (exp))));
++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))));
return TREE_CST_RTL (exp);
} }
/* Similar hash facility for making memory-constants /* Similar hash facility for making memory-constants
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment