OSDN Git Service

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