OSDN Git Service

Change export code to use the backend interface.
[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 // Export a type.  We have to ensure that on import we create a single
233 // Named_type node for each named type.  We do this by keeping a hash
234 // table mapping named types to reference numbers.  The first time we
235 // see a named type we assign it a reference number by making an entry
236 // in the hash table.  If we see it again, we just refer to the
237 // reference number.
238
239 // Named types are, of course, associated with packages.  Note that we
240 // may see a named type when importing one package, and then later see
241 // the same named type when importing a different package.  The home
242 // package may or may not be imported during this compilation.  The
243 // reference number scheme has to get this all right.  Basic approach
244 // taken from "On the Linearization of Graphs and Writing Symbol
245 // Files" by Robert Griesemer.
246
247 void
248 Export::write_type(const Type* type)
249 {
250   // We don't want to assign a reference number to a forward
251   // declaration to a type which was defined later.
252   type = type->forwarded();
253
254   Type_refs::const_iterator p = this->type_refs_.find(type);
255   if (p != this->type_refs_.end())
256     {
257       // This type was already in the table.
258       int index = p->second;
259       go_assert(index != 0);
260       char buf[30];
261       snprintf(buf, sizeof buf, "<type %d>", index);
262       this->write_c_string(buf);
263       return;
264     }
265
266   const Named_type* named_type = type->named_type();
267   const Forward_declaration_type* forward = type->forward_declaration_type();
268
269   int index = this->type_index_;
270   ++this->type_index_;
271
272   char buf[30];
273   snprintf(buf, sizeof buf, "<type %d ", index);
274   this->write_c_string(buf);
275
276   if (named_type != NULL || forward != NULL)
277     {
278       const Named_object* named_object;
279       if (named_type != NULL)
280         {
281           // The builtin types should have been predefined.
282           go_assert(named_type->location() != BUILTINS_LOCATION
283                      || (named_type->named_object()->package()->name()
284                          == "unsafe"));
285           named_object = named_type->named_object();
286         }
287       else
288         named_object = forward->named_object();
289
290       const Package* package = named_object->package();
291
292       std::string s = "\"";
293       if (package != NULL && !Gogo::is_hidden_name(named_object->name()))
294         {
295           s += package->unique_prefix();
296           s += '.';
297           s += package->name();
298           s += '.';
299         }
300       s += named_object->name();
301       s += "\" ";
302       this->write_string(s);
303
304       // We must add a named type to the table now, since the
305       // definition of the type may refer to the named type via a
306       // pointer.
307       this->type_refs_[type] = index;
308     }
309
310   type->export_type(this);
311
312   this->write_c_string(">");
313
314   if (named_type == NULL)
315     this->type_refs_[type] = index;
316 }
317
318 // Add the builtin types to the export table.
319
320 void
321 Export::register_builtin_types(Gogo* gogo)
322 {
323   this->register_builtin_type(gogo, "int8", BUILTIN_INT8);
324   this->register_builtin_type(gogo, "int16", BUILTIN_INT16);
325   this->register_builtin_type(gogo, "int32", BUILTIN_INT32);
326   this->register_builtin_type(gogo, "int64", BUILTIN_INT64);
327   this->register_builtin_type(gogo, "uint8", BUILTIN_UINT8);
328   this->register_builtin_type(gogo, "uint16", BUILTIN_UINT16);
329   this->register_builtin_type(gogo, "uint32", BUILTIN_UINT32);
330   this->register_builtin_type(gogo, "uint64", BUILTIN_UINT64);
331   this->register_builtin_type(gogo, "float32", BUILTIN_FLOAT32);
332   this->register_builtin_type(gogo, "float64", BUILTIN_FLOAT64);
333   this->register_builtin_type(gogo, "complex64", BUILTIN_COMPLEX64);
334   this->register_builtin_type(gogo, "complex128", BUILTIN_COMPLEX128);
335   this->register_builtin_type(gogo, "int", BUILTIN_INT);
336   this->register_builtin_type(gogo, "uint", BUILTIN_UINT);
337   this->register_builtin_type(gogo, "uintptr", BUILTIN_UINTPTR);
338   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
339   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
340 }
341
342 // Register one builtin type in the export table.
343
344 void
345 Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
346 {
347   Named_object* named_object = gogo->lookup_global(name);
348   go_assert(named_object != NULL && named_object->is_type());
349   std::pair<Type_refs::iterator, bool> ins =
350     this->type_refs_.insert(std::make_pair(named_object->type_value(), code));
351   go_assert(ins.second);
352
353   // We also insert the underlying type.  We can see the underlying
354   // type at least for string and bool.
355   Type* real_type = named_object->type_value()->real_type();
356   ins = this->type_refs_.insert(std::make_pair(real_type, code));
357   go_assert(ins.second);
358 }
359
360 // Class Export::Stream.
361
362 Export::Stream::Stream()
363 {
364   this->checksum_ = new sha1_ctx;
365   memset(this->checksum_, 0, sizeof(sha1_ctx));
366   sha1_init_ctx(this->checksum_);
367 }
368
369 Export::Stream::~Stream()
370 {
371 }
372
373 // Write bytes to the stream.  This keeps a checksum of bytes as they
374 // go by.
375
376 void
377 Export::Stream::write_and_sum_bytes(const char* bytes, size_t length)
378 {
379   sha1_process_bytes(bytes, length, this->checksum_);
380   this->do_write(bytes, length);
381 }
382
383 // Get the checksum.
384
385 std::string
386 Export::Stream::checksum()
387 {
388   // Use a union to provide the required alignment.
389   union
390   {
391     char checksum[Export::v1_checksum_len];
392     long align;
393   } u;
394   sha1_finish_ctx(this->checksum_, u.checksum);
395   return std::string(u.checksum, Export::v1_checksum_len);
396 }
397
398 // Write the checksum string to the export data.
399
400 void
401 Export::Stream::write_checksum(const std::string& s)
402 {
403   this->do_write(s.data(), s.length());
404 }
405
406 // Class Stream_to_section.
407
408 Stream_to_section::Stream_to_section()
409 {
410 }
411
412 // Write data to a section.
413
414 void
415 Stream_to_section::do_write(const char* bytes, size_t length)
416 {
417   go_write_export_data (bytes, length);
418 }