aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8/gcc/go/gofrontend/gogo.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8/gcc/go/gofrontend/gogo.cc')
-rw-r--r--gcc-4.8/gcc/go/gofrontend/gogo.cc172
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)