* config/sh/tm-sh.h (BELIEVE_PCC_PROMOTION): Define, so that
[deliverable/binutils-gdb.git] / gas / subsegs.c
CommitLineData
fecd2382 1/* subsegs.c - subsegments -
cc886e3d
SS
2 Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
3 Free Software Foundation, Inc.
604633ae 4
a39116f1 5 This file is part of GAS, the GNU Assembler.
604633ae 6
a39116f1
RP
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
604633ae 11
a39116f1
RP
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
604633ae 16
a39116f1
RP
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
1356d77d 19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
fecd2382
RP
20
21/*
22 * Segments & sub-segments.
23 */
24
25#include "as.h"
26
27#include "subsegs.h"
28#include "obstack.h"
29
604633ae
ILT
30frchainS *frchain_root, *frchain_now;
31
d19dcb67
KR
32static struct obstack frchains;
33
604633ae 34#ifndef BFD_ASSEMBLER
a39116f1
RP
35#ifdef MANY_SEGMENTS
36segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
37
a39116f1 38#else
604633ae
ILT
39/* Commented in "subsegs.h". */
40frchainS *data0_frchainP, *bss0_frchainP;
fecd2382 41
604633ae 42#endif /* MANY_SEGMENTS */
1356d77d 43char const *const seg_name[] =
604633ae
ILT
44{
45 "absolute",
a39116f1 46#ifdef MANY_SEGMENTS
604633ae 47 "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
a39116f1 48#else
604633ae
ILT
49 "text",
50 "data",
51 "bss",
52#endif /* MANY_SEGMENTS */
53 "unknown",
54 "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
55 "expr",
56 "debug",
57 "transfert vector preload",
58 "transfert vector postload",
59 "register",
60 "",
61}; /* Used by error reporters, dumpers etc. */
dff770c8
ILT
62#else /* BFD_ASSEMBLER */
63
64/* Gas segment information for bfd_abs_section_ptr and
65 bfd_und_section_ptr. */
66static segment_info_type *abs_seg_info;
67static segment_info_type *und_seg_info;
68
604633ae 69#endif /* BFD_ASSEMBLER */
fecd2382 70
604633ae 71static void subseg_set_rest PARAMS ((segT, subsegT));
d19dcb67
KR
72
73static fragS dummy_frag;
74
75static frchainS absolute_frchain;
fecd2382
RP
76\f
77void
604633ae 78subsegs_begin ()
fecd2382 79{
604633ae
ILT
80 /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
81#if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
82 know (SEG_ABSOLUTE == 0);
83 know (SEG_TEXT == 1);
84 know (SEG_DATA == 2);
85 know (SEG_BSS == 3);
86 know (SEG_UNKNOWN == 4);
87 know (SEG_GOOF == 5);
88 know (SEG_EXPR == 6);
89 know (SEG_DEBUG == 7);
90 know (SEG_NTV == 8);
91 know (SEG_PTV == 9);
92 know (SEG_REGISTER == 10);
93 know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
a39116f1 94#endif
604633ae 95
d19dcb67
KR
96 obstack_begin (&frchains, chunksize);
97#if __GNUC__ >= 2
98 obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
99#endif
100
604633ae
ILT
101 frchain_root = NULL;
102 frchain_now = NULL; /* Warn new_subseg() that we are booting. */
d19dcb67
KR
103
104 frag_now = &dummy_frag;
604633ae
ILT
105
106#ifndef BFD_ASSEMBLER
604633ae 107 now_subseg = 42; /* Lie for 1st call to subseg_new. */
a39116f1 108#ifdef MANY_SEGMENTS
604633ae
ILT
109 {
110 int i;
111 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
112 {
113 subseg_set (i, 0);
114 segment_info[i].frchainP = frchain_now;
115 }
116 }
a39116f1 117#else
604633ae
ILT
118 subseg_set (SEG_DATA, 0); /* .data 0 */
119 data0_frchainP = frchain_now;
65bfcf2e 120
604633ae
ILT
121 subseg_set (SEG_BSS, 0);
122 bss0_frchainP = frchain_now;
123
124#endif /* ! MANY_SEGMENTS */
125#endif /* ! BFD_ASSEMBLER */
65bfcf2e 126
d19dcb67
KR
127 absolute_frchain.frch_seg = absolute_section;
128 absolute_frchain.frch_subseg = 0;
129 absolute_frchain.fix_root = absolute_frchain.fix_tail = 0;
130 absolute_frchain.frch_frag_now = &zero_address_frag;
131 absolute_frchain.frch_root = absolute_frchain.frch_last = &zero_address_frag;
fecd2382
RP
132}
133\f
134/*
135 * subseg_change()
136 *
137 * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
138 * subsegment. If we are already in the correct subsegment, change nothing.
604633ae 139 * This is used eg as a worker for subseg_set [which does make a new frag_now]
fecd2382
RP
140 * and for changing segments after we have read the source. We construct eg
141 * fixSs even after the source file is read, so we do have to keep the
142 * segment context correct.
143 */
144void
604633ae
ILT
145subseg_change (seg, subseg)
146 register segT seg;
147 register int subseg;
fecd2382 148{
604633ae
ILT
149 now_seg = seg;
150 now_subseg = subseg;
151
d19dcb67
KR
152 if (now_seg == absolute_section)
153 return;
154
604633ae
ILT
155#ifdef BFD_ASSEMBLER
156 {
157 segment_info_type *seginfo;
158 seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
159 if (! seginfo)
160 {
161 seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
3c498933 162 memset ((PTR) seginfo, 0, sizeof (*seginfo));
dff770c8
ILT
163 seginfo->fix_root = NULL;
164 seginfo->fix_tail = NULL;
604633ae
ILT
165 seginfo->bfd_section = seg;
166 seginfo->sym = 0;
dff770c8
ILT
167 if (seg == bfd_abs_section_ptr)
168 abs_seg_info = seginfo;
169 else if (seg == bfd_und_section_ptr)
170 und_seg_info = seginfo;
171 else
172 bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
604633ae
ILT
173 }
174 }
175#else
a39116f1 176#ifdef MANY_SEGMENTS
604633ae
ILT
177 seg_fix_rootP = &segment_info[seg].fix_root;
178 seg_fix_tailP = &segment_info[seg].fix_tail;
a39116f1 179#else
604633ae
ILT
180 if (seg == SEG_DATA)
181 {
182 seg_fix_rootP = &data_fix_root;
183 seg_fix_tailP = &data_fix_tail;
184 }
185 else if (seg == SEG_TEXT)
186 {
187 seg_fix_rootP = &text_fix_root;
188 seg_fix_tailP = &text_fix_tail;
189 }
190 else
191 {
192 know (seg == SEG_BSS);
193 seg_fix_rootP = &bss_fix_root;
194 seg_fix_tailP = &bss_fix_tail;
195 }
196
197#endif
a39116f1 198#endif
fecd2382
RP
199}
200\f
604633ae
ILT
201static void
202subseg_set_rest (seg, subseg)
203 segT seg;
204 subsegT subseg;
205{
206 long tmp; /* JF for obstack alignment hacking */
207 register frchainS *frcP; /* crawl frchain chain */
208 register frchainS **lastPP; /* address of last pointer */
209 frchainS *newP; /* address of new frchain */
210 register fragS *former_last_fragP;
211 register fragS *new_fragP;
212
d19dcb67
KR
213 mri_common_symbol = NULL;
214
215 if (frag_now && frchain_now)
216 frchain_now->frch_frag_now = frag_now;
217
218 assert (frchain_now == 0
219 || now_seg == undefined_section
220 || now_seg == absolute_section
221 || frchain_now->frch_last == frag_now);
222
223 subseg_change (seg, (int) subseg);
224
225 if (seg == absolute_section)
604633ae 226 {
d19dcb67
KR
227 frchain_now = &absolute_frchain;
228 frag_now = &zero_address_frag;
229 return;
604633ae 230 }
d19dcb67
KR
231
232 assert (frchain_now == 0
233 || now_seg == undefined_section
234 || frchain_now->frch_last == frag_now);
235
604633ae
ILT
236 /*
237 * Attempt to find or make a frchain for that sub seg.
238 * Crawl along chain of frchainSs, begins @ frchain_root.
239 * If we need to make a frchainS, link it into correct
240 * position of chain rooted in frchain_root.
241 */
242 for (frcP = *(lastPP = &frchain_root);
3b6d6f71 243 frcP && frcP->frch_seg <= seg;
604633ae
ILT
244 frcP = *(lastPP = &frcP->frch_next))
245 {
3b6d6f71 246 if (frcP->frch_seg == seg
604633ae
ILT
247 && frcP->frch_subseg >= subseg)
248 {
249 break;
250 }
251 }
252 /*
253 * frcP: Address of the 1st frchainS in correct segment with
254 * frch_subseg >= subseg.
255 * We want to either use this frchainS, or we want
256 * to insert a new frchainS just before it.
257 *
258 * If frcP==NULL, then we are at the end of the chain
259 * of frchainS-s. A NULL frcP means we fell off the end
260 * of the chain looking for a
261 * frch_subseg >= subseg, so we
262 * must make a new frchainS.
263 *
264 * If we ever maintain a pointer to
265 * the last frchainS in the chain, we change that pointer
266 * ONLY when frcP==NULL.
267 *
268 * lastPP: Address of the pointer with value frcP;
269 * Never NULL.
270 * May point to frchain_root.
271 *
272 */
273 if (!frcP
3b6d6f71 274 || (frcP->frch_seg > seg
604633ae
ILT
275 || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
276 {
277 /*
278 * This should be the only code that creates a frchainS.
279 */
d19dcb67
KR
280 extern fragS *frag_alloc ();
281 newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
1356d77d 282 newP->frch_subseg = subseg;
604633ae 283 newP->frch_seg = seg;
cc886e3d
SS
284#ifdef BFD_ASSEMBLER
285 newP->fix_root = NULL;
286 newP->fix_tail = NULL;
287#endif
1356d77d 288 obstack_begin (&newP->frch_obstack, 5000);
d19dcb67
KR
289#if __GNUC__ >= 2
290 obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
291#endif
292 newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
293 newP->frch_frag_now->fr_type = rs_fill;
294
295 newP->frch_root = newP->frch_last = newP->frch_frag_now;
1356d77d
ILT
296
297 *lastPP = newP;
298 newP->frch_next = frcP; /* perhaps NULL */
299 frcP = newP;
604633ae
ILT
300 }
301 /*
1356d77d 302 * Here with frcP pointing to the frchainS for subseg.
604633ae
ILT
303 */
304 frchain_now = frcP;
d19dcb67 305 frag_now = frcP->frch_frag_now;
1356d77d 306
d19dcb67 307 assert (frchain_now->frch_last == frag_now);
604633ae
ILT
308}
309
fecd2382 310/*
604633ae 311 * subseg_set(segT, subsegT)
fecd2382
RP
312 *
313 * If you attempt to change to the current subsegment, nothing happens.
314 *
315 * In: segT, subsegT code for new subsegment.
316 * frag_now -> incomplete frag for current subsegment.
317 * If frag_now==NULL, then there is no old, incomplete frag, so
318 * the old frag is not closed off.
319 *
320 * Out: now_subseg, now_seg updated.
321 * Frchain_now points to the (possibly new) struct frchain for this
322 * sub-segment.
323 * Frchain_root updated if needed.
324 */
325
604633ae
ILT
326#ifndef BFD_ASSEMBLER
327
328segT
329subseg_new (segname, subseg)
330 const char *segname;
331 subsegT subseg;
fecd2382 332{
604633ae
ILT
333 int i;
334
335 for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
336 {
337 const char *s;
338
339 s = segment_name ((segT) i);
340 if (strcmp (segname, s) == 0
341 || (segname[0] == '.'
342 && strcmp (segname + 1, s) == 0))
f8701a3f 343 {
604633ae
ILT
344 subseg_set ((segT) i, subseg);
345 return (segT) i;
346 }
347#ifdef obj_segment_name
348 s = obj_segment_name ((segT) i);
349 if (strcmp (segname, s) == 0
350 || (segname[0] == '.'
351 && strcmp (segname + 1, s) == 0))
352 {
353 subseg_set ((segT) i, subseg);
354 return (segT) i;
f8701a3f 355 }
a39116f1 356#endif
604633ae 357 }
fecd2382 358
604633ae
ILT
359#ifdef obj_add_segment
360 {
361 segT new_seg;
362 new_seg = obj_add_segment (segname);
363 subseg_set (new_seg, subseg);
364 return new_seg;
365 }
366#else
367 as_bad ("Attempt to switch to nonexistent segment \"%s\"", segname);
368 return now_seg;
369#endif
370}
371
372void
373subseg_set (seg, subseg) /* begin assembly for a new sub-segment */
374 register segT seg; /* SEG_DATA or SEG_TEXT */
375 register subsegT subseg;
376{
377#ifndef MANY_SEGMENTS
d19dcb67
KR
378 know (seg == SEG_DATA
379 || seg == SEG_TEXT
380 || seg == SEG_BSS
381 || seg == SEG_ABSOLUTE);
604633ae
ILT
382#endif
383
384 if (seg != now_seg || subseg != now_subseg)
385 { /* we just changed sub-segments */
386 subseg_set_rest (seg, subseg);
387 }
1356d77d 388 mri_common_symbol = NULL;
604633ae
ILT
389}
390
391#else /* BFD_ASSEMBLER */
392
393segT
d025bc7b 394subseg_get (segname, force_new)
604633ae 395 const char *segname;
d025bc7b 396 int force_new;
604633ae
ILT
397{
398 segT secptr;
399 segment_info_type *seginfo;
400 const char *now_seg_name = (now_seg
401 ? bfd_get_section_name (stdoutput, now_seg)
402 : 0);
403
d025bc7b
JL
404 if (!force_new
405 && now_seg_name
604633ae 406 && (now_seg_name == segname
d025bc7b 407 || !strcmp (now_seg_name, segname)))
604633ae
ILT
408 return now_seg;
409
d025bc7b
JL
410 if (!force_new)
411 secptr = bfd_make_section_old_way (stdoutput, segname);
412 else
413 secptr = bfd_make_section_anyway (stdoutput, segname);
414
604633ae
ILT
415 seginfo = seg_info (secptr);
416 if (! seginfo)
417 {
dff770c8
ILT
418 /* Check whether output_section is set first because secptr may
419 be bfd_abs_section_ptr. */
420 if (secptr->output_section != secptr)
421 secptr->output_section = secptr;
604633ae 422 seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
3c498933 423 memset ((PTR) seginfo, 0, sizeof (*seginfo));
cc886e3d 424 seginfo->fix_root = NULL;
dff770c8 425 seginfo->fix_tail = NULL;
604633ae 426 seginfo->bfd_section = secptr;
dff770c8
ILT
427 if (secptr == bfd_abs_section_ptr)
428 abs_seg_info = seginfo;
429 else if (secptr == bfd_und_section_ptr)
430 und_seg_info = seginfo;
431 else
432 bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
cc886e3d
SS
433 seginfo->frchainP = NULL;
434 seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
435 seginfo->sym = NULL;
436 seginfo->dot = NULL;
604633ae 437 }
d025bc7b
JL
438 return secptr;
439}
440
441segT
442subseg_new (segname, subseg)
443 const char *segname;
444 subsegT subseg;
445{
446 segT secptr;
447 segment_info_type *seginfo;
448
449 secptr = subseg_get (segname, 0);
450 subseg_set_rest (secptr, subseg);
451 seginfo = seg_info (secptr);
452 if (! seginfo->frchainP)
453 seginfo->frchainP = frchain_now;
454 return secptr;
455}
456
457/* Like subseg_new, except a new section is always created, even if
458 a section with that name already exists. */
459segT
460subseg_force_new (segname, subseg)
461 const char *segname;
462 subsegT subseg;
463{
464 segT secptr;
465 segment_info_type *seginfo;
466
467 secptr = subseg_get (segname, 1);
468 subseg_set_rest (secptr, subseg);
469 seginfo = seg_info (secptr);
470 if (! seginfo->frchainP)
471 seginfo->frchainP = frchain_now;
604633ae
ILT
472 return secptr;
473}
474
475void
476subseg_set (secptr, subseg)
477 segT secptr;
478 subsegT subseg;
479{
480 if (! (secptr == now_seg && subseg == now_subseg))
481 subseg_set_rest (secptr, subseg);
1356d77d 482 mri_common_symbol = NULL;
604633ae
ILT
483}
484
cc886e3d
SS
485#ifndef obj_sec_sym_ok_for_reloc
486#define obj_sec_sym_ok_for_reloc(SEC) 0
487#endif
488
dff770c8
ILT
489/* Get the gas information we are storing for a section. */
490
491segment_info_type *
492seg_info (sec)
493 segT sec;
494{
495 if (sec == bfd_abs_section_ptr)
496 return abs_seg_info;
497 else if (sec == bfd_und_section_ptr)
498 return und_seg_info;
499 else
500 return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
501}
502
d025bc7b
JL
503symbolS *
504section_symbol (sec)
505 segT sec;
506{
507 segment_info_type *seginfo = seg_info (sec);
cc886e3d 508 symbolS *s;
d025bc7b
JL
509
510 if (seginfo == 0)
511 abort ();
512 if (seginfo->sym)
513 return seginfo->sym;
cc886e3d
SS
514 s = symbol_find (sec->name);
515 if (!s)
d025bc7b 516 {
3c498933
KR
517#ifndef EMIT_SECTION_SYMBOLS
518#define EMIT_SECTION_SYMBOLS 1
519#endif
520
1356d77d 521 if (! EMIT_SECTION_SYMBOLS
3c498933
KR
522#ifdef BFD_ASSEMBLER
523 && symbol_table_frozen
524#endif
525 )
1356d77d 526 /* Here we know it won't be going into the symbol table. */
3c498933 527 s = symbol_create (sec->name, sec, 0, &zero_address_frag);
1356d77d
ILT
528 else
529 s = symbol_new (sec->name, sec, 0, &zero_address_frag);
cc886e3d
SS
530 S_CLEAR_EXTERNAL (s);
531
532 /* Use the BFD section symbol, if possible. */
533 if (obj_sec_sym_ok_for_reloc (sec))
534 s->bsym = sec->symbol;
d025bc7b 535 }
cc886e3d
SS
536 seginfo->sym = s;
537 return s;
d025bc7b
JL
538}
539
604633ae 540#endif /* BFD_ASSEMBLER */
fecd2382 541
8b228fe9 542/* end of subsegs.c */
This page took 0.299652 seconds and 4 git commands to generate.