OSDN Git Service

compiler: Add parameter names to export information.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / export.cc
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
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::string& import_init_fn,
97                        const std::set<Import_init>& imported_init_fns,
98                        const Bindings* bindings)
99 {
100   // If there have been any errors so far, don't try to export
101   // anything.  That way the export code doesn't have to worry about
102   // mismatched types or other confusions.
103   if (saw_errors())
104     return;
105
106   // Export the symbols in sorted order.  That will reduce cases where
107   // irrelevant changes to the source code affect the exported
108   // interface.
109   std::vector<Named_object*> exports;
110   exports.reserve(bindings->size_definitions());
111
112   for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
113        p != bindings->end_definitions();
114        ++p)
115     if (should_export(*p))
116       exports.push_back(*p);
117
118   for (Bindings::const_declarations_iterator p =
119          bindings->begin_declarations();
120        p != bindings->end_declarations();
121        ++p)
122     {
123       // We export a function declaration as it may be implemented in
124       // supporting C code.  We do not export type declarations.
125       if (p->second->is_function_declaration()
126           && should_export(p->second))
127         exports.push_back(p->second);
128     }
129
130   std::sort(exports.begin(), exports.end(), Sort_bindings());
131
132   // Although the export data is readable, at least this version is,
133   // it is conceptually a binary format.  Start with a four byte
134   // verison number.
135   this->write_bytes(Export::v1_magic, Export::v1_magic_len);
136
137   // The package name.
138   this->write_c_string("package ");
139   this->write_string(package_name);
140   this->write_c_string(";\n");
141
142   // The unique prefix.  This prefix is used for all global symbols.
143   this->write_c_string("prefix ");
144   this->write_string(unique_prefix);
145   this->write_c_string(";\n");
146
147   // The package priority.
148   char buf[100];
149   snprintf(buf, sizeof buf, "priority %d;\n", package_priority);
150   this->write_c_string(buf);
151
152   this->write_imported_init_fns(package_name, package_priority, import_init_fn,
153                                 imported_init_fns);
154
155   // FIXME: It might be clever to add something about the processor
156   // and ABI being used, although ideally any problems in that area
157   // would be caught by the linker.
158
159   for (std::vector<Named_object*>::const_iterator p = exports.begin();
160        p != exports.end();
161        ++p)
162     (*p)->export_named_object(this);
163
164   std::string checksum = this->stream_->checksum();
165   std::string s = "checksum ";
166   for (std::string::const_iterator p = checksum.begin();
167        p != checksum.end();
168        ++p)
169     {
170       unsigned char c = *p;
171       unsigned int dig = c >> 4;
172       s += dig < 10 ? '0' + dig : 'A' + dig - 10;
173       dig = c & 0xf;
174       s += dig < 10 ? '0' + dig : 'A' + dig - 10;
175     }
176   s += ";\n";
177   this->stream_->write_checksum(s);
178 }
179
180 // Write out the import control variables for this package.
181
182 void
183 Export::write_imported_init_fns(
184     const std::string& package_name,
185     int priority,
186     const std::string& import_init_fn,
187     const std::set<Import_init>& imported_init_fns)
188 {
189   if (import_init_fn.empty() && imported_init_fns.empty())
190     return;
191
192   this->write_c_string("import");
193
194   if (!import_init_fn.empty())
195     {
196       this->write_c_string(" ");
197       this->write_string(package_name);
198       this->write_c_string(" ");
199       this->write_string(import_init_fn);
200       char buf[100];
201       snprintf(buf, sizeof buf, " %d", priority);
202       this->write_c_string(buf);
203     }
204
205   if (!imported_init_fns.empty())
206     {
207       // Sort the list of functions for more consistent output.
208       std::vector<Import_init> v;
209       for (std::set<Import_init>::const_iterator p = imported_init_fns.begin();
210            p != imported_init_fns.end();
211            ++p)
212         v.push_back(*p);
213       std::sort(v.begin(), v.end());
214
215       for (std::vector<Import_init>::const_iterator p = v.begin();
216            p != v.end();
217            ++p)
218         {
219           this->write_c_string(" ");
220           this->write_string(p->package_name());
221           this->write_c_string(" ");
222           this->write_string(p->init_name());
223           char buf[100];
224           snprintf(buf, sizeof buf, " %d", p->priority());
225           this->write_c_string(buf);
226         }
227     }
228
229   this->write_c_string(";\n");
230 }
231
232 // Write a name to the export stream.
233
234 void
235 Export::write_name(const std::string& name)
236 {
237   if (name.empty())
238     this->write_c_string("?");
239   else
240     this->write_string(Gogo::message_name(name));
241 }
242
243 // Export a type.  We have to ensure that on import we create a single
244 // Named_type node for each named type.  We do this by keeping a hash
245 // table mapping named types to reference numbers.  The first time we
246 // see a named type we assign it a reference number by making an entry
247 // in the hash table.  If we see it again, we just refer to the
248 // reference number.
249
250 // Named types are, of course, associated with packages.  Note that we
251 // may see a named type when importing one package, and then later see
252 // the same named type when importing a different package.  The home
253 // package may or may not be imported during this compilation.  The
254 // reference number scheme has to get this all right.  Basic approach
255 // taken from "On the Linearization of Graphs and Writing Symbol
256 // Files" by Robert Griesemer.
257
258 void
259 Export::write_type(const Type* type)
260 {
261   // We don't want to assign a reference number to a forward
262   // declaration to a type which was defined later.
263   type = type->forwarded();
264
265   Type_refs::const_iterator p = this->type_refs_.find(type);
266   if (p != this->type_refs_.end())
267     {
268       // This type was already in the table.
269       int index = p->second;
270       go_assert(index != 0);
271       char buf[30];
272       snprintf(buf, sizeof buf, "<type %d>", index);
273       this->write_c_string(buf);
274       return;
275     }
276
277   const Named_type* named_type = type->named_type();
278   const Forward_declaration_type* forward = type->forward_declaration_type();
279
280   int index = this->type_index_;
281   ++this->type_index_;
282
283   char buf[30];
284   snprintf(buf, sizeof buf, "<type %d ", index);
285   this->write_c_string(buf);
286
287   if (named_type != NULL || forward != NULL)
288     {
289       const Named_object* named_object;
290       if (named_type != NULL)
291         {
292           // The builtin types should have been predefined.
293           go_assert(!Linemap::is_predeclared_location(named_type->location())
294                      || (named_type->named_object()->package()->name()
295                          == "unsafe"));
296           named_object = named_type->named_object();
297         }
298       else
299         named_object = forward->named_object();
300
301       const Package* package = named_object->package();
302
303       std::string s = "\"";
304       if (package != NULL && !Gogo::is_hidden_name(named_object->name()))
305         {
306           s += package->unique_prefix();
307           s += '.';
308           s += package->name();
309           s += '.';
310         }
311       s += named_object->name();
312       s += "\" ";
313       this->write_string(s);
314
315       // We must add a named type to the table now, since the
316       // definition of the type may refer to the named type via a
317       // pointer.
318       this->type_refs_[type] = index;
319     }
320
321   type->export_type(this);
322
323   this->write_c_string(">");
324
325   if (named_type == NULL)
326     this->type_refs_[type] = index;
327 }
328
329 // Add the builtin types to the export table.
330
331 void
332 Export::register_builtin_types(Gogo* gogo)
333 {
334   this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
335   this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
336   this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
337   this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
338   this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
339   this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
340   this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
341   this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
342   this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
343   this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
344   this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
345   this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
346   this->register_builtin_type(gogo, "int", BUILTIN_INT);
347   this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
348   this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
349   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
350   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
351   this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
352   this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
353   this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
354 }
355
356 // Register one builtin type in the export table.
357
358 void
359 Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
360 {
361   Named_object* named_object = gogo->lookup_global(name);
362   go_assert(named_object != NULL && named_object->is_type());
363   std::pair<Type_refs::iterator, bool> ins =
364     this->type_refs_.insert(std::make_pair(named_object->type_value(), code));
365   go_assert(ins.second);
366
367   // We also insert the underlying type.  We can see the underlying
368   // type at least for string and bool.  We skip the type aliases byte
369   // and rune here.
370   if (code != BUILTIN_BYTE && code != BUILTIN_RUNE)
371     {
372       Type* real_type = named_object->type_value()->real_type();
373       ins = this->type_refs_.insert(std::make_pair(real_type, code));
374       go_assert(ins.second);
375     }
376 }
377
378 // Class Export::Stream.
379
380 Export::Stream::Stream()
381 {
382   this->checksum_ = new sha1_ctx;
383   memset(this->checksum_, 0, sizeof(sha1_ctx));
384   sha1_init_ctx(this->checksum_);
385 }
386
387 Export::Stream::~Stream()
388 {
389 }
390
391 // Write bytes to the stream.  This keeps a checksum of bytes as they
392 // go by.
393
394 void
395 Export::Stream::write_and_sum_bytes(const char* bytes, size_t length)
396 {
397   sha1_process_bytes(bytes, length, this->checksum_);
398   this->do_write(bytes, length);
399 }
400
401 // Get the checksum.
402
403 std::string
404 Export::Stream::checksum()
405 {
406   // Use a union to provide the required alignment.
407   union
408   {
409     char checksum[Export::v1_checksum_len];
410     long align;
411   } u;
412   sha1_finish_ctx(this->checksum_, u.checksum);
413   return std::string(u.checksum, Export::v1_checksum_len);
414 }
415
416 // Write the checksum string to the export data.
417
418 void
419 Export::Stream::write_checksum(const std::string& s)
420 {
421   this->do_write(s.data(), s.length());
422 }
423
424 // Class Stream_to_section.
425
426 Stream_to_section::Stream_to_section()
427 {
428 }
429
430 // Write data to a section.
431
432 void
433 Stream_to_section::do_write(const char* bytes, size_t length)
434 {
435   go_write_export_data (bytes, length);
436 }