1// 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
24const int Export::v1_magic_len;
25
26const char Export::v1_magic[Export::v1_magic_len] =
27  {
28    'v', '1', ';', '\n'
29  };
30
31const int Export::v1_checksum_len;
32
33// Constructor.
34
35Export::Export(Stream* stream)
36  : stream_(stream), type_refs_(), type_index_(1), packages_()
37{
38}
39
40// A functor to sort Named_object pointers by name.
41
42struct 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
51static bool
52should_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
92void
93Export::export_globals(const std::string& package_name,
94		       const std::string& prefix,
95		       const std::string& pkgpath,
96		       int package_priority,
97		       const std::map<std::string, Package*>& packages,
98		       const std::map<std::string, Package*>& imports,
99		       const std::string& import_init_fn,
100		       const std::set<Import_init>& imported_init_fns,
101		       const Bindings* bindings)
102{
103  // If there have been any errors so far, don't try to export
104  // anything.  That way the export code doesn't have to worry about
105  // mismatched types or other confusions.
106  if (saw_errors())
107    return;
108
109  // Export the symbols in sorted order.  That will reduce cases where
110  // irrelevant changes to the source code affect the exported
111  // interface.
112  std::vector<Named_object*> exports;
113  exports.reserve(bindings->size_definitions());
114
115  for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
116       p != bindings->end_definitions();
117       ++p)
118    if (should_export(*p))
119      exports.push_back(*p);
120
121  for (Bindings::const_declarations_iterator p =
122	 bindings->begin_declarations();
123       p != bindings->end_declarations();
124       ++p)
125    {
126      // We export a function declaration as it may be implemented in
127      // supporting C code.  We do not export type declarations.
128      if (p->second->is_function_declaration()
129	  && should_export(p->second))
130	exports.push_back(p->second);
131    }
132
133  std::sort(exports.begin(), exports.end(), Sort_bindings());
134
135  // Although the export data is readable, at least this version is,
136  // it is conceptually a binary format.  Start with a four byte
137  // verison number.
138  this->write_bytes(Export::v1_magic, Export::v1_magic_len);
139
140  // The package name.
141  this->write_c_string("package ");
142  this->write_string(package_name);
143  this->write_c_string(";\n");
144
145  // The prefix or package path, used for all global symbols.
146  if (prefix.empty())
147    {
148      go_assert(!pkgpath.empty());
149      this->write_c_string("pkgpath ");
150      this->write_string(pkgpath);
151    }
152  else
153    {
154      this->write_c_string("prefix ");
155      this->write_string(prefix);
156    }
157  this->write_c_string(";\n");
158
159  // The package priority.
160  char buf[100];
161  snprintf(buf, sizeof buf, "priority %d;\n", package_priority);
162  this->write_c_string(buf);
163
164  this->write_packages(packages);
165
166  this->write_imports(imports);
167
168  this->write_imported_init_fns(package_name, package_priority, import_init_fn,
169				imported_init_fns);
170
171  // FIXME: It might be clever to add something about the processor
172  // and ABI being used, although ideally any problems in that area
173  // would be caught by the linker.
174
175  for (std::vector<Named_object*>::const_iterator p = exports.begin();
176       p != exports.end();
177       ++p)
178    (*p)->export_named_object(this);
179
180  std::string checksum = this->stream_->checksum();
181  std::string s = "checksum ";
182  for (std::string::const_iterator p = checksum.begin();
183       p != checksum.end();
184       ++p)
185    {
186      unsigned char c = *p;
187      unsigned int dig = c >> 4;
188      s += dig < 10 ? '0' + dig : 'A' + dig - 10;
189      dig = c & 0xf;
190      s += dig < 10 ? '0' + dig : 'A' + dig - 10;
191    }
192  s += ";\n";
193  this->stream_->write_checksum(s);
194}
195
196// Sort packages.
197
198static bool
199packages_compare(const Package* a, const Package* b)
200{
201  return a->package_name() < b->package_name();
202}
203
204// Write out all the known packages whose pkgpath symbol is not a
205// simple transformation of the pkgpath, so that the importing code
206// can reliably know it.
207
208void
209Export::write_packages(const std::map<std::string, Package*>& packages)
210{
211  // Sort for consistent output.
212  std::vector<Package*> out;
213  for (std::map<std::string, Package*>::const_iterator p = packages.begin();
214       p != packages.end();
215       ++p)
216    {
217      if (p->second->pkgpath_symbol()
218	  != Gogo::pkgpath_for_symbol(p->second->pkgpath()))
219	out.push_back(p->second);
220    }
221
222  std::sort(out.begin(), out.end(), packages_compare);
223
224  for (std::vector<Package*>::const_iterator p = out.begin();
225       p != out.end();
226       ++p)
227    {
228      this->write_c_string("package ");
229      this->write_string((*p)->package_name());
230      this->write_c_string(" ");
231      this->write_string((*p)->pkgpath());
232      this->write_c_string(" ");
233      this->write_string((*p)->pkgpath_symbol());
234      this->write_c_string(";\n");
235    }
236}
237
238// Sort imported packages.
239
240static bool
241import_compare(const std::pair<std::string, Package*>& a,
242	       const std::pair<std::string, Package*>& b)
243{
244  return a.first < b.first;
245}
246
247// Write out the imported packages.
248
249void
250Export::write_imports(const std::map<std::string, Package*>& imports)
251{
252  // Sort the imports for more consistent output.
253  std::vector<std::pair<std::string, Package*> > imp;
254  for (std::map<std::string, Package*>::const_iterator p = imports.begin();
255       p != imports.end();
256       ++p)
257    imp.push_back(std::make_pair(p->first, p->second));
258
259  std::sort(imp.begin(), imp.end(), import_compare);
260
261  for (std::vector<std::pair<std::string, Package*> >::const_iterator p =
262	 imp.begin();
263       p != imp.end();
264       ++p)
265    {
266      this->write_c_string("import ");
267      this->write_string(p->second->package_name());
268      this->write_c_string(" ");
269      this->write_string(p->second->pkgpath());
270      this->write_c_string(" \"");
271      this->write_string(p->first);
272      this->write_c_string("\";\n");
273
274      this->packages_.insert(p->second);
275    }
276}
277
278// Write out the initialization functions which need to run for this
279// package.
280
281void
282Export::write_imported_init_fns(
283    const std::string& package_name,
284    int priority,
285    const std::string& import_init_fn,
286    const std::set<Import_init>& imported_init_fns)
287{
288  if (import_init_fn.empty() && imported_init_fns.empty())
289    return;
290
291  this->write_c_string("init");
292
293  if (!import_init_fn.empty())
294    {
295      this->write_c_string(" ");
296      this->write_string(package_name);
297      this->write_c_string(" ");
298      this->write_string(import_init_fn);
299      char buf[100];
300      snprintf(buf, sizeof buf, " %d", priority);
301      this->write_c_string(buf);
302    }
303
304  if (!imported_init_fns.empty())
305    {
306      // Sort the list of functions for more consistent output.
307      std::vector<Import_init> v;
308      for (std::set<Import_init>::const_iterator p = imported_init_fns.begin();
309	   p != imported_init_fns.end();
310	   ++p)
311	v.push_back(*p);
312      std::sort(v.begin(), v.end());
313
314      for (std::vector<Import_init>::const_iterator p = v.begin();
315	   p != v.end();
316	   ++p)
317	{
318	  this->write_c_string(" ");
319	  this->write_string(p->package_name());
320	  this->write_c_string(" ");
321	  this->write_string(p->init_name());
322	  char buf[100];
323	  snprintf(buf, sizeof buf, " %d", p->priority());
324	  this->write_c_string(buf);
325	}
326    }
327
328  this->write_c_string(";\n");
329}
330
331// Write a name to the export stream.
332
333void
334Export::write_name(const std::string& name)
335{
336  if (name.empty())
337    this->write_c_string("?");
338  else
339    this->write_string(Gogo::message_name(name));
340}
341
342// Export a type.  We have to ensure that on import we create a single
343// Named_type node for each named type.  We do this by keeping a hash
344// table mapping named types to reference numbers.  The first time we
345// see a named type we assign it a reference number by making an entry
346// in the hash table.  If we see it again, we just refer to the
347// reference number.
348
349// Named types are, of course, associated with packages.  Note that we
350// may see a named type when importing one package, and then later see
351// the same named type when importing a different package.  The home
352// package may or may not be imported during this compilation.  The
353// reference number scheme has to get this all right.  Basic approach
354// taken from "On the Linearization of Graphs and Writing Symbol
355// Files" by Robert Griesemer.
356
357void
358Export::write_type(const Type* type)
359{
360  // We don't want to assign a reference number to a forward
361  // declaration to a type which was defined later.
362  type = type->forwarded();
363
364  Type_refs::const_iterator p = this->type_refs_.find(type);
365  if (p != this->type_refs_.end())
366    {
367      // This type was already in the table.
368      int index = p->second;
369      go_assert(index != 0);
370      char buf[30];
371      snprintf(buf, sizeof buf, "<type %d>", index);
372      this->write_c_string(buf);
373      return;
374    }
375
376  const Named_type* named_type = type->named_type();
377  const Forward_declaration_type* forward = type->forward_declaration_type();
378
379  int index = this->type_index_;
380  ++this->type_index_;
381
382  char buf[30];
383  snprintf(buf, sizeof buf, "<type %d ", index);
384  this->write_c_string(buf);
385
386  if (named_type != NULL || forward != NULL)
387    {
388      const Named_object* named_object;
389      if (named_type != NULL)
390	{
391	  // The builtin types should have been predefined.
392	  go_assert(!Linemap::is_predeclared_location(named_type->location())
393		     || (named_type->named_object()->package()->package_name()
394			 == "unsafe"));
395	  named_object = named_type->named_object();
396	}
397      else
398	named_object = forward->named_object();
399
400      const Package* package = named_object->package();
401
402      std::string s = "\"";
403      if (package != NULL && !Gogo::is_hidden_name(named_object->name()))
404	{
405	  s += package->pkgpath();
406	  s += '.';
407	}
408      s += named_object->name();
409      s += "\" ";
410      this->write_string(s);
411
412      // It is possible that this type was imported indirectly, and is
413      // not in a package in the import list.  If we have not
414      // mentioned this package before, write out the package name
415      // here so that any package importing this one will know it.
416      if (package != NULL
417	  && this->packages_.find(package) == this->packages_.end())
418	{
419	  this->write_c_string("\"");
420	  this->write_string(package->package_name());
421	  this->packages_.insert(package);
422	  this->write_c_string("\" ");
423	}
424
425      // We must add a named type to the table now, since the
426      // definition of the type may refer to the named type via a
427      // pointer.
428      this->type_refs_[type] = index;
429    }
430
431  type->export_type(this);
432
433  this->write_c_string(">");
434
435  if (named_type == NULL)
436    this->type_refs_[type] = index;
437}
438
439// Add the builtin types to the export table.
440
441void
442Export::register_builtin_types(Gogo* gogo)
443{
444  this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
445  this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
446  this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
447  this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
448  this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
449  this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
450  this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
451  this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
452  this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
453  this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
454  this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
455  this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
456  this->register_builtin_type(gogo, "int", BUILTIN_INT);
457  this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
458  this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
459  this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
460  this->register_builtin_type(gogo, "string", BUILTIN_STRING);
461  this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
462  this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
463  this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
464}
465
466// Register one builtin type in the export table.
467
468void
469Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
470{
471  Named_object* named_object = gogo->lookup_global(name);
472  go_assert(named_object != NULL && named_object->is_type());
473  std::pair<Type_refs::iterator, bool> ins =
474    this->type_refs_.insert(std::make_pair(named_object->type_value(), code));
475  go_assert(ins.second);
476
477  // We also insert the underlying type.  We can see the underlying
478  // type at least for string and bool.  We skip the type aliases byte
479  // and rune here.
480  if (code != BUILTIN_BYTE && code != BUILTIN_RUNE)
481    {
482      Type* real_type = named_object->type_value()->real_type();
483      ins = this->type_refs_.insert(std::make_pair(real_type, code));
484      go_assert(ins.second);
485    }
486}
487
488// Class Export::Stream.
489
490Export::Stream::Stream()
491{
492  this->checksum_ = new sha1_ctx;
493  memset(this->checksum_, 0, sizeof(sha1_ctx));
494  sha1_init_ctx(this->checksum_);
495}
496
497Export::Stream::~Stream()
498{
499}
500
501// Write bytes to the stream.  This keeps a checksum of bytes as they
502// go by.
503
504void
505Export::Stream::write_and_sum_bytes(const char* bytes, size_t length)
506{
507  sha1_process_bytes(bytes, length, this->checksum_);
508  this->do_write(bytes, length);
509}
510
511// Get the checksum.
512
513std::string
514Export::Stream::checksum()
515{
516  // Use a union to provide the required alignment.
517  union
518  {
519    char checksum[Export::v1_checksum_len];
520    long align;
521  } u;
522  sha1_finish_ctx(this->checksum_, u.checksum);
523  return std::string(u.checksum, Export::v1_checksum_len);
524}
525
526// Write the checksum string to the export data.
527
528void
529Export::Stream::write_checksum(const std::string& s)
530{
531  this->do_write(s.data(), s.length());
532}
533
534// Class Stream_to_section.
535
536Stream_to_section::Stream_to_section()
537{
538}
539
540// Write data to a section.
541
542void
543Stream_to_section::do_write(const char* bytes, size_t length)
544{
545  go_write_export_data (bytes, length);
546}
547