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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [lto-section-out.c] - Blame information for rev 867

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

Line No. Rev Author Line
1 684 jeremybenn
/* Functions for writing LTO sections.
2
 
3
   Copyright (C) 2009, 2010 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 "tree.h"
27
#include "expr.h"
28
#include "params.h"
29
#include "input.h"
30
#include "hashtab.h"
31
#include "basic-block.h"
32
#include "tree-flow.h"
33
#include "tree-pass.h"
34
#include "cgraph.h"
35
#include "function.h"
36
#include "ggc.h"
37
#include "except.h"
38
#include "vec.h"
39
#include "pointer-set.h"
40
#include "bitmap.h"
41
#include "langhooks.h"
42
#include "data-streamer.h"
43
#include "lto-streamer.h"
44
#include "lto-compress.h"
45
 
46
static VEC(lto_out_decl_state_ptr, heap) *decl_state_stack;
47
 
48
/* List of out decl states used by functions.  We use this to
49
   generate the decl directory later. */
50
 
51
VEC(lto_out_decl_state_ptr, heap) *lto_function_decl_states;
52
/* Returns a hash code for P.  */
53
 
54
hashval_t
55
lto_hash_decl_slot_node (const void *p)
56
{
57
  const struct lto_decl_slot *ds = (const struct lto_decl_slot *) p;
58
 
59
  /*
60
    return (hashval_t) DECL_UID (ds->t);
61
  */
62
  return (hashval_t) TREE_HASH (ds->t);
63
}
64
 
65
 
66
/* Returns nonzero if P1 and P2 are equal.  */
67
 
68
int
69
lto_eq_decl_slot_node (const void *p1, const void *p2)
70
{
71
  const struct lto_decl_slot *ds1 =
72
    (const struct lto_decl_slot *) p1;
73
  const struct lto_decl_slot *ds2 =
74
    (const struct lto_decl_slot *) p2;
75
 
76
  /*
77
  return DECL_UID (ds1->t) == DECL_UID (ds2->t);
78
  */
79
  return ds1->t == ds2->t;
80
}
81
 
82
 
83
/* Returns a hash code for P.  */
84
 
85
hashval_t
86
lto_hash_type_slot_node (const void *p)
87
{
88
  const struct lto_decl_slot *ds = (const struct lto_decl_slot *) p;
89
  return (hashval_t) TYPE_UID (ds->t);
90
}
91
 
92
 
93
/* Returns nonzero if P1 and P2 are equal.  */
94
 
95
int
96
lto_eq_type_slot_node (const void *p1, const void *p2)
97
{
98
  const struct lto_decl_slot *ds1 =
99
    (const struct lto_decl_slot *) p1;
100
  const struct lto_decl_slot *ds2 =
101
    (const struct lto_decl_slot *) p2;
102
 
103
  return TYPE_UID (ds1->t) == TYPE_UID (ds2->t);
104
}
105
 
106
/*****************************************************************************
107
   Output routines shared by all of the serialization passes.
108
*****************************************************************************/
109
 
110
 
111
/* Flush compressed stream data function, sends NUM_CHARS from CHARS
112
   to the append lang hook, OPAQUE is currently always NULL.  */
113
 
114
static void
115
lto_append_data (const char *chars, unsigned int num_chars, void *opaque)
116
{
117
  gcc_assert (opaque == NULL);
118
  lang_hooks.lto.append_data (chars, num_chars, opaque);
119
}
120
 
121
/* Pointer to the current compression stream.  */
122
 
123
static struct lto_compression_stream *compression_stream = NULL;
124
 
125
/* Begin a new output section named NAME. If COMPRESS is true, zlib compress
126
   the section. */
127
 
128
void
129
lto_begin_section (const char *name, bool compress)
130
{
131
  lang_hooks.lto.begin_section (name);
132
 
133
  /* FIXME lto: for now, suppress compression if the lang_hook that appends
134
     data is anything other than assembler output.  The effect here is that
135
     we get compression of IL only in non-ltrans object files.  */
136
  gcc_assert (compression_stream == NULL);
137
  if (compress)
138
    compression_stream = lto_start_compression (lto_append_data, NULL);
139
}
140
 
141
 
142
/* End the current output section.  */
143
 
144
void
145
lto_end_section (void)
146
{
147
  if (compression_stream)
148
    {
149
      lto_end_compression (compression_stream);
150
      compression_stream = NULL;
151
    }
152
  lang_hooks.lto.end_section ();
153
}
154
 
155
 
156
/* Write all of the chars in OBS to the assembler.  Recycle the blocks
157
   in obs as this is being done.  */
158
 
159
void
160
lto_write_stream (struct lto_output_stream *obs)
161
{
162
  unsigned int block_size = 1024;
163
  struct lto_char_ptr_base *block;
164
  struct lto_char_ptr_base *next_block;
165
  if (!obs->first_block)
166
    return;
167
 
168
  for (block = obs->first_block; block; block = next_block)
169
    {
170
      const char *base = ((char *)block) + sizeof (struct lto_char_ptr_base);
171
      unsigned int num_chars = block_size - sizeof (struct lto_char_ptr_base);
172
 
173
      /* If this is not the last block, it is full.  If it is the last
174
         block, left_in_block indicates how many chars are unoccupied in
175
         this block; subtract from num_chars to obtain occupancy.  */
176
      next_block = (struct lto_char_ptr_base *) block->ptr;
177
      if (!next_block)
178
        num_chars -= obs->left_in_block;
179
 
180
      /* FIXME lto: WPA mode uses an ELF function as a lang_hook to append
181
         output data.  This hook is not happy with the way that compression
182
         blocks up output differently to the way it's blocked here.  So for
183
         now, we don't compress WPA output.  */
184
      if (compression_stream)
185
        {
186
          lto_compress_block (compression_stream, base, num_chars);
187
          lang_hooks.lto.append_data (NULL, 0, block);
188
        }
189
      else
190
        lang_hooks.lto.append_data (base, num_chars, block);
191
      block_size *= 2;
192
    }
193
}
194
 
195
 
196
/* Adds a new block to output stream OBS.  */
197
 
198
void
199
lto_append_block (struct lto_output_stream *obs)
200
{
201
  struct lto_char_ptr_base *new_block;
202
 
203
  gcc_assert (obs->left_in_block == 0);
204
 
205
  if (obs->first_block == NULL)
206
    {
207
      /* This is the first time the stream has been written
208
         into.  */
209
      obs->block_size = 1024;
210
      new_block = (struct lto_char_ptr_base*) xmalloc (obs->block_size);
211
      obs->first_block = new_block;
212
    }
213
  else
214
    {
215
      struct lto_char_ptr_base *tptr;
216
      /* Get a new block that is twice as big as the last block
217
         and link it into the list.  */
218
      obs->block_size *= 2;
219
      new_block = (struct lto_char_ptr_base*) xmalloc (obs->block_size);
220
      /* The first bytes of the block are reserved as a pointer to
221
         the next block.  Set the chain of the full block to the
222
         pointer to the new block.  */
223
      tptr = obs->current_block;
224
      tptr->ptr = (char *) new_block;
225
    }
226
 
227
  /* Set the place for the next char at the first position after the
228
     chain to the next block.  */
229
  obs->current_pointer
230
    = ((char *) new_block) + sizeof (struct lto_char_ptr_base);
231
  obs->current_block = new_block;
232
  /* Null out the newly allocated block's pointer to the next block.  */
233
  new_block->ptr = NULL;
234
  obs->left_in_block = obs->block_size - sizeof (struct lto_char_ptr_base);
235
}
236
 
237
 
238
/* Write raw DATA of length LEN to the output block OB.  */
239
 
240
void
241
lto_output_data_stream (struct lto_output_stream *obs, const void *data,
242
                        size_t len)
243
{
244
  while (len)
245
    {
246
      size_t copy;
247
 
248
      /* No space left.  */
249
      if (obs->left_in_block == 0)
250
        lto_append_block (obs);
251
 
252
      /* Determine how many bytes to copy in this loop.  */
253
      if (len <= obs->left_in_block)
254
        copy = len;
255
      else
256
        copy = obs->left_in_block;
257
 
258
      /* Copy the data and do bookkeeping.  */
259
      memcpy (obs->current_pointer, data, copy);
260
      obs->current_pointer += copy;
261
      obs->total_size += copy;
262
      obs->left_in_block -= copy;
263
      data = (const char *) data + copy;
264
      len -= copy;
265
    }
266
}
267
 
268
 
269
/* Lookup NAME in ENCODER.  If NAME is not found, create a new entry in
270
   ENCODER for NAME with the next available index of ENCODER,  then
271
   print the index to OBS.  True is returned if NAME was added to
272
   ENCODER.  The resulting index is stored in THIS_INDEX.
273
 
274
   If OBS is NULL, the only action is to add NAME to the encoder. */
275
 
276
bool
277
lto_output_decl_index (struct lto_output_stream *obs,
278
                       struct lto_tree_ref_encoder *encoder,
279
                       tree name, unsigned int *this_index)
280
{
281
  void **slot;
282
  struct lto_decl_slot d_slot;
283
  int index;
284
  bool new_entry_p = FALSE;
285
 
286
  d_slot.t = name;
287
  slot = htab_find_slot (encoder->tree_hash_table, &d_slot, INSERT);
288
  if (*slot == NULL)
289
    {
290
      struct lto_decl_slot *new_slot
291
        = (struct lto_decl_slot *) xmalloc (sizeof (struct lto_decl_slot));
292
      index = encoder->next_index++;
293
 
294
      new_slot->t = name;
295
      new_slot->slot_num = index;
296
      *slot = new_slot;
297
      VEC_safe_push (tree, heap, encoder->trees, name);
298
      new_entry_p = TRUE;
299
    }
300
  else
301
    {
302
      struct lto_decl_slot *old_slot = (struct lto_decl_slot *)*slot;
303
      index = old_slot->slot_num;
304
    }
305
 
306
  if (obs)
307
    streamer_write_uhwi_stream (obs, index);
308
  *this_index = index;
309
  return new_entry_p;
310
}
311
 
312
/* Output a field DECL to OBS.  */
313
 
314
void
315
lto_output_field_decl_index (struct lto_out_decl_state *decl_state,
316
                             struct lto_output_stream * obs, tree decl)
317
{
318
  unsigned int index;
319
  lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_FIELD_DECL],
320
                         decl, &index);
321
}
322
 
323
/* Output a function DECL to OBS.  */
324
 
325
void
326
lto_output_fn_decl_index (struct lto_out_decl_state *decl_state,
327
                          struct lto_output_stream * obs, tree decl)
328
{
329
  unsigned int index;
330
  lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_FN_DECL],
331
                         decl, &index);
332
}
333
 
334
/* Output a namespace DECL to OBS.  */
335
 
336
void
337
lto_output_namespace_decl_index (struct lto_out_decl_state *decl_state,
338
                                 struct lto_output_stream * obs, tree decl)
339
{
340
  unsigned int index;
341
  lto_output_decl_index (obs,
342
                         &decl_state->streams[LTO_DECL_STREAM_NAMESPACE_DECL],
343
                         decl, &index);
344
}
345
 
346
/* Output a static or extern var DECL to OBS.  */
347
 
348
void
349
lto_output_var_decl_index (struct lto_out_decl_state *decl_state,
350
                           struct lto_output_stream * obs, tree decl)
351
{
352
  unsigned int index;
353
  lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_VAR_DECL],
354
                         decl, &index);
355
}
356
 
357
/* Output a type DECL to OBS.  */
358
 
359
void
360
lto_output_type_decl_index (struct lto_out_decl_state *decl_state,
361
                            struct lto_output_stream * obs, tree decl)
362
{
363
  unsigned int index;
364
  lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_TYPE_DECL],
365
                         decl, &index);
366
}
367
 
368
/* Output a type REF to OBS.  */
369
 
370
void
371
lto_output_type_ref_index (struct lto_out_decl_state *decl_state,
372
                           struct lto_output_stream *obs, tree ref)
373
{
374
  unsigned int index;
375
  lto_output_decl_index (obs, &decl_state->streams[LTO_DECL_STREAM_TYPE],
376
                         ref, &index);
377
}
378
 
379
 
380
/* Create the output block and return it.  */
381
 
382
struct lto_simple_output_block *
383
lto_create_simple_output_block (enum lto_section_type section_type)
384
{
385
  struct lto_simple_output_block *ob
386
    = ((struct lto_simple_output_block *)
387
       xcalloc (1, sizeof (struct lto_simple_output_block)));
388
 
389
  ob->section_type = section_type;
390
  ob->decl_state = lto_get_out_decl_state ();
391
  ob->main_stream = ((struct lto_output_stream *)
392
                     xcalloc (1, sizeof (struct lto_output_stream)));
393
 
394
  return ob;
395
}
396
 
397
 
398
/* Produce a simple section for one of the ipa passes.  */
399
 
400
void
401
lto_destroy_simple_output_block (struct lto_simple_output_block *ob)
402
{
403
  char *section_name;
404
  struct lto_simple_header header;
405
  struct lto_output_stream *header_stream;
406
 
407
  section_name = lto_get_section_name (ob->section_type, NULL, NULL);
408
  lto_begin_section (section_name, !flag_wpa);
409
  free (section_name);
410
 
411
  /* Write the header which says how to decode the pieces of the
412
     t.  */
413
  memset (&header, 0, sizeof (struct lto_simple_header));
414
  header.lto_header.major_version = LTO_major_version;
415
  header.lto_header.minor_version = LTO_minor_version;
416
  header.lto_header.section_type = LTO_section_cgraph;
417
 
418
  header.compressed_size = 0;
419
 
420
  header.main_size = ob->main_stream->total_size;
421
 
422
  header_stream = XCNEW (struct lto_output_stream);
423
  lto_output_data_stream (header_stream, &header, sizeof header);
424
  lto_write_stream (header_stream);
425
  free (header_stream);
426
 
427
  lto_write_stream (ob->main_stream);
428
 
429
  /* Put back the assembly section that was there before we started
430
     writing lto info.  */
431
  lto_end_section ();
432
 
433
  free (ob->main_stream);
434
  free (ob);
435
}
436
 
437
 
438
/* Return a new lto_out_decl_state. */
439
 
440
struct lto_out_decl_state *
441
lto_new_out_decl_state (void)
442
{
443
  struct lto_out_decl_state *state = XCNEW (struct lto_out_decl_state);
444
  int i;
445
  htab_hash hash_fn;
446
  htab_eq eq_fn;
447
 
448
  for (i = 0; i < LTO_N_DECL_STREAMS; i++)
449
    {
450
      if (i == LTO_DECL_STREAM_TYPE)
451
        {
452
          hash_fn = lto_hash_type_slot_node;
453
          eq_fn = lto_eq_type_slot_node;
454
        }
455
      else
456
        {
457
          hash_fn = lto_hash_decl_slot_node;
458
          eq_fn = lto_eq_decl_slot_node;
459
        }
460
      lto_init_tree_ref_encoder (&state->streams[i], hash_fn, eq_fn);
461
    }
462
 
463
  return state;
464
}
465
 
466
 
467
/* Delete STATE and components.  */
468
 
469
void
470
lto_delete_out_decl_state (struct lto_out_decl_state *state)
471
{
472
  int i;
473
 
474
  for (i = 0; i < LTO_N_DECL_STREAMS; i++)
475
    lto_destroy_tree_ref_encoder (&state->streams[i]);
476
 
477
  free (state);
478
}
479
 
480
 
481
/* Get the currently used lto_out_decl_state structure. */
482
 
483
struct lto_out_decl_state *
484
lto_get_out_decl_state (void)
485
{
486
  return VEC_last (lto_out_decl_state_ptr, decl_state_stack);
487
}
488
 
489
/* Push STATE to top of out decl stack. */
490
 
491
void
492
lto_push_out_decl_state (struct lto_out_decl_state *state)
493
{
494
  VEC_safe_push (lto_out_decl_state_ptr, heap, decl_state_stack, state);
495
}
496
 
497
/* Pop the currently used out-decl state from top of stack. */
498
 
499
struct lto_out_decl_state *
500
lto_pop_out_decl_state (void)
501
{
502
  return VEC_pop (lto_out_decl_state_ptr, decl_state_stack);
503
}
504
 
505
/* Record STATE after it has been used in serializing the body of
506
   FN_DECL.  STATE should no longer be used by the caller.  The ownership
507
   of it is taken over from this point.  */
508
 
509
void
510
lto_record_function_out_decl_state (tree fn_decl,
511
                                    struct lto_out_decl_state *state)
512
{
513
  int i;
514
 
515
  /* Strip all hash tables to save some memory. */
516
  for (i = 0; i < LTO_N_DECL_STREAMS; i++)
517
    if (state->streams[i].tree_hash_table)
518
      {
519
        htab_delete (state->streams[i].tree_hash_table);
520
        state->streams[i].tree_hash_table = NULL;
521
      }
522
  state->fn_decl = fn_decl;
523
  VEC_safe_push (lto_out_decl_state_ptr, heap, lto_function_decl_states,
524
                 state);
525
}

powered by: WebSVN 2.1.0

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