OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gcc-4.5.1/] [gcc/] [lto-section-out.c] - Blame information for rev 816

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 280 jeremybenn
/* Functions for writing LTO sections.
2
 
3
   Copyright (C) 2009 Free Software Foundation, Inc.
4
   Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify it under
9
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 3, or (at your option) any later
11
version.
12
 
13
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING3.  If not see
20
<http://www.gnu.org/licenses/>.  */
21
 
22
#include "config.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tm.h"
26
#include "toplev.h"
27
#include "tree.h"
28
#include "expr.h"
29
#include "params.h"
30
#include "input.h"
31
#include "varray.h"
32
#include "hashtab.h"
33
#include "basic-block.h"
34
#include "tree-flow.h"
35
#include "tree-pass.h"
36
#include "cgraph.h"
37
#include "function.h"
38
#include "ggc.h"
39
#include "except.h"
40
#include "vec.h"
41
#include "pointer-set.h"
42
#include "bitmap.h"
43
#include "langhooks.h"
44
#include "lto-streamer.h"
45
#include "lto-compress.h"
46
 
47
static VEC(lto_out_decl_state_ptr, heap) *decl_state_stack;
48
 
49
/* List of out decl states used by functions.  We use this to
50
   generate the decl directory later. */
51
 
52
VEC(lto_out_decl_state_ptr, heap) *lto_function_decl_states;
53
 
54
/* Bitmap indexed by DECL_UID to indicate if a function needs to be
55
   forced extern inline. */
56
static bitmap forced_extern_inline;
57
 
58
/* Initialize states for determining which function decls to be ouput
59
   as extern inline, regardless of the decls' own attributes.  */
60
 
61
void
62
lto_new_extern_inline_states (void)
63
{
64
  forced_extern_inline = lto_bitmap_alloc ();
65
}
66
 
67
/* Releasing resources use for states to determine which function decls
68
   to be ouput as extern inline */
69
 
70
void
71
lto_delete_extern_inline_states (void)
72
{
73
  lto_bitmap_free (forced_extern_inline);
74
  forced_extern_inline = NULL;
75
}
76
 
77
/* Force all the functions in DECLS to be output as extern inline.
78
   DECLS is a bitmap indexed by DECL_UID. */
79
 
80
void
81
lto_force_functions_extern_inline (bitmap decls)
82
{
83
  bitmap_ior_into (forced_extern_inline, decls);
84
}
85
 
86
/* Return true if FN_DECL is a function which should be emitted as
87
   extern inline.  */
88
 
89
bool
90
lto_forced_extern_inline_p (tree fn_decl)
91
{
92
  return bitmap_bit_p (forced_extern_inline, DECL_UID (fn_decl));
93
}
94
 
95
/* Returns a hash code for P.  */
96
 
97
hashval_t
98
lto_hash_decl_slot_node (const void *p)
99
{
100
  const struct lto_decl_slot *ds = (const struct lto_decl_slot *) p;
101
 
102
  /*
103
    return (hashval_t) DECL_UID (ds->t);
104
  */
105
  return (hashval_t) TREE_HASH (ds->t);
106
}
107
 
108
 
109
/* Returns nonzero if P1 and P2 are equal.  */
110
 
111
int
112
lto_eq_decl_slot_node (const void *p1, const void *p2)
113
{
114
  const struct lto_decl_slot *ds1 =
115
    (const struct lto_decl_slot *) p1;
116
  const struct lto_decl_slot *ds2 =
117
    (const struct lto_decl_slot *) p2;
118
 
119
  /*
120
  return DECL_UID (ds1->t) == DECL_UID (ds2->t);
121
  */
122
  return ds1->t == ds2->t;
123
}
124
 
125
 
126
/* Returns a hash code for P.  */
127
 
128
hashval_t
129
lto_hash_type_slot_node (const void *p)
130
{
131
  const struct lto_decl_slot *ds = (const struct lto_decl_slot *) p;
132
  return (hashval_t) TYPE_UID (ds->t);
133
}
134
 
135
 
136
/* Returns nonzero if P1 and P2 are equal.  */
137
 
138
int
139
lto_eq_type_slot_node (const void *p1, const void *p2)
140
{
141
  const struct lto_decl_slot *ds1 =
142
    (const struct lto_decl_slot *) p1;
143
  const struct lto_decl_slot *ds2 =
144
    (const struct lto_decl_slot *) p2;
145
 
146
  return TYPE_UID (ds1->t) == TYPE_UID (ds2->t);
147
}
148
 
149
/*****************************************************************************
150
   Output routines shared by all of the serialization passes.
151
*****************************************************************************/
152
 
153
 
154
/* Flush compressed stream data function, sends NUM_CHARS from CHARS
155
   to the append lang hook, OPAQUE is currently always NULL.  */
156
 
157
static void
158
lto_append_data (const char *chars, unsigned int num_chars, void *opaque)
159
{
160
  gcc_assert (opaque == NULL);
161
  lang_hooks.lto.append_data (chars, num_chars, opaque);
162
}
163
 
164
/* Pointer to the current compression stream.  */
165
 
166
static struct lto_compression_stream *compression_stream = NULL;
167
 
168
/* Begin a new output section named NAME. If COMPRESS is true, zlib compress
169
   the section. */
170
 
171
void
172
lto_begin_section (const char *name, bool compress)
173
{
174
  lang_hooks.lto.begin_section (name);
175
 
176
  /* FIXME lto: for now, suppress compression if the lang_hook that appends
177
     data is anything other than assembler output.  The effect here is that
178
     we get compression of IL only in non-ltrans object files.  */
179
  gcc_assert (compression_stream == NULL);
180
  if (compress)
181
    compression_stream = lto_start_compression (lto_append_data, NULL);
182
}
183
 
184
 
185
/* End the current output section.  */
186
 
187
void
188
lto_end_section (void)
189
{
190
  if (compression_stream)
191
    {
192
      lto_end_compression (compression_stream);
193
      compression_stream = NULL;
194
    }
195
  lang_hooks.lto.end_section ();
196
}
197
 
198
 
199
/* Write all of the chars in OBS to the assembler.  Recycle the blocks
200
   in obs as this is being done.  */
201
 
202
void
203
lto_write_stream (struct lto_output_stream *obs)
204
{
205
  unsigned int block_size = 1024;
206
  struct lto_char_ptr_base *block;
207
  struct lto_char_ptr_base *next_block;
208
  if (!obs->first_block)
209
    return;
210
 
211
  for (block = obs->first_block; block; block = next_block)
212
    {
213
      const char *base = ((char *)block) + sizeof (struct lto_char_ptr_base);
214
      unsigned int num_chars = block_size - sizeof (struct lto_char_ptr_base);
215
 
216
      /* If this is not the last block, it is full.  If it is the last
217
         block, left_in_block indicates how many chars are unoccupied in
218
         this block; subtract from num_chars to obtain occupancy.  */
219
      next_block = (struct lto_char_ptr_base *) block->ptr;
220
      if (!next_block)
221
        num_chars -= obs->left_in_block;
222
 
223
      /* FIXME lto: WPA mode uses an ELF function as a lang_hook to append
224
         output data.  This hook is not happy with the way that compression
225
         blocks up output differently to the way it's blocked here.  So for
226
         now, we don't compress WPA output.  */
227
      if (compression_stream)
228
        {
229
          lto_compress_block (compression_stream, base, num_chars);
230
          lang_hooks.lto.append_data (NULL, 0, block);
231
        }
232
      else
233
        lang_hooks.lto.append_data (base, num_chars, block);
234
      block_size *= 2;
235
    }
236
}
237
 
238
 
239
/* Adds a new block to output stream OBS.  */
240
 
241
static void
242
append_block (struct lto_output_stream *obs)
243
{
244
  struct lto_char_ptr_base *new_block;
245
 
246
  gcc_assert (obs->left_in_block == 0);
247
 
248
  if (obs->first_block == NULL)
249
    {
250
      /* This is the first time the stream has been written
251
         into.  */
252
      obs->block_size = 1024;
253
      new_block = (struct lto_char_ptr_base*) xmalloc (obs->block_size);
254
      obs->first_block = new_block;
255
    }
256
  else
257
    {
258
      struct lto_char_ptr_base *tptr;
259
      /* Get a new block that is twice as big as the last block
260
         and link it into the list.  */
261
      obs->block_size *= 2;
262
      new_block = (struct lto_char_ptr_base*) xmalloc (obs->block_size);
263
      /* The first bytes of the block are reserved as a pointer to
264
         the next block.  Set the chain of the full block to the
265
         pointer to the new block.  */
266
      tptr = obs->current_block;
267
      tptr->ptr = (char *) new_block;
268
    }
269
 
270
  /* Set the place for the next char at the first position after the
271
     chain to the next block.  */
272
  obs->current_pointer
273
    = ((char *) new_block) + sizeof (struct lto_char_ptr_base);
274
  obs->current_block = new_block;
275
  /* Null out the newly allocated block's pointer to the next block.  */
276
  new_block->ptr = NULL;
277
  obs->left_in_block = obs->block_size - sizeof (struct lto_char_ptr_base);
278
}
279
 
280
 
281
/* Write a character to the output block.  */
282
 
283
void
284
lto_output_1_stream (struct lto_output_stream *obs, char c)
285
{
286
  /* No space left.  */
287
  if (obs->left_in_block == 0)
288
    append_block (obs);
289
 
290
  /* Write the actual character.  */
291
  *obs->current_pointer = c;
292
  obs->current_pointer++;
293
  obs->total_size++;
294
  obs->left_in_block--;
295
}
296
 
297
 
298
/* Write raw DATA of length LEN to the output block OB.  */
299
 
300
void
301
lto_output_data_stream (struct lto_output_stream *obs, const void *data,
302
                        size_t len)
303
{
304
  while (len)
305
    {
306
      size_t copy;
307
 
308
      /* No space left.  */
309
      if (obs->left_in_block == 0)
310
        append_block (obs);
311
 
312
      /* Determine how many bytes to copy in this loop.  */
313
      if (len <= obs->left_in_block)
314
        copy = len;
315
      else
316
        copy = obs->left_in_block;
317
 
318
      /* Copy the data and do bookkeeping.  */
319
      memcpy (obs->current_pointer, data, copy);
320
      obs->current_pointer += copy;
321
      obs->total_size += copy;
322
      obs->left_in_block -= copy;
323
      data = (const char *) data + copy;
324
      len -= copy;
325
    }
326
}
327
 
328
 
329
/* Output an unsigned LEB128 quantity to OBS.  */
330
 
331
void
332
lto_output_uleb128_stream (struct lto_output_stream *obs,
333
                           unsigned HOST_WIDE_INT work)
334
{
335
  do
336
    {
337
      unsigned int byte = (work & 0x7f);
338
      work >>= 7;
339
      if (work != 0)
340
        /* More bytes to follow.  */
341
        byte |= 0x80;
342
 
343
      lto_output_1_stream (obs, byte);
344
    }
345
  while (work != 0);
346
}
347
 
348
/* Identical to output_uleb128_stream above except using unsigned
349
   HOST_WIDEST_INT type.  For efficiency on host where unsigned HOST_WIDEST_INT
350
   is not native, we only use this if we know that HOST_WIDE_INT is not wide
351
   enough.  */
352
 
353
void
354
lto_output_widest_uint_uleb128_stream (struct lto_output_stream *obs,
355
                                       unsigned HOST_WIDEST_INT work)
356
{
357
  do
358
    {
359
      unsigned int byte = (work & 0x7f);
360
      work >>= 7;
361
      if (work != 0)
362
        /* More bytes to follow.  */
363
        byte |= 0x80;
364
 
365
      lto_output_1_stream (obs, byte);
366
    }
367
  while (work != 0);
368
}
369
 
370
 
371
/* Output a signed LEB128 quantity.  */
372
 
373
void
374
lto_output_sleb128_stream (struct lto_output_stream *obs, HOST_WIDE_INT work)
375
{
376
  int more, byte;
377
 
378
  do
379
    {
380
      byte = (work & 0x7f);
381
      /* arithmetic shift */
382
      work >>= 7;
383
      more = !((work == 0 && (byte & 0x40) == 0)
384
               || (work == -1 && (byte & 0x40) != 0));
385
      if (more)
386
        byte |= 0x80;
387
 
388
      lto_output_1_stream (obs, byte);
389
    }
390
  while (more);
391
}
392
 
393
 
394
/* Lookup NAME in ENCODER.  If NAME is not found, create a new entry in
395
   ENCODER for NAME with the next available index of ENCODER,  then
396
   print the index to OBS.  True is returned if NAME was added to
397
   ENCODER.  The resulting index is stored in THIS_INDEX.
398
 
399
   If OBS is NULL, the only action is to add NAME to the encoder. */
400
 
401
bool
402
lto_output_decl_index (struct lto_output_stream *obs,
403
                       struct lto_tree_ref_encoder *encoder,
404
                       tree name, unsigned int *this_index)
405
{
406
  void **slot;
407
  struct lto_decl_slot d_slot;
408
  int index;
409
  bool new_entry_p = FALSE;
410
 
411
  d_slot.t = name;
412
  slot = htab_find_slot (encoder->tree_hash_table, &d_slot, INSERT);
413
  if (*slot == NULL)
414
    {
415
      struct lto_decl_slot *new_slot
416
        = (struct lto_decl_slot *) xmalloc (sizeof (struct lto_decl_slot));
417
      index = encoder->next_index++;
418
 
419
      new_slot->t = name;
420
      new_slot->slot_num = index;
421
      *slot = new_slot;
422
      VEC_safe_push (tree, heap, encoder->trees, name);
423
      new_entry_p = TRUE;
424
    }
425
  else
426
    {
427
      struct lto_decl_slot *old_slot = (struct lto_decl_slot *)*slot;
428
      index = old_slot->slot_num;
429
    }
430
 
431
  if (obs)
432
    lto_output_uleb128_stream (obs, index);
433
  *this_index = index;
434
  return new_entry_p;
435
}
436
 
437
/* Output a field DECL to OBS.  */
438
 
439
void
440
lto_output_field_decl_index (struct lto_out_decl_state *decl_state,
441
                             struct lto_output_stream * obs, tree decl)
442
{
443
  unsigned int index;
444
  lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_FIELD_DECL],
445
                         decl, &index);
446
}
447
 
448
/* Output a function DECL to OBS.  */
449
 
450
void
451
lto_output_fn_decl_index (struct lto_out_decl_state *decl_state,
452
                          struct lto_output_stream * obs, tree decl)
453
{
454
  unsigned int index;
455
  lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_FN_DECL],
456
                         decl, &index);
457
}
458
 
459
/* Output a namespace DECL to OBS.  */
460
 
461
void
462
lto_output_namespace_decl_index (struct lto_out_decl_state *decl_state,
463
                                 struct lto_output_stream * obs, tree decl)
464
{
465
  unsigned int index;
466
  lto_output_decl_index (obs,
467
                         &decl_state->streams[LTO_DECL_STREAM_NAMESPACE_DECL],
468
                         decl, &index);
469
}
470
 
471
/* Output a static or extern var DECL to OBS.  */
472
 
473
void
474
lto_output_var_decl_index (struct lto_out_decl_state *decl_state,
475
                           struct lto_output_stream * obs, tree decl)
476
{
477
  unsigned int index;
478
  lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_VAR_DECL],
479
                         decl, &index);
480
}
481
 
482
/* Output a type DECL to OBS.  */
483
 
484
void
485
lto_output_type_decl_index (struct lto_out_decl_state *decl_state,
486
                            struct lto_output_stream * obs, tree decl)
487
{
488
  unsigned int index;
489
  lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_TYPE_DECL],
490
                         decl, &index);
491
}
492
 
493
/* Output a type REF to OBS.  */
494
 
495
void
496
lto_output_type_ref_index (struct lto_out_decl_state *decl_state,
497
                           struct lto_output_stream *obs, tree ref)
498
{
499
  unsigned int index;
500
  lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_TYPE],
501
                         ref, &index);
502
}
503
 
504
 
505
/* Create the output block and return it.  */
506
 
507
struct lto_simple_output_block *
508
lto_create_simple_output_block (enum lto_section_type section_type)
509
{
510
  struct lto_simple_output_block *ob
511
    = ((struct lto_simple_output_block *)
512
       xcalloc (1, sizeof (struct lto_simple_output_block)));
513
 
514
  ob->section_type = section_type;
515
  ob->decl_state = lto_get_out_decl_state ();
516
  ob->main_stream = ((struct lto_output_stream *)
517
                     xcalloc (1, sizeof (struct lto_output_stream)));
518
 
519
  return ob;
520
}
521
 
522
 
523
/* Produce a simple section for one of the ipa passes.  */
524
 
525
void
526
lto_destroy_simple_output_block (struct lto_simple_output_block *ob)
527
{
528
  char *section_name;
529
  struct lto_simple_header header;
530
  struct lto_output_stream *header_stream;
531
 
532
  section_name = lto_get_section_name (ob->section_type, NULL);
533
  lto_begin_section (section_name, !flag_wpa);
534
  free (section_name);
535
 
536
  /* Write the header which says how to decode the pieces of the
537
     t.  */
538
  memset (&header, 0, sizeof (struct lto_simple_header));
539
  header.lto_header.major_version = LTO_major_version;
540
  header.lto_header.minor_version = LTO_minor_version;
541
  header.lto_header.section_type = LTO_section_cgraph;
542
 
543
  header.compressed_size = 0;
544
 
545
  header.main_size = ob->main_stream->total_size;
546
 
547
  header_stream = XCNEW (struct lto_output_stream);
548
  lto_output_data_stream (header_stream, &header, sizeof header);
549
  lto_write_stream (header_stream);
550
  free (header_stream);
551
 
552
  lto_write_stream (ob->main_stream);
553
 
554
  /* Put back the assembly section that was there before we started
555
     writing lto info.  */
556
  lto_end_section ();
557
 
558
  free (ob->main_stream);
559
  free (ob);
560
}
561
 
562
 
563
/* Return a new lto_out_decl_state. */
564
 
565
struct lto_out_decl_state *
566
lto_new_out_decl_state (void)
567
{
568
  struct lto_out_decl_state *state = XCNEW (struct lto_out_decl_state);
569
  int i;
570
  htab_hash hash_fn;
571
  htab_eq eq_fn;
572
 
573
  for (i = 0; i < LTO_N_DECL_STREAMS; i++)
574
    {
575
      if (i == LTO_DECL_STREAM_TYPE)
576
        {
577
          hash_fn = lto_hash_type_slot_node;
578
          eq_fn = lto_eq_type_slot_node;
579
        }
580
      else
581
        {
582
          hash_fn = lto_hash_decl_slot_node;
583
          eq_fn = lto_eq_decl_slot_node;
584
        }
585
      lto_init_tree_ref_encoder (&state->streams[i], hash_fn, eq_fn);
586
    }
587
 
588
  state->cgraph_node_encoder = lto_cgraph_encoder_new ();
589
 
590
  return state;
591
}
592
 
593
 
594
/* Delete STATE and components.  */
595
 
596
void
597
lto_delete_out_decl_state (struct lto_out_decl_state *state)
598
{
599
  int i;
600
 
601
  for (i = 0; i < LTO_N_DECL_STREAMS; i++)
602
    lto_destroy_tree_ref_encoder (&state->streams[i]);
603
 
604
  free (state);
605
}
606
 
607
 
608
/* Get the currently used lto_out_decl_state structure. */
609
 
610
struct lto_out_decl_state *
611
lto_get_out_decl_state (void)
612
{
613
  return VEC_last (lto_out_decl_state_ptr, decl_state_stack);
614
}
615
 
616
/* Push STATE to top of out decl stack. */
617
 
618
void
619
lto_push_out_decl_state (struct lto_out_decl_state *state)
620
{
621
  VEC_safe_push (lto_out_decl_state_ptr, heap, decl_state_stack, state);
622
}
623
 
624
/* Pop the currently used out-decl state from top of stack. */
625
 
626
struct lto_out_decl_state *
627
lto_pop_out_decl_state (void)
628
{
629
  return VEC_pop (lto_out_decl_state_ptr, decl_state_stack);
630
}
631
 
632
/* Record STATE after it has been used in serializing the body of
633
   FN_DECL.  STATE should no longer be used by the caller.  The ownership
634
   of it is taken over from this point.  */
635
 
636
void
637
lto_record_function_out_decl_state (tree fn_decl,
638
                                    struct lto_out_decl_state *state)
639
{
640
  int i;
641
 
642
  /* Strip all hash tables to save some memory. */
643
  for (i = 0; i < LTO_N_DECL_STREAMS; i++)
644
    if (state->streams[i].tree_hash_table)
645
      {
646
        htab_delete (state->streams[i].tree_hash_table);
647
        state->streams[i].tree_hash_table = NULL;
648
      }
649
  state->fn_decl = fn_decl;
650
  VEC_safe_push (lto_out_decl_state_ptr, heap, lto_function_decl_states,
651
                 state);
652
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.