compiler: add error to list of built-in types.
[gcc.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(!Linemap::is_predeclared_location(named_type->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 this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
341 }
342
343 // Register one builtin type in the export table.
344
345 void
346 Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
347 {
348 Named_object* named_object = gogo->lookup_global(name);
349 go_assert(named_object != NULL && named_object->is_type());
350 std::pair<Type_refs::iterator, bool> ins =
351 this->type_refs_.insert(std::make_pair(named_object->type_value(), code));
352 go_assert(ins.second);
353
354 // We also insert the underlying type. We can see the underlying
355 // type at least for string and bool.
356 Type* real_type = named_object->type_value()->real_type();
357 ins = this->type_refs_.insert(std::make_pair(real_type, code));
358 go_assert(ins.second);
359 }
360
361 // Class Export::Stream.
362
363 Export::Stream::Stream()
364 {
365 this->checksum_ = new sha1_ctx;
366 memset(this->checksum_, 0, sizeof(sha1_ctx));
367 sha1_init_ctx(this->checksum_);
368 }
369
370 Export::Stream::~Stream()
371 {
372 }
373
374 // Write bytes to the stream. This keeps a checksum of bytes as they
375 // go by.
376
377 void
378 Export::Stream::write_and_sum_bytes(const char* bytes, size_t length)
379 {
380 sha1_process_bytes(bytes, length, this->checksum_);
381 this->do_write(bytes, length);
382 }
383
384 // Get the checksum.
385
386 std::string
387 Export::Stream::checksum()
388 {
389 // Use a union to provide the required alignment.
390 union
391 {
392 char checksum[Export::v1_checksum_len];
393 long align;
394 } u;
395 sha1_finish_ctx(this->checksum_, u.checksum);
396 return std::string(u.checksum, Export::v1_checksum_len);
397 }
398
399 // Write the checksum string to the export data.
400
401 void
402 Export::Stream::write_checksum(const std::string& s)
403 {
404 this->do_write(s.data(), s.length());
405 }
406
407 // Class Stream_to_section.
408
409 Stream_to_section::Stream_to_section()
410 {
411 }
412
413 // Write data to a section.
414
415 void
416 Stream_to_section::do_write(const char* bytes, size_t length)
417 {
418 go_write_export_data (bytes, length);
419 }