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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [go/] [gofrontend/] [export.cc] - Blame information for rev 774

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

Line No. Rev Author Line
1 714 jeremybenn
// export.cc -- Export declarations in Go frontend.
2
 
3
// Copyright 2009 The Go Authors. All rights reserved.
4
// Use of this source code is governed by a BSD-style
5
// license that can be found in the LICENSE file.
6
 
7
#include "go-system.h"
8
 
9
#include "sha1.h"
10
 
11
#include "go-c.h"
12
 
13
#include "gogo.h"
14
#include "types.h"
15
#include "statements.h"
16
#include "export.h"
17
 
18
// This file handles exporting global declarations.
19
 
20
// Class Export.
21
 
22
// Version 1 magic number.
23
 
24
const int Export::v1_magic_len;
25
 
26
const char Export::v1_magic[Export::v1_magic_len] =
27
  {
28
    'v', '1', ';', '\n'
29
  };
30
 
31
const int Export::v1_checksum_len;
32
 
33
// Constructor.
34
 
35
Export::Export(Stream* stream)
36
  : stream_(stream), type_refs_(), type_index_(1)
37
{
38
}
39
 
40
// A functor to sort Named_object pointers by name.
41
 
42
struct Sort_bindings
43
{
44
  bool
45
  operator()(const Named_object* n1, const Named_object* n2) const
46
  { return n1->name() < n2->name(); }
47
};
48
 
49
// Return true if we should export NO.
50
 
51
static bool
52
should_export(Named_object* no)
53
{
54
  // We only export objects which are locally defined.
55
  if (no->package() != NULL)
56
    return false;
57
 
58
  // We don't export packages.
59
  if (no->is_package())
60
    return false;
61
 
62
  // We don't export hidden names.
63
  if (Gogo::is_hidden_name(no->name()))
64
    return false;
65
 
66
  // We don't export nested functions.
67
  if (no->is_function() && no->func_value()->enclosing() != NULL)
68
    return false;
69
 
70
  // We don't export thunks.
71
  if (no->is_function() && Gogo::is_thunk(no))
72
    return false;
73
 
74
  // Methods are exported with the type, not here.
75
  if (no->is_function()
76
      && no->func_value()->type()->is_method())
77
    return false;
78
  if (no->is_function_declaration()
79
      && no->func_declaration_value()->type()->is_method())
80
    return false;
81
 
82
  // Don't export dummy global variables created for initializers when
83
  // used with sinks.
84
  if (no->is_variable() && no->name()[0] == '_' && no->name()[1] == '.')
85
    return false;
86
 
87
  return true;
88
}
89
 
90
// Export those identifiers marked for exporting.
91
 
92
void
93
Export::export_globals(const std::string& package_name,
94
                       const std::string& unique_prefix,
95
                       int package_priority,
96
                       const std::map<std::string, Package*>& imports,
97
                       const std::string& import_init_fn,
98
                       const std::set<Import_init>& imported_init_fns,
99
                       const Bindings* bindings)
100
{
101
  // If there have been any errors so far, don't try to export
102
  // anything.  That way the export code doesn't have to worry about
103
  // mismatched types or other confusions.
104
  if (saw_errors())
105
    return;
106
 
107
  // Export the symbols in sorted order.  That will reduce cases where
108
  // irrelevant changes to the source code affect the exported
109
  // interface.
110
  std::vector<Named_object*> exports;
111
  exports.reserve(bindings->size_definitions());
112
 
113
  for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
114
       p != bindings->end_definitions();
115
       ++p)
116
    if (should_export(*p))
117
      exports.push_back(*p);
118
 
119
  for (Bindings::const_declarations_iterator p =
120
         bindings->begin_declarations();
121
       p != bindings->end_declarations();
122
       ++p)
123
    {
124
      // We export a function declaration as it may be implemented in
125
      // supporting C code.  We do not export type declarations.
126
      if (p->second->is_function_declaration()
127
          && should_export(p->second))
128
        exports.push_back(p->second);
129
    }
130
 
131
  std::sort(exports.begin(), exports.end(), Sort_bindings());
132
 
133
  // Although the export data is readable, at least this version is,
134
  // it is conceptually a binary format.  Start with a four byte
135
  // verison number.
136
  this->write_bytes(Export::v1_magic, Export::v1_magic_len);
137
 
138
  // The package name.
139
  this->write_c_string("package ");
140
  this->write_string(package_name);
141
  this->write_c_string(";\n");
142
 
143
  // The unique prefix.  This prefix is used for all global symbols.
144
  this->write_c_string("prefix ");
145
  this->write_string(unique_prefix);
146
  this->write_c_string(";\n");
147
 
148
  // The package priority.
149
  char buf[100];
150
  snprintf(buf, sizeof buf, "priority %d;\n", package_priority);
151
  this->write_c_string(buf);
152
 
153
  this->write_imports(imports);
154
 
155
  this->write_imported_init_fns(package_name, package_priority, import_init_fn,
156
                                imported_init_fns);
157
 
158
  // FIXME: It might be clever to add something about the processor
159
  // and ABI being used, although ideally any problems in that area
160
  // would be caught by the linker.
161
 
162
  for (std::vector<Named_object*>::const_iterator p = exports.begin();
163
       p != exports.end();
164
       ++p)
165
    (*p)->export_named_object(this);
166
 
167
  std::string checksum = this->stream_->checksum();
168
  std::string s = "checksum ";
169
  for (std::string::const_iterator p = checksum.begin();
170
       p != checksum.end();
171
       ++p)
172
    {
173
      unsigned char c = *p;
174
      unsigned int dig = c >> 4;
175
      s += dig < 10 ? '0' + dig : 'A' + dig - 10;
176
      dig = c & 0xf;
177
      s += dig < 10 ? '0' + dig : 'A' + dig - 10;
178
    }
179
  s += ";\n";
180
  this->stream_->write_checksum(s);
181
}
182
 
183
// Sort imported packages.
184
 
185
static bool
186
import_compare(const std::pair<std::string, Package*>& a,
187
               const std::pair<std::string, Package*>& b)
188
{
189
  return a.first < b.first;
190
}
191
 
192
// Write out the imported packages.
193
 
194
void
195
Export::write_imports(const std::map<std::string, Package*>& imports)
196
{
197
  // Sort the imports for more consistent output.
198
  std::vector<std::pair<std::string, Package*> > imp;
199
  for (std::map<std::string, Package*>::const_iterator p = imports.begin();
200
       p != imports.end();
201
       ++p)
202
    imp.push_back(std::make_pair(p->first, p->second));
203
 
204
  std::sort(imp.begin(), imp.end(), import_compare);
205
 
206
  for (std::vector<std::pair<std::string, Package*> >::const_iterator p =
207
         imp.begin();
208
       p != imp.end();
209
       ++p)
210
    {
211
      this->write_c_string("import ");
212
      this->write_string(p->second->name());
213
      this->write_c_string(" ");
214
      this->write_string(p->second->unique_prefix());
215
      this->write_c_string(" \"");
216
      this->write_string(p->first);
217
      this->write_c_string("\";\n");
218
    }
219
}
220
 
221
// Write out the initialization functions which need to run for this
222
// package.
223
 
224
void
225
Export::write_imported_init_fns(
226
    const std::string& package_name,
227
    int priority,
228
    const std::string& import_init_fn,
229
    const std::set<Import_init>& imported_init_fns)
230
{
231
  if (import_init_fn.empty() && imported_init_fns.empty())
232
    return;
233
 
234
  this->write_c_string("init");
235
 
236
  if (!import_init_fn.empty())
237
    {
238
      this->write_c_string(" ");
239
      this->write_string(package_name);
240
      this->write_c_string(" ");
241
      this->write_string(import_init_fn);
242
      char buf[100];
243
      snprintf(buf, sizeof buf, " %d", priority);
244
      this->write_c_string(buf);
245
    }
246
 
247
  if (!imported_init_fns.empty())
248
    {
249
      // Sort the list of functions for more consistent output.
250
      std::vector<Import_init> v;
251
      for (std::set<Import_init>::const_iterator p = imported_init_fns.begin();
252
           p != imported_init_fns.end();
253
           ++p)
254
        v.push_back(*p);
255
      std::sort(v.begin(), v.end());
256
 
257
      for (std::vector<Import_init>::const_iterator p = v.begin();
258
           p != v.end();
259
           ++p)
260
        {
261
          this->write_c_string(" ");
262
          this->write_string(p->package_name());
263
          this->write_c_string(" ");
264
          this->write_string(p->init_name());
265
          char buf[100];
266
          snprintf(buf, sizeof buf, " %d", p->priority());
267
          this->write_c_string(buf);
268
        }
269
    }
270
 
271
  this->write_c_string(";\n");
272
}
273
 
274
// Write a name to the export stream.
275
 
276
void
277
Export::write_name(const std::string& name)
278
{
279
  if (name.empty())
280
    this->write_c_string("?");
281
  else
282
    this->write_string(Gogo::message_name(name));
283
}
284
 
285
// Export a type.  We have to ensure that on import we create a single
286
// Named_type node for each named type.  We do this by keeping a hash
287
// table mapping named types to reference numbers.  The first time we
288
// see a named type we assign it a reference number by making an entry
289
// in the hash table.  If we see it again, we just refer to the
290
// reference number.
291
 
292
// Named types are, of course, associated with packages.  Note that we
293
// may see a named type when importing one package, and then later see
294
// the same named type when importing a different package.  The home
295
// package may or may not be imported during this compilation.  The
296
// reference number scheme has to get this all right.  Basic approach
297
// taken from "On the Linearization of Graphs and Writing Symbol
298
// Files" by Robert Griesemer.
299
 
300
void
301
Export::write_type(const Type* type)
302
{
303
  // We don't want to assign a reference number to a forward
304
  // declaration to a type which was defined later.
305
  type = type->forwarded();
306
 
307
  Type_refs::const_iterator p = this->type_refs_.find(type);
308
  if (p != this->type_refs_.end())
309
    {
310
      // This type was already in the table.
311
      int index = p->second;
312
      go_assert(index != 0);
313
      char buf[30];
314
      snprintf(buf, sizeof buf, "<type %d>", index);
315
      this->write_c_string(buf);
316
      return;
317
    }
318
 
319
  const Named_type* named_type = type->named_type();
320
  const Forward_declaration_type* forward = type->forward_declaration_type();
321
 
322
  int index = this->type_index_;
323
  ++this->type_index_;
324
 
325
  char buf[30];
326
  snprintf(buf, sizeof buf, "<type %d ", index);
327
  this->write_c_string(buf);
328
 
329
  if (named_type != NULL || forward != NULL)
330
    {
331
      const Named_object* named_object;
332
      if (named_type != NULL)
333
        {
334
          // The builtin types should have been predefined.
335
          go_assert(!Linemap::is_predeclared_location(named_type->location())
336
                     || (named_type->named_object()->package()->name()
337
                         == "unsafe"));
338
          named_object = named_type->named_object();
339
        }
340
      else
341
        named_object = forward->named_object();
342
 
343
      const Package* package = named_object->package();
344
 
345
      std::string s = "\"";
346
      if (package != NULL && !Gogo::is_hidden_name(named_object->name()))
347
        {
348
          s += package->unique_prefix();
349
          s += '.';
350
          s += package->name();
351
          s += '.';
352
        }
353
      s += named_object->name();
354
      s += "\" ";
355
      this->write_string(s);
356
 
357
      // We must add a named type to the table now, since the
358
      // definition of the type may refer to the named type via a
359
      // pointer.
360
      this->type_refs_[type] = index;
361
    }
362
 
363
  type->export_type(this);
364
 
365
  this->write_c_string(">");
366
 
367
  if (named_type == NULL)
368
    this->type_refs_[type] = index;
369
}
370
 
371
// Add the builtin types to the export table.
372
 
373
void
374
Export::register_builtin_types(Gogo* gogo)
375
{
376
  this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
377
  this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
378
  this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
379
  this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
380
  this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
381
  this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
382
  this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
383
  this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
384
  this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
385
  this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
386
  this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
387
  this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
388
  this->register_builtin_type(gogo, "int", BUILTIN_INT);
389
  this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
390
  this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
391
  this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
392
  this->register_builtin_type(gogo, "string", BUILTIN_STRING);
393
  this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
394
  this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
395
  this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
396
}
397
 
398
// Register one builtin type in the export table.
399
 
400
void
401
Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
402
{
403
  Named_object* named_object = gogo->lookup_global(name);
404
  go_assert(named_object != NULL && named_object->is_type());
405
  std::pair<Type_refs::iterator, bool> ins =
406
    this->type_refs_.insert(std::make_pair(named_object->type_value(), code));
407
  go_assert(ins.second);
408
 
409
  // We also insert the underlying type.  We can see the underlying
410
  // type at least for string and bool.  We skip the type aliases byte
411
  // and rune here.
412
  if (code != BUILTIN_BYTE && code != BUILTIN_RUNE)
413
    {
414
      Type* real_type = named_object->type_value()->real_type();
415
      ins = this->type_refs_.insert(std::make_pair(real_type, code));
416
      go_assert(ins.second);
417
    }
418
}
419
 
420
// Class Export::Stream.
421
 
422
Export::Stream::Stream()
423
{
424
  this->checksum_ = new sha1_ctx;
425
  memset(this->checksum_, 0, sizeof(sha1_ctx));
426
  sha1_init_ctx(this->checksum_);
427
}
428
 
429
Export::Stream::~Stream()
430
{
431
}
432
 
433
// Write bytes to the stream.  This keeps a checksum of bytes as they
434
// go by.
435
 
436
void
437
Export::Stream::write_and_sum_bytes(const char* bytes, size_t length)
438
{
439
  sha1_process_bytes(bytes, length, this->checksum_);
440
  this->do_write(bytes, length);
441
}
442
 
443
// Get the checksum.
444
 
445
std::string
446
Export::Stream::checksum()
447
{
448
  // Use a union to provide the required alignment.
449
  union
450
  {
451
    char checksum[Export::v1_checksum_len];
452
    long align;
453
  } u;
454
  sha1_finish_ctx(this->checksum_, u.checksum);
455
  return std::string(u.checksum, Export::v1_checksum_len);
456
}
457
 
458
// Write the checksum string to the export data.
459
 
460
void
461
Export::Stream::write_checksum(const std::string& s)
462
{
463
  this->do_write(s.data(), s.length());
464
}
465
 
466
// Class Stream_to_section.
467
 
468
Stream_to_section::Stream_to_section()
469
{
470
}
471
 
472
// Write data to a section.
473
 
474
void
475
Stream_to_section::do_write(const char* bytes, size_t length)
476
{
477
  go_write_export_data (bytes, length);
478
}

powered by: WebSVN 2.1.0

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