-f8a3668cbcfa3f8cd6c26c62bce416714cd401fc
+b5ab7b419d6328f5126ba8d6795280129eaf6e79
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
else
has_closure_arg = true;
+ Expression* first_arg = NULL;
+ if (!is_interface_method && fntype->is_method())
+ {
+ first_arg = this->args_->front();
+ if (first_arg->type()->points_to() == NULL
+ && first_arg->type()->is_direct_iface_type())
+ first_arg = Expression::unpack_direct_iface(first_arg,
+ first_arg->location());
+ }
+
int nargs;
std::vector<Bexpression*> fn_args;
if (this->args_ == NULL || this->args_->empty())
&& this->args_->size() == 1);
nargs = 1;
fn_args.resize(1);
- fn_args[0] = this->args_->front()->get_backend(context);
+ fn_args[0] = first_arg->get_backend(context);
}
else
{
Expression_list::const_iterator pe = this->args_->begin();
if (!is_interface_method && fntype->is_method())
{
- fn_args[i] = (*pe)->get_backend(context);
+ fn_args[i] = first_arg->get_backend(context);
++pe;
++i;
}
static Expression*
pack_direct_iface(Type*, Expression*, Location);
+ // Return an expression of the underlying pointer for a direct interface
+ // type (the opposite of pack_direct_iface).
+ static Expression*
+ unpack_direct_iface(Expression*, Location);
+
// Dump an expression to a dump constext.
void
dump_expression(Ast_dump_context*) const;
: NULL);
}
- static Expression*
- unpack_direct_iface(Expression*, Location);
-
static Expression*
get_interface_type_descriptor(Expression*);
// We always pass the receiver to a method as a pointer. If
// the receiver is declared as a non-pointer type, then we
- // copy the value into a local variable.
+ // copy the value into a local variable. For direct interface
+ // type we pack the pointer into the type.
if ((*p)->var_value()->is_receiver()
- && !(*p)->var_value()->type()->is_direct_iface_type())
+ && (*p)->var_value()->type()->points_to() == NULL)
{
std::string name = (*p)->name() + ".pointer";
Type* var_type = (*p)->var_value()->type();
parm_bvar = parm_no->get_backend_variable(gogo, named_function);
vars.push_back(bvar);
- Expression* parm_ref =
+
+ Expression* parm_ref =
Expression::make_var_reference(parm_no, loc);
- parm_ref =
- Expression::make_dereference(parm_ref,
- Expression::NIL_CHECK_NEEDED,
- loc);
- if ((*p)->var_value()->is_in_heap())
- parm_ref = Expression::make_heap_expression(parm_ref, loc);
+ Type* recv_type = (*p)->var_value()->type();
+ if (recv_type->is_direct_iface_type())
+ parm_ref = Expression::pack_direct_iface(recv_type, parm_ref, loc);
+ else
+ parm_ref =
+ Expression::make_dereference(parm_ref,
+ Expression::NIL_CHECK_NEEDED,
+ loc);
+ if ((*p)->var_value()->is_in_heap())
+ parm_ref = Expression::make_heap_expression(parm_ref, loc);
var_inits.push_back(parm_ref->get_backend(&context));
}
else if ((*p)->var_value()->is_in_heap())
else
{
bool is_parameter = this->is_parameter_;
- if (this->is_receiver_ && !type->is_direct_iface_type())
+ if (this->is_receiver_ && type->points_to() == NULL)
is_parameter = false;
if (this->is_in_heap())
{
// We always pass the address of the receiver parameter, in
// order to make interface calls work with unknown types,
// except for direct interface types where the interface call
- // actually passes value.
+ // actually passes the underlying pointer of the value.
Type* rtype = this->receiver_->type();
- if (!rtype->is_direct_iface_type())
- rtype = Type::make_pointer_type(rtype);
+ if (rtype->points_to() == NULL)
+ {
+ if (rtype->is_direct_iface_type())
+ rtype = Type::make_pointer_type(Type::make_void_type());
+ else
+ rtype = Type::make_pointer_type(rtype);
+ }
breceiver.btype = rtype->get_backend(gogo);
breceiver.location = this->receiver_->location();
}