|
|
1.1 root 1: /* Output variables, constants and external declarations, for GNU compiler.
2: Copyright (C) 1987, 1988 Free Software Foundation, Inc.
3:
4: This file is part of GNU CC.
5:
6: GNU CC is distributed in the hope that it will be useful,
7: but WITHOUT ANY WARRANTY. No author or distributor
8: accepts responsibility to anyone for the consequences of using it
9: or for whether it serves any particular purpose or works at all,
10: unless he says so in writing. Refer to the GNU CC General Public
11: License for full details.
12:
13: Everyone is granted permission to copy, modify and redistribute
14: GNU CC, but only under the conditions described in the
15: GNU CC General Public License. A copy of this license is
16: supposed to have been given to you along with GNU CC so you
17: can know your rights and responsibilities. It should be in a
18: file named COPYING. Among other things, the copyright notice
19: and this notice must be preserved on all copies. */
20:
21:
22: /* This file handles generation of all the assembler code
23: *except* the instructions of a function.
24: This includes declarations of variables and their initial values.
25:
26: We also output the assembler code for constants stored in memory
27: and are responsible for combining constants with the same value. */
28:
29: #include <stdio.h>
30: /* #include <stab.h> */
31: #include "config.h"
32: #include "rtl.h"
33: #include "tree.h"
34: #include "flags.h"
35: #include "expr.h"
36:
37: #include "obstack.h"
38:
39: #define MIN(a, b) ((a) < (b) ? (a) : (b))
40:
41: /* File in which assembler code is being written. */
42:
43: extern FILE *asm_out_file;
44:
45: extern struct obstack *current_obstack;
46: extern struct obstack *saveable_obstack;
47: extern struct obstack permanent_obstack;
48: #define obstack_chunk_alloc xmalloc
49: extern int xmalloc ();
50:
51: /* Number for making the label on the next
52: constant that is stored in memory. */
53:
54: int const_labelno;
55:
56: /* Number for making the label on the next
57: static variable internal to a function. */
58:
59: int var_labelno;
60:
61: extern FILE *asm_out_file;
62:
63: static char *compare_constant_1 ();
64: static void record_constant_1 ();
65: void assemble_name ();
66: void output_addressed_constants ();
67: void output_constant ();
68: void output_constructor ();
69:
70: /* Output a string of literal assembler code
71: for an `asm' keyword used between functions. */
72:
73: void
74: assemble_asm (string)
75: tree string;
76: {
77: app_enable ();
78:
79: fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string));
80: }
81:
82: /* Output assembler code associated with defining the name of a function
83: as described by DECL. */
84:
85: void
86: assemble_function (decl)
87: tree decl;
88: {
89: rtx x, n;
90: char *fnname;
91:
92: /* Get the function's name, as described by its RTL.
93: This may be different from the DECL_NAME name used in the source file. */
94:
95: x = DECL_RTL (decl);
96: if (GET_CODE (x) != MEM)
97: abort ();
98: n = XEXP (x, 0);
99: if (GET_CODE (n) != SYMBOL_REF)
100: abort ();
101: fnname = XSTR (n, 0);
102:
103: /* The following code does not need preprocessing in the assembler. */
104:
105: app_disable ();
106:
107: /* Tell assembler to switch to text segment. */
108:
109: fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
110:
111: /* Tell assembler to move to target machine's alignment for functions. */
112:
113: ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT));
114:
115: /* Make function name accessible from other files, if appropriate. */
116:
117: if (TREE_PUBLIC (decl))
118: ASM_GLOBALIZE_LABEL (asm_out_file, fnname);
119:
120: /* Do any machine/system dependent processing of the function name */
121: #ifdef ASM_DECLARE_FUNCTION_NAME
122: ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname);
123: #else
124: /* Standard thing is just output label for the function. */
125: ASM_OUTPUT_LABEL (asm_out_file, fnname);
126: #endif /* ASM_DECLARE_FUNCTION_NAME */
127: }
128:
129: /* Assemble " .int 0\n" or whatever this assembler wants. */
130:
131: void
132: assemble_integer_zero ()
133: {
134: ASM_OUTPUT_INT (asm_out_file, const0_rtx);
135: }
136:
137: /* Create the rtx to represent a function in calls to it.
138: DECL is a FUNCTION_DECL node which describes which function.
139: The rtl is stored in DECL. */
140:
141: void
142: make_function_rtl (decl)
143: tree decl;
144: {
145: if (DECL_RTL (decl) == 0)
146: DECL_RTL (decl)
147: = gen_rtx (MEM, DECL_MODE (decl),
148: gen_rtx (SYMBOL_REF, Pmode,
149: IDENTIFIER_POINTER (DECL_NAME (decl))));
150: }
151:
152: /* Assemble everything that is needed for a variable or function declaration.
153: Not used for automatic variables, and not used for function definitions.
154: Should not be called for variables of incomplete structure type.
155:
156: ASMSPEC is the user's specification of assembler symbol name to use.
157: TOP_LEVEL is nonzero if this variable has file scope.
158: WRITE_SYMBOLS is 2 if writing dbx symbol output.
159: The dbx data for a file-scope variable is written here.
160: AT_END is nonzero if this is the special handling, at end of compilation,
161: to define things that have had only tentative definitions. */
162:
163: void
164: assemble_variable (decl, asmspec, top_level, write_symbols, at_end)
165: tree decl;
166: tree asmspec;
167: int top_level;
168: int write_symbols;
169: int at_end;
170: {
171: register char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
172: register int i;
173:
174: if (asmspec != 0)
175: {
176: if (TREE_CODE (asmspec) != STRING_CST)
177: abort ();
178: name = (char *) oballoc (strlen (TREE_STRING_POINTER (asmspec)) + 2);
179: name[0] = '*';
180: strcpy (&name[1], TREE_STRING_POINTER (asmspec));
181: }
182:
183: /* For a duplicate declaration, we can be called twice on the
184: same DECL node. Don't alter the RTL already made
185: unless the old mode is wrong (which can happen when
186: the previous rtl was made when the type was incomplete). */
187: if (DECL_RTL (decl) == 0
188: || GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
189: {
190: if (DECL_RTL (decl) && asmspec == 0)
191: name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
192:
193: /* Can't use just the variable's own name for a variable
194: whose scope is less than the whole file.
195: Concatenate a distinguishing number. */
196: else if (!top_level && !TREE_EXTERNAL (decl) && asmspec == 0)
197: {
198: char *label;
199:
200: ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno);
201: name = obstack_copy0 (current_obstack, label, strlen (label));
202: var_labelno++;
203: }
204:
205: DECL_RTL (decl) = gen_rtx (MEM, DECL_MODE (decl),
206: gen_rtx (SYMBOL_REF, Pmode, name));
207: if (TREE_VOLATILE (decl))
208: DECL_RTL (decl)->volatil = 1;
209: if (TREE_READONLY (decl))
210: DECL_RTL (decl)->unchanging = 1;
211: DECL_RTL (decl)->in_struct
212: = (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
213: || TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
214: || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE);
215: }
216:
217: /* Output no assembler code for a function declaration.
218: Only definitions of functions output anything. */
219:
220: if (TREE_CODE (decl) == FUNCTION_DECL)
221: return;
222:
223: /* Normally no need to say anything for external references,
224: since assembler considers all undefined symbols external. */
225:
226: if (TREE_EXTERNAL (decl))
227: {
228: #ifdef ASM_OUTPUT_EXTERNAL
229: /* Some systems do require some output. */
230: ASM_OUTPUT_EXTERNAL (asm_out_file, decl, name);
231: #endif
232: return;
233: }
234: /* Don't output anything when a tentative file-scope definition is seen.
235: But at end of compilation, do output code for them. */
236: if (! at_end && top_level
237: && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
238: return;
239:
240: /* If type was incomplete when the variable was declared,
241: see if it is complete now. */
242:
243: if (DECL_SIZE (decl) == 0)
244: layout_decl (decl);
245:
246: /* Still incomplete => don't allocate it; treat the tentative defn
247: (which is what it must have been) as an `extern' reference. */
248:
249: if (DECL_SIZE (decl) == 0)
250: {
251: error_with_file_and_line (DECL_SOURCE_FILE (decl),
252: DECL_SOURCE_LINE (decl),
253: "storage size of static var `%s' isn't known",
254: IDENTIFIER_POINTER (DECL_NAME (decl)));
255: return;
256: }
257:
258: /* The first declaration of a variable that comes through this function
259: decides whether it is global (in C, has external linkage)
260: or local (in C, has internal linkage). So do nothing more
261: if this function has already run. */
262:
263: if (TREE_ASM_WRITTEN (decl))
264: return;
265:
266: TREE_ASM_WRITTEN (decl) = 1;
267:
268: if (write_symbols == 2)
269: dbxout_symbol (decl, 0);
270: else if (write_symbols != 0)
271: /* Make sure the file is known to GDB even if it has no functions. */
272: set_current_gdbfile (DECL_SOURCE_FILE (decl));
273:
274: /* If storage size is erroneously variable, just continue.
275: Error message was already made. */
276:
277: if (! TREE_LITERAL (DECL_SIZE (decl)))
278: return;
279:
280: app_disable ();
281:
282: /* Handle uninitialized definitions. */
283:
284: if (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)
285: {
286: int size = (TREE_INT_CST_LOW (DECL_SIZE (decl))
287: * DECL_SIZE_UNIT (decl)
288: / BITS_PER_UNIT);
289: /* Round size up to multiple of BIGGEST_ALIGNMENT bits
290: so that each uninitialized object starts on such a boundary. */
291: size = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
292: / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
293: * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
294: if (TREE_PUBLIC (decl))
295: ASM_OUTPUT_COMMON (asm_out_file, name, size);
296: else
297: ASM_OUTPUT_LOCAL (asm_out_file, name, size);
298: return;
299: }
300:
301: /* Handle initialized definitions. */
302:
303: if (TREE_PUBLIC (decl))
304: ASM_GLOBALIZE_LABEL (asm_out_file, name);
305:
306: output_addressed_constants (DECL_INITIAL (decl));
307:
308: if (TREE_READONLY (decl) && ! TREE_VOLATILE (decl))
309: fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
310: else
311: fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
312:
313: for (i = 0; DECL_ALIGN (decl) >= BITS_PER_UNIT << (i + 1); i++);
314:
315: ASM_OUTPUT_ALIGN (asm_out_file, i);
316:
317: ASM_OUTPUT_LABEL (asm_out_file, name);
318: output_constant (DECL_INITIAL (decl), int_size_in_bytes (TREE_TYPE (decl)));
319: }
320:
321: /* Output to FILE a reference to the assembler name of a C-level name NAME.
322: If NAME starts with a *, the rest of NAME is output verbatim.
323: Otherwise NAME is transformed in an implementation-defined way
324: (usually by the addition of an underscore).
325: Many macros in the tm file are defined to call this function. */
326:
327: void
328: assemble_name (file, name)
329: FILE *file;
330: char *name;
331: {
332: if (name[0] == '*')
333: fputs (&name[1], file);
334: else
335: ASM_OUTPUT_LABELREF (file, name);
336: }
337:
338: /* Here we combine duplicate floating constants to make
339: CONST_DOUBLE rtx's, and force those out to memory when necessary. */
340:
341: /* Chain of all CONST_DOUBLE rtx's constructed for the current function.
342: They are chained through the third operand slot. */
343:
344: extern rtx real_constant_chain;
345:
346: /* Return a CONST_DOUBLE for a specified `double' value
347: and machine mode. */
348:
349: rtx
350: immed_real_const_1 (d, mode)
351: double d;
352: enum machine_mode mode;
353:
354: {
355: register rtx r;
356: union {double d; int i[2];} u;
357: register int i0, i1;
358:
359: /* Get the desired `double' value as two ints
360: since that is how they are stored in a CONST_DOUBLE. */
361:
362: u.d = d;
363: i0 = u.i[0];
364: i1 = u.i[1];
365:
366: /* Search the chain for an existing CONST_DOUBLE with the right value.
367: If one is found, return it. */
368:
369: for (r = real_constant_chain; r; r = XEXP (r, 3))
370: if (XINT (r, 0) == i0 && XINT (r, 1) == i1
371: && GET_MODE (r) == mode)
372: return r;
373:
374: /* No; make a new one and add it to the chain. */
375:
376: r = gen_rtx (CONST_DOUBLE, mode, i0, i1, 0);
377: XEXP (r, 3) = real_constant_chain;
378: real_constant_chain = r;
379:
380: /* Store const0_rtx in slot 2 just so most things won't barf.
381: Actual use of slot 2 is only through force_const_double_mem. */
382:
383: XEXP (r, 2) = const0_rtx;
384:
385: return r;
386: }
387:
388: /* Return a CONST_DOUBLE rtx for a value specified by EXP,
389: which must be a REAL_CST tree node. Make only one CONST_DOUBLE
390: for each distinct value. */
391:
392: rtx
393: immed_real_const (exp)
394: tree exp;
395: {
396: register rtx r;
397: r = immed_real_const_1 (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)));
398:
399: /* Associate exp and with this rtl value. */
400: TREE_CST_RTL (exp) = r;
401:
402: return r;
403: }
404:
405: /* Given a CONST_DOUBLE, cause a constant in memory to be created
406: (unless we already have one for the same value)
407: and return a MEM rtx to refer to it. */
408:
409: rtx
410: force_const_double_mem (r)
411: rtx r;
412: {
413: if (XEXP (r, 2) == const0_rtx)
414: {
415: XEXP (r, 2) = force_const_mem (GET_MODE (r), r);
416: }
417: /* XEXP (r, 2) is now a MEM with a constant address.
418: If that is legitimate, return it.
419: Othewise it will need reloading, so return a copy of it. */
420: if (memory_address_p (GET_MODE (r), XEXP (XEXP (r, 2), 0)))
421: return XEXP (r, 2);
422: return gen_rtx (MEM, GET_MODE (r), XEXP (XEXP (r, 2), 0));
423: }
424:
425: /* At the start of a function, forget the memory-constants
426: previously made for CONST_DOUBLEs. */
427:
428: static void
429: clear_const_double_mem ()
430: {
431: register rtx r;
432:
433: for (r = real_constant_chain; r; r = XEXP (r, 3))
434: XEXP (r, 2) = 0;
435: }
436:
437: /* Given an expression EXP with a constant value,
438: reduce it to the sum of an assembler symbol and an integer.
439: Store them both in the structure *VALUE.
440: Abort if EXP does not reduce. */
441:
442: struct addr_const
443: {
444: rtx base;
445: int offset;
446: };
447:
448: static void
449: decode_addr_const (exp, value)
450: tree exp;
451: struct addr_const *value;
452: {
453: register tree target = TREE_OPERAND (exp, 0);
454: register int offset = 0;
455: register rtx x;
456:
457: while (1)
458: {
459: if (TREE_CODE (target) == COMPONENT_REF)
460: {
461: offset += DECL_OFFSET (TREE_OPERAND (target, 1)) / BITS_PER_UNIT;
462: target = TREE_OPERAND (target, 0);
463: }
464: else if (TREE_CODE (target) == ARRAY_REF)
465: {
466: if (TREE_CODE (TREE_OPERAND (target, 1)) != INTEGER_CST
467: || TREE_CODE (TYPE_SIZE (TREE_TYPE (target))) != INTEGER_CST)
468: abort ();
469: offset += ((TYPE_SIZE_UNIT (TREE_TYPE (target))
470: * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (target)))
471: * TREE_INT_CST_LOW (TREE_OPERAND (target, 1)))
472: / BITS_PER_UNIT);
473: target = TREE_OPERAND (target, 0);
474: }
475: else break;
476: }
477:
478: if (TREE_CODE (target) == VAR_DECL
479: || TREE_CODE (target) == FUNCTION_DECL)
480: x = DECL_RTL (target);
481: else if (TREE_LITERAL (target))
482: x = TREE_CST_RTL (target);
483: else
484: abort ();
485:
486: if (GET_CODE (x) != MEM)
487: abort ();
488: x = XEXP (x, 0);
489:
490: value->base = x;
491: value->offset = offset;
492: }
493:
494: /* Uniquize all constants that appear in memory.
495: Each constant in memory thus far output is recorded
496: in `const_hash_table' with a `struct constant_descriptor'
497: that contains a polish representation of the value of
498: the constant.
499:
500: We cannot store the trees in the hash table
501: because the trees may be temporary. */
502:
503: struct constant_descriptor
504: {
505: struct constant_descriptor *next;
506: char *label;
507: char contents[1];
508: };
509:
510: #define HASHBITS 30
511: #define MAX_HASH_TABLE 1007
512: static struct constant_descriptor *const_hash_table[MAX_HASH_TABLE];
513:
514: /* Compute a hash code for a constant expression. */
515:
516: int
517: const_hash (exp)
518: tree exp;
519: {
520: register char *p;
521: register int len, hi, i;
522: register enum tree_code code = TREE_CODE (exp);
523:
524: if (code == INTEGER_CST)
525: {
526: p = (char *) &TREE_INT_CST_LOW (exp);
527: len = 2 * sizeof TREE_INT_CST_LOW (exp);
528: }
529: else if (code == REAL_CST)
530: {
531: p = (char *) &TREE_REAL_CST (exp);
532: len = sizeof TREE_REAL_CST (exp);
533: }
534: else if (code == STRING_CST)
535: p = TREE_STRING_POINTER (exp), len = TREE_STRING_LENGTH (exp);
536: else if (code == COMPLEX_CST)
537: return const_hash (TREE_REALPART (exp)) * 5
538: + const_hash (TREE_IMAGPART (exp));
539: else if (code == CONSTRUCTOR)
540: {
541: register tree link;
542: hi = 5;
543: for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
544: hi = (hi * 603 + const_hash (TREE_VALUE (link))) % MAX_HASH_TABLE;
545: return hi;
546: }
547: else if (code == ADDR_EXPR)
548: {
549: struct addr_const value;
550: decode_addr_const (exp, &value);
551: p = (char *) &value;
552: len = sizeof value;
553: }
554: else if (code == PLUS_EXPR || code == MINUS_EXPR)
555: return const_hash (TREE_OPERAND (exp, 0)) * 9
556: + const_hash (TREE_OPERAND (exp, 1));
557: else if (code == NOP_EXPR || code == CONVERT_EXPR)
558: return const_hash (TREE_OPERAND (exp, 0)) * 7 + 2;
559:
560: /* Compute hashing function */
561: hi = len;
562: for (i = 0; i < len; i++)
563: hi = ((hi * 613) + (unsigned)(p[i]));
564:
565: hi &= (1 << HASHBITS) - 1;
566: hi %= MAX_HASH_TABLE;
567: return hi;
568: }
569:
570: /* Compare a constant expression EXP with a constant-descriptor DESC.
571: Return 1 if DESC describes a constant with the same value as EXP. */
572:
573: static int
574: compare_constant (exp, desc)
575: tree exp;
576: struct constant_descriptor *desc;
577: {
578: return 0 != compare_constant_1 (exp, desc->contents);
579: }
580:
581: /* Compare constant expression EXP with a substring P of a constant descriptor.
582: If they match, return a pointer to the end of the substring matched.
583: If they do not match, return 0.
584:
585: Since descriptors are written in polish prefix notation,
586: this function can be used recursively to test one operand of EXP
587: against a subdescriptor, and if it succeeds it returns the
588: address of the subdescriptor for the next operand. */
589:
590: static char *
591: compare_constant_1 (exp, p)
592: tree exp;
593: char *p;
594: {
595: register char *strp;
596: register int len;
597: register enum tree_code code = TREE_CODE (exp);
598:
599: if (code != (enum tree_code) *p++)
600: return 0;
601:
602: if (code == INTEGER_CST)
603: {
604: strp = (char *) &TREE_INT_CST_LOW (exp);
605: len = 2 * sizeof TREE_INT_CST_LOW (exp);
606: }
607: else if (code == REAL_CST)
608: {
609: /* Real constants are the same only if the same width of type. */
610: if (*p++ != TYPE_PRECISION (TREE_TYPE (exp)))
611: return 0;
612: strp = (char *) &TREE_REAL_CST (exp);
613: len = sizeof TREE_REAL_CST (exp);
614: }
615: else if (code == STRING_CST)
616: {
617: if (flag_writable_strings)
618: return 0;
619: strp = TREE_STRING_POINTER (exp);
620: len = TREE_STRING_LENGTH (exp);
621: if (bcmp (&TREE_STRING_LENGTH (exp), p,
622: sizeof TREE_STRING_LENGTH (exp)))
623: return 0;
624: p += sizeof TREE_STRING_LENGTH (exp);
625: }
626: else if (code == COMPLEX_CST)
627: {
628: p = compare_constant_1 (TREE_REALPART (exp), p);
629: if (p == 0) return 0;
630: p = compare_constant_1 (TREE_IMAGPART (exp), p);
631: return p;
632: }
633: else if (code == CONSTRUCTOR)
634: {
635: register tree link;
636: int length = list_length (CONSTRUCTOR_ELTS (exp));
637: if (bcmp (&length, p, sizeof length))
638: return 0;
639: p += sizeof length;
640: for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
641: if ((p = compare_constant_1 (TREE_VALUE (link), p)) == 0)
642: return 0;
643: return p;
644: }
645: else if (code == ADDR_EXPR)
646: {
647: struct addr_const value;
648: decode_addr_const (exp, &value);
649: strp = (char *) &value;
650: len = sizeof value;
651: }
652: else if (code == PLUS_EXPR || code == MINUS_EXPR)
653: {
654: if (*p++ != (char) code)
655: return 0;
656: p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
657: if (p == 0) return 0;
658: p = compare_constant_1 (TREE_OPERAND (exp, 1), p);
659: return p;
660: }
661: else if (code == NOP_EXPR || code == CONVERT_EXPR)
662: {
663: if (*p++ != (char) code)
664: return 0;
665: p = compare_constant_1 (TREE_OPERAND (exp, 0), p);
666: return p;
667: }
668:
669: /* Compare constant contents. */
670: while (--len >= 0)
671: if (*p++ != *strp++)
672: return 0;
673:
674: return p;
675: }
676:
677: /* Construct a constant descriptor for the expression EXP.
678: It is up to the caller to enter the descriptor in the hash table. */
679:
680: static struct constant_descriptor *
681: record_constant (exp)
682: tree exp;
683: {
684: struct constant_descriptor *ptr = 0;
685: int buf;
686:
687: obstack_grow (&permanent_obstack, &ptr, sizeof ptr);
688: obstack_grow (&permanent_obstack, &buf, sizeof buf);
689: record_constant_1 (exp);
690: return (struct constant_descriptor *) obstack_finish (&permanent_obstack);
691: }
692:
693: /* Add a description of constant expression EXP
694: to the object growing in `permanent_obstack'.
695: No need to return its address; the caller will get that
696: from the obstack when the object is complete. */
697:
698: static void
699: record_constant_1 (exp)
700: tree exp;
701: {
702: register char *strp;
703: register int len;
704: register enum tree_code code = TREE_CODE (exp);
705:
706: obstack_1grow (&permanent_obstack, (unsigned char) code);
707:
708: if (code == INTEGER_CST)
709: {
710: strp = (char *) &TREE_INT_CST_LOW (exp);
711: len = 2 * sizeof TREE_INT_CST_LOW (exp);
712: }
713: else if (code == REAL_CST)
714: {
715: obstack_1grow (&permanent_obstack, TYPE_PRECISION (TREE_TYPE (exp)));
716: strp = (char *) &TREE_REAL_CST (exp);
717: len = sizeof TREE_REAL_CST (exp);
718: }
719: else if (code == STRING_CST)
720: {
721: if (flag_writable_strings)
722: return;
723: strp = TREE_STRING_POINTER (exp);
724: len = TREE_STRING_LENGTH (exp);
725: obstack_grow (&permanent_obstack, (char *) &TREE_STRING_LENGTH (exp),
726: sizeof TREE_STRING_LENGTH (exp));
727: }
728: else if (code == COMPLEX_CST)
729: {
730: record_constant_1 (TREE_REALPART (exp));
731: record_constant_1 (TREE_IMAGPART (exp));
732: return;
733: }
734: else if (code == CONSTRUCTOR)
735: {
736: register tree link;
737: int length = list_length (CONSTRUCTOR_ELTS (exp));
738: obstack_grow (&permanent_obstack, (char *) &length, sizeof length);
739:
740: for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
741: record_constant_1 (TREE_VALUE (link));
742: return;
743: }
744: else if (code == ADDR_EXPR)
745: {
746: struct addr_const value;
747: decode_addr_const (exp, &value);
748: strp = (char *) &value;
749: len = sizeof value;
750: }
751: else if (code == PLUS_EXPR || code == MINUS_EXPR)
752: {
753: obstack_1grow (&permanent_obstack, (char) code);
754: record_constant_1 (TREE_OPERAND (exp, 0));
755: record_constant_1 (TREE_OPERAND (exp, 1));
756: return;
757: }
758: else if (code == NOP_EXPR || code == CONVERT_EXPR)
759: {
760: obstack_1grow (&permanent_obstack, (char) code);
761: record_constant_1 (TREE_OPERAND (exp, 0));
762: return;
763: }
764:
765: /* Record constant contents. */
766: obstack_grow (&permanent_obstack, strp, len);
767: }
768:
769: /* Return the constant-label-string for constant value EXP.
770: If no constant equal to EXP has yet been output,
771: define a new label and output assembler code for it.
772: The const_hash_table records which constants already have label strings. */
773:
774: static char *
775: get_or_assign_label (exp)
776: tree exp;
777: {
778: register int hash, i;
779: register struct constant_descriptor *desc;
780: char label[10];
781:
782: /* Make sure any other constants whose addresses appear in EXP
783: are assigned label numbers. */
784:
785: output_addressed_constants (exp);
786:
787: /* Compute hash code of EXP. Search the descriptors for that hash code
788: to see if any of them describes EXP. If yes, the descriptor records
789: the label number already assigned. */
790:
791: hash = const_hash (exp) % MAX_HASH_TABLE;
792:
793: for (desc = const_hash_table[hash]; desc; desc = desc->next)
794: if (compare_constant (exp, desc))
795: return desc->label;
796:
797: /* No constant equal to EXP is known to have been output.
798: Make a constant descriptor to enter EXP in the hash table.
799: Assign the label number and record it in the descriptor for
800: future calls to this function to find. */
801:
802: desc = record_constant (exp);
803: desc->next = const_hash_table[hash];
804: const_hash_table[hash] = desc;
805:
806: /* Now output assembler code to define that label
807: and follow it with the data of EXP. */
808:
809: /* First switch to text segment, except for writable strings. */
810: if ((TREE_CODE (exp) == STRING_CST) && flag_writable_strings)
811: fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
812: else
813: fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
814:
815: /* Align the location counter as required by EXP's data type. */
816: for (i = 0; TYPE_ALIGN (TREE_TYPE (exp)) >= BITS_PER_UNIT << (i + 1); i++);
817: ASM_OUTPUT_ALIGN (asm_out_file, i);
818:
819: /* Output the label itself. */
820: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", const_labelno);
821:
822: /* Output the value of EXP. */
823: output_constant (exp,
824: (TREE_CODE (exp) == STRING_CST
825: ? TREE_STRING_LENGTH (exp)
826: : int_size_in_bytes (TREE_TYPE (exp))));
827:
828: /* Create a string containing the label name, in LABEL. */
829: ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
830:
831: ++const_labelno;
832:
833: desc->label
834: = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
835:
836: return desc->label;
837: }
838:
839: /* Return an rtx representing a reference to constant data in memory
840: for the constant expression EXP.
841: If assembler code for such a constant has already been output,
842: return an rtx to refer to it.
843: Otherwise, output such a constant in memory and generate
844: an rtx for it. The TREE_CST_RTL of EXP is set up to point to that rtx. */
845:
846: rtx
847: output_constant_def (exp)
848: tree exp;
849: {
850: register rtx def;
851: char label[10];
852:
853: if (TREE_CST_RTL (exp))
854: return TREE_CST_RTL (exp);
855:
856: def = gen_rtx (SYMBOL_REF, Pmode, get_or_assign_label (exp));
857:
858: TREE_CST_RTL (exp)
859: = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)), def);
860: TREE_CST_RTL (exp)->unchanging = 1;
861:
862: return TREE_CST_RTL (exp);
863: }
864:
865: /* Similar hash facility for making memory-constants
866: from constant rtl-expressions. It is used on RISC machines
867: where immediate integer arguments and constant addresses are restricted
868: so that such constants must be stored in memory.
869:
870: This pool of constants is reinitialized for each function
871: so each function gets its own constants-pool that comes right before it. */
872:
873: #define MAX_RTX_HASH_TABLE 61
874: static struct constant_descriptor *const_rtx_hash_table[MAX_RTX_HASH_TABLE];
875:
876: void
877: init_const_rtx_hash_table ()
878: {
879: bzero (const_rtx_hash_table, sizeof const_rtx_hash_table);
880: clear_const_double_mem ();
881: }
882:
883: struct rtx_const
884: {
885: enum kind { RTX_DOUBLE, RTX_INT } kind : 16;
886: enum machine_mode mode : 16;
887: union {
888: int d[2];
889: struct addr_const addr;
890: } un;
891: };
892:
893: /* Express an rtx for a constant integer (perhaps symbolic)
894: as the sum of a symbol or label plus an explicit integer.
895: They are stored into VALUE. */
896:
897: static void
898: decode_rtx_const (x, value)
899: rtx x;
900: struct rtx_const *value;
901: {
902: value->kind = RTX_INT; /* Most usual kind. */
903: value->mode = GET_MODE (x);
904: value->un.addr.base = 0;
905: value->un.addr.offset = 0;
906:
907: switch (GET_CODE (x))
908: {
909: case CONST_DOUBLE:
910: value->kind = RTX_DOUBLE;
911: value->mode = GET_MODE (x);
912: value->un.d[0] = XINT (x, 0);
913: value->un.d[1] = XINT (x, 1);
914: break;
915:
916: case CONST_INT:
917: value->un.addr.offset = INTVAL (x);
918: break;
919:
920: case SYMBOL_REF:
921: /* Use the string's address, not the SYMBOL_REF's address,
922: for the sake of addresses of library routines. */
923: value->un.addr.base = XEXP (x, 0);
924: break;
925:
926: case LABEL_REF:
927: /* Return the CODE_LABEL, not the LABEL_REF. */
928: value->un.addr.base = XEXP (x, 0);
929: break;
930:
931: case CONST:
932: x = XEXP (x, 0);
933: if (GET_CODE (x) == PLUS)
934: {
935: value->un.addr.base = XEXP (x, 0);
936: if (GET_CODE (XEXP (x, 1)) != CONST_INT)
937: abort ();
938: value->un.addr.offset = INTVAL (XEXP (x, 1));
939: }
940: else if (GET_CODE (x) == MINUS)
941: {
942: value->un.addr.base = XEXP (x, 0);
943: if (GET_CODE (XEXP (x, 1)) != CONST_INT)
944: abort ();
945: value->un.addr.offset = - INTVAL (XEXP (x, 1));
946: }
947: else
948: abort ();
949: break;
950:
951: default:
952: abort ();
953: }
954: }
955:
956: /* Compute a hash code for a constant RTL expression. */
957:
958: int
959: const_hash_rtx (x)
960: rtx x;
961: {
962: register int hi, i, len;
963: register char *p;
964:
965: struct rtx_const value;
966: decode_rtx_const (x, &value);
967:
968: /* Compute hashing function */
969: hi = 0;
970: for (i = 0; i < sizeof value / sizeof (int); i++)
971: hi += ((int *) &value)[i];
972:
973: hi &= (1 << HASHBITS) - 1;
974: hi %= MAX_RTX_HASH_TABLE;
975: return hi;
976: }
977:
978: /* Compare a constant rtl object X with a constant-descriptor DESC.
979: Return 1 if DESC describes a constant with the same value as X. */
980:
981: static int
982: compare_constant_rtx (x, desc)
983: rtx x;
984: struct constant_descriptor *desc;
985: {
986: register int *p = (int *) desc->contents;
987: register int *strp;
988: register int len;
989: struct rtx_const value;
990:
991: decode_rtx_const (x, &value);
992: strp = (int *) &value;
993: len = sizeof value / sizeof (int);
994:
995: /* Compare constant contents. */
996: while (--len >= 0)
997: if (*p++ != *strp++)
998: return 0;
999:
1000: return 1;
1001: }
1002:
1003: /* Construct a constant descriptor for the rtl-expression X.
1004: It is up to the caller to enter the descriptor in the hash table. */
1005:
1006: static struct constant_descriptor *
1007: record_constant_rtx (x)
1008: rtx x;
1009: {
1010: struct constant_descriptor *ptr = 0;
1011: int buf;
1012: struct rtx_const value;
1013:
1014: decode_rtx_const (x, &value);
1015:
1016: obstack_grow (saveable_obstack, &ptr, sizeof ptr);
1017: obstack_grow (saveable_obstack, &buf, sizeof buf);
1018:
1019: /* Record constant contents. */
1020: obstack_grow (saveable_obstack, &value, sizeof value);
1021:
1022: return (struct constant_descriptor *) obstack_finish (saveable_obstack);
1023: }
1024:
1025: /* Given a constant rtx X, make (or find) a memory constant for its value
1026: and return a MEM rtx to refer to it in memory. */
1027:
1028: rtx
1029: force_const_mem (mode, x)
1030: enum machine_mode mode;
1031: rtx x;
1032: {
1033: register int hash, i;
1034: register struct constant_descriptor *desc;
1035: char label[10];
1036: char *found = 0;
1037: rtx def;
1038:
1039: /* Compute hash code of X. Search the descriptors for that hash code
1040: to see if any of them describes X. If yes, the descriptor records
1041: the label number already assigned. */
1042:
1043: hash = const_hash_rtx (x);
1044:
1045: for (desc = const_rtx_hash_table[hash]; desc; desc = desc->next)
1046: if (compare_constant_rtx (x, desc))
1047: {
1048: found = desc->label;
1049: break;
1050: }
1051:
1052: if (found == 0)
1053: {
1054: /* No constant equal to X is known to have been output.
1055: Make a constant descriptor to enter X in the hash table.
1056: Assign the label number and record it in the descriptor for
1057: future calls to this function to find. */
1058:
1059: desc = record_constant_rtx (x);
1060: desc->next = const_rtx_hash_table[hash];
1061: const_rtx_hash_table[hash] = desc;
1062:
1063: /* Now output assembler code to define that label
1064: and follow it with the data of EXP. */
1065:
1066: /* First switch to text segment. */
1067: fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
1068:
1069: /* Align the location counter as required by EXP's data type. */
1070: ASM_OUTPUT_ALIGN (asm_out_file, exact_log2 (UNITS_PER_WORD));
1071:
1072: /* Output the label itself. */
1073: ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", const_labelno);
1074:
1075: /* Output the value of EXP. */
1076: if (GET_CODE (x) == CONST_DOUBLE)
1077: {
1078: union {double d; int i[2];} u;
1079:
1080: u.i[0] = XINT (x, 0);
1081: u.i[1] = XINT (x, 1);
1082: if (GET_MODE_SIZE (GET_MODE (x)) == GET_MODE_SIZE (DFmode))
1083: ASM_OUTPUT_DOUBLE (asm_out_file, u.d);
1084: else
1085: ASM_OUTPUT_FLOAT (asm_out_file, u.d);
1086: }
1087: else
1088: ASM_OUTPUT_INT (asm_out_file, x);
1089:
1090: /* Create a string containing the label name, in LABEL. */
1091: ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
1092:
1093: ++const_labelno;
1094:
1095: desc->label = found
1096: = (char *) obstack_copy0 (&permanent_obstack, label, strlen (label));
1097: }
1098:
1099: /* We have a symbol name; construct the SYMBOL_REF and the MEM. */
1100:
1101: def = gen_rtx (MEM, mode, gen_rtx (SYMBOL_REF, Pmode, desc->label));
1102:
1103: def->unchanging = 1;
1104: /* Mark the symbol_ref as belonging to this constants pool. */
1105: XEXP (def, 0)->unchanging = 1;
1106:
1107: return def;
1108: }
1109:
1110: /* Find all the constants whose addresses are referenced inside of EXP,
1111: and make sure assembler code with a label has been output for each one. */
1112:
1113: void
1114: output_addressed_constants (exp)
1115: tree exp;
1116: {
1117: switch (TREE_CODE (exp))
1118: {
1119: case ADDR_EXPR:
1120: {
1121: register tree constant = TREE_OPERAND (exp, 0);
1122:
1123: while (TREE_CODE (constant) == COMPONENT_REF)
1124: {
1125: constant = TREE_OPERAND (constant, 0);
1126: }
1127:
1128: if (TREE_LITERAL (constant))
1129: /* No need to do anything here
1130: for addresses of variables or functions. */
1131: output_constant_def (constant);
1132: }
1133: break;
1134:
1135: case PLUS_EXPR:
1136: case MINUS_EXPR:
1137: output_addressed_constants (TREE_OPERAND (exp, 0));
1138: output_addressed_constants (TREE_OPERAND (exp, 1));
1139: break;
1140:
1141: case NOP_EXPR:
1142: case CONVERT_EXPR:
1143: output_addressed_constants (TREE_OPERAND (exp, 0));
1144: break;
1145:
1146: case CONSTRUCTOR:
1147: {
1148: register tree link;
1149: for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
1150: output_addressed_constants (TREE_VALUE (link));
1151: }
1152: break;
1153:
1154: case ERROR_MARK:
1155: break;
1156:
1157: default:
1158: if (! TREE_LITERAL (exp))
1159: abort ();
1160: }
1161: }
1162:
1163: /* Output assembler code for constant EXP to FILE, with no label.
1164: This includes the pseudo-op such as ".int" or ".byte", and a newline.
1165: Assumes output_addressed_constants has been done on EXP already.
1166:
1167: Generate exactly SIZE bytes of assembler data, padding at the end
1168: with zeros if necessary. SIZE must always be specified.
1169:
1170: SIZE is important for structure constructors,
1171: since trailing members may have been omitted from the constructor.
1172: It is also important for initialization of arrays from string constants
1173: since the full length of the string constant might not be wanted.
1174: It is also needed for initialization of unions, where the initializer's
1175: type is just one member, and that may not be as long as the union.
1176:
1177: There a case in which we would fail to output exactly SIZE bytes:
1178: for a structure constructor that wants to produce more than SIZE bytes.
1179: But such constructors will never be generated for any possible input. */
1180:
1181: void
1182: output_constant (exp, size)
1183: register tree exp;
1184: register int size;
1185: {
1186: register enum tree_code code = TREE_CODE (TREE_TYPE (exp));
1187: rtx x;
1188:
1189: if (size == 0)
1190: return;
1191:
1192: switch (code)
1193: {
1194: case INTEGER_TYPE:
1195: case ENUMERAL_TYPE:
1196: case POINTER_TYPE:
1197: x = expand_expr (exp, 0, VOIDmode, EXPAND_SUM);
1198:
1199: if (size == 1)
1200: {
1201: ASM_OUTPUT_CHAR (asm_out_file, x);
1202: size -= 1;
1203: }
1204: else if (size == 2)
1205: {
1206: ASM_OUTPUT_SHORT (asm_out_file, x);
1207: size -= 2;
1208: }
1209: else if (size == 4)
1210: {
1211: ASM_OUTPUT_INT (asm_out_file, x);
1212: size -= 4;
1213: }
1214: else
1215: abort ();
1216:
1217: break;
1218:
1219: case REAL_TYPE:
1220: if (TREE_CODE (exp) != REAL_CST)
1221: error ("initializer for floating value is not a floating constant");
1222:
1223: if (size < 4)
1224: break;
1225: else if (size < 8)
1226: {
1227: ASM_OUTPUT_FLOAT (asm_out_file, TREE_REAL_CST (exp));
1228: size -= 4;
1229: }
1230: else
1231: {
1232: ASM_OUTPUT_DOUBLE (asm_out_file, TREE_REAL_CST (exp));
1233: size -= 8;
1234: }
1235: break;
1236:
1237: case COMPLEX_TYPE:
1238: output_constant (TREE_REALPART (exp), size / 2);
1239: output_constant (TREE_IMAGPART (exp), size / 2);
1240: size -= (size / 2) * 2;
1241: break;
1242:
1243: case ARRAY_TYPE:
1244: if (TREE_CODE (exp) == CONSTRUCTOR)
1245: {
1246: output_constructor (exp, size);
1247: return;
1248: }
1249: else if (TREE_CODE (exp) == STRING_CST)
1250: {
1251: register int i;
1252: register unsigned char *p
1253: = (unsigned char *) TREE_STRING_POINTER (exp);
1254: int excess = 0;
1255:
1256: if (size > TREE_STRING_LENGTH (exp))
1257: {
1258: excess = size - TREE_STRING_LENGTH (exp);
1259: size = TREE_STRING_LENGTH (exp);
1260: }
1261:
1262: #ifdef ASM_OUTPUT_ASCII
1263: ASM_OUTPUT_ASCII (asm_out_file, p, size);
1264: #else
1265: fprintf (asm_out_file, "\t.ascii \"");
1266:
1267: for (i = 0; i < size; i++)
1268: {
1269: register int c = p[i];
1270: if (c == '\"' || c == '\\')
1271: putc ('\\', asm_out_file);
1272: if (c >= ' ' && c < 0177)
1273: putc (c, asm_out_file);
1274: else
1275: {
1276: fprintf (asm_out_file, "\\%o", c);
1277: /* After an octal-escape, if a digit follows,
1278: terminate one string constant and start another.
1279: The Vax assembler fails to stop reading the escape
1280: after three digits, so this is the only way we
1281: can get it to parse the data properly. */
1282: if (i < size - 1 && p[i + 1] >= '0' && p[i + 1] <= '9')
1283: fprintf (asm_out_file, "\"\n\t.ascii \"");
1284: }
1285: }
1286: fprintf (asm_out_file, "\"\n");
1287: #endif /* no ASM_OUTPUT_ASCII */
1288:
1289: size = excess;
1290: }
1291: else
1292: abort ();
1293: break;
1294:
1295: case RECORD_TYPE:
1296: case UNION_TYPE:
1297: if (TREE_CODE (exp) == CONSTRUCTOR)
1298: output_constructor (exp, size);
1299: else
1300: abort ();
1301: return;
1302: }
1303:
1304: if (size > 0)
1305: ASM_OUTPUT_SKIP (asm_out_file, size);
1306: }
1307:
1308: /* Subroutine of output_constant, used for CONSTRUCTORs
1309: (aggregate constants).
1310: Generate at least SIZE bytes, padding if necessary. */
1311:
1312: void
1313: output_constructor (exp, size)
1314: tree exp;
1315: int size;
1316: {
1317: register tree link, field = 0;
1318: register int byte;
1319: int total_bytes = 0;
1320: int byte_offset = -1;
1321:
1322: if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1323: || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)
1324: field = TYPE_FIELDS (TREE_TYPE (exp));
1325:
1326: /* As LINK goes through the elements of the constant,
1327: FIELD goes through the structure fields, if the constant is a structure.
1328: But the constant could also be an array. Then FIELD is zero. */
1329: for (link = CONSTRUCTOR_ELTS (exp);
1330: link;
1331: link = TREE_CHAIN (link),
1332: field = field ? TREE_CHAIN (field) : 0)
1333: {
1334: if (field == 0
1335: || (DECL_MODE (field) != BImode))
1336: {
1337: register int fieldsize;
1338:
1339: /* An element that is not a bit-field.
1340: Output any buffered-up bit-fields preceding it. */
1341: if (byte_offset >= 0)
1342: {
1343: ASM_OUTPUT_BYTE (asm_out_file, byte);
1344: total_bytes++;
1345: byte_offset = -1;
1346: }
1347:
1348: /* Align to this element's alignment,
1349: if it isn't aligned properly by its predecessors. */
1350: if (field && (total_bytes * BITS_PER_UNIT) % DECL_ALIGN (field) != 0)
1351: {
1352: int byte_align = DECL_ALIGN (field) / BITS_PER_UNIT;
1353: int to_byte = (((total_bytes + byte_align - 1) / byte_align)
1354: * byte_align);
1355: ASM_OUTPUT_SKIP (asm_out_file, to_byte - total_bytes);
1356: total_bytes = to_byte;
1357: }
1358:
1359: /* Output the element's initial value. */
1360: if (field)
1361: {
1362: if (! TREE_LITERAL (DECL_SIZE (field)))
1363: abort ();
1364: fieldsize = TREE_INT_CST_LOW (DECL_SIZE (field))
1365: * DECL_SIZE_UNIT (field);
1366: fieldsize = (fieldsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT;
1367: }
1368: else
1369: fieldsize = int_size_in_bytes (TREE_TYPE (TREE_TYPE (exp)));
1370:
1371: output_constant (TREE_VALUE (link), fieldsize);
1372:
1373: /* Count its size. */
1374: total_bytes += fieldsize;
1375: }
1376: else if (TREE_CODE (TREE_VALUE (link)) != INTEGER_CST)
1377: error ("invalid initial value for member `%s'",
1378: IDENTIFIER_POINTER (DECL_NAME (field)));
1379: else
1380: {
1381: /* Element that is a bit-field. */
1382:
1383: int next_offset = DECL_OFFSET (field);
1384: int end_offset
1385: = (next_offset
1386: + (TREE_INT_CST_LOW (DECL_SIZE (field))
1387: * DECL_SIZE_UNIT (field)));
1388:
1389: /* We must split the element into pieces that fall within
1390: separate bytes, and combine each byte with previous or
1391: following bit-fields. */
1392:
1393: /* next_offset is the offset n fbits from the begining of
1394: the structure to the next bit of this element to be processed.
1395: end_offset is the offset of the first bit past the end of
1396: this element. */
1397: while (next_offset < end_offset)
1398: {
1399: int this_time;
1400: int next_byte = next_offset / BITS_PER_UNIT;
1401: int next_bit = next_offset % BITS_PER_UNIT;
1402: if (byte_offset < 0)
1403: {
1404: byte_offset = next_byte;
1405: byte = 0;
1406: }
1407: else
1408: while (next_byte != byte_offset)
1409: {
1410: ASM_OUTPUT_BYTE (asm_out_file, byte);
1411: byte_offset++;
1412: total_bytes++;
1413: byte = 0;
1414: }
1415: /* Number of bits we can process at once
1416: (all part of the same byte). */
1417: this_time = MIN (end_offset - next_offset,
1418: BITS_PER_UNIT - next_bit);
1419: #ifdef BYTES_BIG_ENDIAN
1420: /* On big-endian machine, take the most significant bits
1421: first (of the bits that are significant)
1422: and put them into bytes from the most significant end. */
1423: byte |= (((TREE_INT_CST_LOW (TREE_VALUE (link))
1424: >> (end_offset - next_offset - this_time))
1425: & ((1 << this_time) - 1))
1426: << (BITS_PER_UNIT - this_time - next_bit));
1427: #else
1428: /* On little-endian machines,
1429: take first the least significant bits of the value
1430: and pack them starting at the least significant
1431: bits of the bytes. */
1432: byte |= ((TREE_INT_CST_LOW (TREE_VALUE (link))
1433: >> (next_offset - DECL_OFFSET (field)))
1434: & ((1 << this_time) - 1)) << next_bit;
1435: #endif
1436: next_offset += this_time;
1437: }
1438: }
1439: }
1440: if (byte_offset >= 0)
1441: {
1442: ASM_OUTPUT_BYTE (asm_out_file, byte);
1443: byte_offset = -1;
1444: total_bytes++;
1445: }
1446: if (total_bytes < size)
1447: ASM_OUTPUT_SKIP (asm_out_file, size - total_bytes);
1448: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.