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