diff options
Diffstat (limited to 'gcc-4.8/gcc/go/gofrontend/gogo.cc')
-rw-r--r-- | gcc-4.8/gcc/go/gofrontend/gogo.cc | 172 |
1 files changed, 169 insertions, 3 deletions
diff --git a/gcc-4.8/gcc/go/gofrontend/gogo.cc b/gcc-4.8/gcc/go/gofrontend/gogo.cc index 9f918cb81..e16b0d3a5 100644 --- a/gcc-4.8/gcc/go/gofrontend/gogo.cc +++ b/gcc-4.8/gcc/go/gofrontend/gogo.cc @@ -2822,7 +2822,10 @@ Build_recover_thunks::function(Named_object* orig_no) if (orig_fntype->is_varargs()) new_fntype->set_is_varargs(); - std::string name = orig_no->name() + "$recover"; + std::string name = orig_no->name(); + if (orig_fntype->is_method()) + name += "$" + orig_fntype->receiver()->type()->mangled_name(gogo); + name += "$recover"; Named_object *new_no = gogo->start_function(name, new_fntype, false, location); Function *new_func = new_no->func_value(); @@ -2916,7 +2919,25 @@ Build_recover_thunks::function(Named_object* orig_no) && !orig_rec_no->var_value()->is_receiver()); orig_rec_no->var_value()->set_is_receiver(); - const std::string& new_receiver_name(orig_fntype->receiver()->name()); + std::string new_receiver_name(orig_fntype->receiver()->name()); + if (new_receiver_name.empty()) + { + // Find the receiver. It was named "r.NNN" in + // Gogo::start_function. + for (Bindings::const_definitions_iterator p = + new_bindings->begin_definitions(); + p != new_bindings->end_definitions(); + ++p) + { + const std::string& pname((*p)->name()); + if (pname[0] == 'r' && pname[1] == '.') + { + new_receiver_name = pname; + break; + } + } + go_assert(!new_receiver_name.empty()); + } Named_object* new_rec_no = new_bindings->lookup_local(new_receiver_name); if (new_rec_no == NULL) go_assert(saw_errors()); @@ -3320,7 +3341,8 @@ Function::Function(Function_type* type, Function* enclosing, Block* block, closure_var_(NULL), block_(block), location_(location), labels_(), local_type_count_(0), descriptor_(NULL), fndecl_(NULL), defer_stack_(NULL), is_sink_(false), results_are_named_(false), nointerface_(false), - calls_recover_(false), is_recover_thunk_(false), has_recover_thunk_(false), + is_unnamed_type_stub_method_(false), calls_recover_(false), + is_recover_thunk_(false), has_recover_thunk_(false), in_unique_section_(false) { } @@ -3819,6 +3841,81 @@ Function::import_func(Import* imp, std::string* pname, *presults = results; } +// Get the backend representation. + +Bfunction* +Function::get_or_make_decl(Gogo* gogo, Named_object* no) +{ + if (this->fndecl_ == NULL) + { + std::string asm_name; + bool is_visible = false; + if (no->package() != NULL) + ; + else if (this->enclosing_ != NULL || Gogo::is_thunk(no)) + ; + else if (Gogo::unpack_hidden_name(no->name()) == "init" + && !this->type_->is_method()) + ; + else if (Gogo::unpack_hidden_name(no->name()) == "main" + && gogo->is_main_package()) + is_visible = true; + // Methods have to be public even if they are hidden because + // they can be pulled into type descriptors when using + // anonymous fields. + else if (!Gogo::is_hidden_name(no->name()) + || this->type_->is_method()) + { + if (!this->is_unnamed_type_stub_method_) + is_visible = true; + std::string pkgpath = gogo->pkgpath_symbol(); + if (this->type_->is_method() + && Gogo::is_hidden_name(no->name()) + && Gogo::hidden_name_pkgpath(no->name()) != gogo->pkgpath()) + { + // This is a method we created for an unexported + // method of an imported embedded type. We need to + // use the pkgpath of the imported package to avoid + // a possible name collision. See bug478 for a test + // case. + pkgpath = Gogo::hidden_name_pkgpath(no->name()); + pkgpath = Gogo::pkgpath_for_symbol(pkgpath); + } + + asm_name = pkgpath; + asm_name.append(1, '.'); + asm_name.append(Gogo::unpack_hidden_name(no->name())); + if (this->type_->is_method()) + { + asm_name.append(1, '.'); + Type* rtype = this->type_->receiver()->type(); + asm_name.append(rtype->mangled_name(gogo)); + } + } + + // If a function calls the predeclared recover function, we + // can't inline it, because recover behaves differently in a + // function passed directly to defer. If this is a recover + // thunk that we built to test whether a function can be + // recovered, we can't inline it, because that will mess up + // our return address comparison. + bool is_inlinable = !(this->calls_recover_ || this->is_recover_thunk_); + + // If this is a thunk created to call a function which calls + // the predeclared recover function, we need to disable + // stack splitting for the thunk. + bool disable_split_stack = this->is_recover_thunk_; + + Btype* functype = this->type_->get_backend_fntype(gogo); + this->fndecl_ = + gogo->backend()->function(functype, no->get_id(gogo), asm_name, + is_visible, false, is_inlinable, + disable_split_stack, + this->in_unique_section_, this->location()); + } + return this->fndecl_; +} + // Class Block. Block::Block(Block* enclosing, Location location) @@ -5110,6 +5207,75 @@ Named_object::get_backend_variable(Gogo* gogo, Named_object* function) go_unreachable(); } + +// Return the external identifier for this object. + +std::string +Named_object::get_id(Gogo* gogo) +{ + go_assert(!this->is_variable() && !this->is_result_variable()); + std::string decl_name; + if (this->is_function_declaration() + && !this->func_declaration_value()->asm_name().empty()) + decl_name = this->func_declaration_value()->asm_name(); + else if (this->is_type() + && Linemap::is_predeclared_location(this->type_value()->location())) + { + // We don't need the package name for builtin types. + decl_name = Gogo::unpack_hidden_name(this->name_); + } + else + { + std::string package_name; + if (this->package_ == NULL) + package_name = gogo->package_name(); + else + package_name = this->package_->package_name(); + + // Note that this will be misleading if this is an unexported + // method generated for an embedded imported type. In that case + // the unexported method should have the package name of the + // package from which it is imported, but we are going to give + // it our package name. Fixing this would require knowing the + // package name, but we only know the package path. It might be + // better to use package paths here anyhow. This doesn't affect + // the assembler code, because we always set that name in + // Function::get_or_make_decl anyhow. FIXME. + + decl_name = package_name + '.' + Gogo::unpack_hidden_name(this->name_); + + Function_type* fntype; + if (this->is_function()) + fntype = this->func_value()->type(); + else if (this->is_function_declaration()) + fntype = this->func_declaration_value()->type(); + else + fntype = NULL; + if (fntype != NULL && fntype->is_method()) + { + decl_name.push_back('.'); + decl_name.append(fntype->receiver()->type()->mangled_name(gogo)); + } + } + if (this->is_type()) + { + unsigned int index; + const Named_object* in_function = this->type_value()->in_function(&index); + if (in_function != NULL) + { + decl_name += '$' + Gogo::unpack_hidden_name(in_function->name()); + if (index > 0) + { + char buf[30]; + snprintf(buf, sizeof buf, "%u", index); + decl_name += '$'; + decl_name += buf; + } + } + } + return decl_name; +} + // Class Bindings. Bindings::Bindings(Bindings* enclosing) |