mirror of git://gcc.gnu.org/git/gcc.git
parent
09367c0d60
commit
f29ce5f5f1
|
@ -7048,6 +7048,7 @@ class Builtin_call_expression : public Call_expression
|
||||||
BUILTIN_CLOSE,
|
BUILTIN_CLOSE,
|
||||||
BUILTIN_COMPLEX,
|
BUILTIN_COMPLEX,
|
||||||
BUILTIN_COPY,
|
BUILTIN_COPY,
|
||||||
|
BUILTIN_DELETE,
|
||||||
BUILTIN_IMAG,
|
BUILTIN_IMAG,
|
||||||
BUILTIN_LEN,
|
BUILTIN_LEN,
|
||||||
BUILTIN_MAKE,
|
BUILTIN_MAKE,
|
||||||
|
@ -7113,6 +7114,8 @@ Builtin_call_expression::Builtin_call_expression(Gogo* gogo,
|
||||||
this->code_ = BUILTIN_COMPLEX;
|
this->code_ = BUILTIN_COMPLEX;
|
||||||
else if (name == "copy")
|
else if (name == "copy")
|
||||||
this->code_ = BUILTIN_COPY;
|
this->code_ = BUILTIN_COPY;
|
||||||
|
else if (name == "delete")
|
||||||
|
this->code_ = BUILTIN_DELETE;
|
||||||
else if (name == "imag")
|
else if (name == "imag")
|
||||||
this->code_ = BUILTIN_IMAG;
|
this->code_ = BUILTIN_IMAG;
|
||||||
else if (name == "len")
|
else if (name == "len")
|
||||||
|
@ -7206,34 +7209,15 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
|
||||||
if (this->classification() == EXPRESSION_ERROR)
|
if (this->classification() == EXPRESSION_ERROR)
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
|
source_location loc = this->location();
|
||||||
|
|
||||||
if (this->is_varargs() && this->code_ != BUILTIN_APPEND)
|
if (this->is_varargs() && this->code_ != BUILTIN_APPEND)
|
||||||
{
|
{
|
||||||
this->report_error(_("invalid use of %<...%> with builtin function"));
|
this->report_error(_("invalid use of %<...%> with builtin function"));
|
||||||
return Expression::make_error(this->location());
|
return Expression::make_error(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->code_ == BUILTIN_NEW)
|
if (this->is_constant())
|
||||||
{
|
|
||||||
const Expression_list* args = this->args();
|
|
||||||
if (args == NULL || args->size() < 1)
|
|
||||||
this->report_error(_("not enough arguments"));
|
|
||||||
else if (args->size() > 1)
|
|
||||||
this->report_error(_("too many arguments"));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Expression* arg = args->front();
|
|
||||||
if (!arg->is_type_expression())
|
|
||||||
{
|
|
||||||
error_at(arg->location(), "expected type");
|
|
||||||
this->set_is_error();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return Expression::make_allocation(arg->type(), this->location());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (this->code_ == BUILTIN_MAKE)
|
|
||||||
return this->lower_make();
|
|
||||||
else if (this->is_constant())
|
|
||||||
{
|
{
|
||||||
// We can only lower len and cap if there are no function calls
|
// We can only lower len and cap if there are no function calls
|
||||||
// in the arguments. Otherwise we have to make the call.
|
// in the arguments. Otherwise we have to make the call.
|
||||||
|
@ -7254,8 +7238,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
|
||||||
Type* type;
|
Type* type;
|
||||||
if (this->integer_constant_value(true, ival, &type))
|
if (this->integer_constant_value(true, ival, &type))
|
||||||
{
|
{
|
||||||
Expression* ret = Expression::make_integer(&ival, type,
|
Expression* ret = Expression::make_integer(&ival, type, loc);
|
||||||
this->location());
|
|
||||||
mpz_clear(ival);
|
mpz_clear(ival);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -7265,8 +7248,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
|
||||||
mpfr_init(rval);
|
mpfr_init(rval);
|
||||||
if (this->float_constant_value(rval, &type))
|
if (this->float_constant_value(rval, &type))
|
||||||
{
|
{
|
||||||
Expression* ret = Expression::make_float(&rval, type,
|
Expression* ret = Expression::make_float(&rval, type, loc);
|
||||||
this->location());
|
|
||||||
mpfr_clear(rval);
|
mpfr_clear(rval);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -7275,8 +7257,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
|
||||||
mpfr_init(imag);
|
mpfr_init(imag);
|
||||||
if (this->complex_constant_value(rval, imag, &type))
|
if (this->complex_constant_value(rval, imag, &type))
|
||||||
{
|
{
|
||||||
Expression* ret = Expression::make_complex(&rval, &imag, type,
|
Expression* ret = Expression::make_complex(&rval, &imag, type, loc);
|
||||||
this->location());
|
|
||||||
mpfr_clear(rval);
|
mpfr_clear(rval);
|
||||||
mpfr_clear(imag);
|
mpfr_clear(imag);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -7284,21 +7265,49 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
|
||||||
mpfr_clear(rval);
|
mpfr_clear(rval);
|
||||||
mpfr_clear(imag);
|
mpfr_clear(imag);
|
||||||
}
|
}
|
||||||
else if (this->code_ == BUILTIN_RECOVER)
|
|
||||||
|
switch (this->code_)
|
||||||
{
|
{
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUILTIN_NEW:
|
||||||
|
{
|
||||||
|
const Expression_list* args = this->args();
|
||||||
|
if (args == NULL || args->size() < 1)
|
||||||
|
this->report_error(_("not enough arguments"));
|
||||||
|
else if (args->size() > 1)
|
||||||
|
this->report_error(_("too many arguments"));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Expression* arg = args->front();
|
||||||
|
if (!arg->is_type_expression())
|
||||||
|
{
|
||||||
|
error_at(arg->location(), "expected type");
|
||||||
|
this->set_is_error();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Expression::make_allocation(arg->type(), loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUILTIN_MAKE:
|
||||||
|
return this->lower_make();
|
||||||
|
|
||||||
|
case BUILTIN_RECOVER:
|
||||||
if (function != NULL)
|
if (function != NULL)
|
||||||
function->func_value()->set_calls_recover();
|
function->func_value()->set_calls_recover();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Calling recover outside of a function always returns the
|
// Calling recover outside of a function always returns the
|
||||||
// nil empty interface.
|
// nil empty interface.
|
||||||
Type* eface = Type::make_interface_type(NULL, this->location());
|
Type* eface = Type::make_interface_type(NULL, loc);
|
||||||
return Expression::make_cast(eface,
|
return Expression::make_cast(eface, Expression::make_nil(loc), loc);
|
||||||
Expression::make_nil(this->location()),
|
|
||||||
this->location());
|
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
else if (this->code_ == BUILTIN_APPEND)
|
|
||||||
|
case BUILTIN_APPEND:
|
||||||
{
|
{
|
||||||
// Lower the varargs.
|
// Lower the varargs.
|
||||||
const Expression_list* args = this->args();
|
const Expression_list* args = this->args();
|
||||||
|
@ -7313,6 +7322,44 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
|
||||||
}
|
}
|
||||||
this->lower_varargs(gogo, function, inserter, slice_type, 2);
|
this->lower_varargs(gogo, function, inserter, slice_type, 2);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUILTIN_DELETE:
|
||||||
|
{
|
||||||
|
// Lower to a runtime function call.
|
||||||
|
const Expression_list* args = this->args();
|
||||||
|
if (args == NULL || args->size() < 2)
|
||||||
|
this->report_error(_("not enough arguments"));
|
||||||
|
else if (args->size() > 2)
|
||||||
|
this->report_error(_("too many arguments"));
|
||||||
|
else if (args->front()->type()->map_type() == NULL)
|
||||||
|
this->report_error(_("argument 1 must be a map"));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Since this function returns no value it must appear in
|
||||||
|
// a statement by itself, so we don't have to worry about
|
||||||
|
// order of evaluation of values around it. Evaluate the
|
||||||
|
// map first to get order of evaluation right.
|
||||||
|
Map_type* mt = args->front()->type()->map_type();
|
||||||
|
Temporary_statement* map_temp =
|
||||||
|
Statement::make_temporary(mt, args->front(), loc);
|
||||||
|
inserter->insert(map_temp);
|
||||||
|
|
||||||
|
Temporary_statement* key_temp =
|
||||||
|
Statement::make_temporary(mt->key_type(), args->back(), loc);
|
||||||
|
inserter->insert(key_temp);
|
||||||
|
|
||||||
|
Expression* e1 = Expression::make_temporary_reference(map_temp,
|
||||||
|
loc);
|
||||||
|
Expression* e2 = Expression::make_temporary_reference(key_temp,
|
||||||
|
loc);
|
||||||
|
e2 = Expression::make_unary(OPERATOR_AND, e2, loc);
|
||||||
|
return Runtime::make_call(Runtime::MAPDELETE, this->location(),
|
||||||
|
2, e1, e2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -7845,6 +7892,7 @@ Builtin_call_expression::do_discarding_value()
|
||||||
|
|
||||||
case BUILTIN_CLOSE:
|
case BUILTIN_CLOSE:
|
||||||
case BUILTIN_COPY:
|
case BUILTIN_COPY:
|
||||||
|
case BUILTIN_DELETE:
|
||||||
case BUILTIN_PANIC:
|
case BUILTIN_PANIC:
|
||||||
case BUILTIN_PRINT:
|
case BUILTIN_PRINT:
|
||||||
case BUILTIN_PRINTLN:
|
case BUILTIN_PRINTLN:
|
||||||
|
@ -7882,6 +7930,7 @@ Builtin_call_expression::do_type()
|
||||||
return Type::lookup_integer_type("int");
|
return Type::lookup_integer_type("int");
|
||||||
|
|
||||||
case BUILTIN_CLOSE:
|
case BUILTIN_CLOSE:
|
||||||
|
case BUILTIN_DELETE:
|
||||||
case BUILTIN_PANIC:
|
case BUILTIN_PANIC:
|
||||||
case BUILTIN_PRINT:
|
case BUILTIN_PRINT:
|
||||||
case BUILTIN_PRINTLN:
|
case BUILTIN_PRINTLN:
|
||||||
|
|
|
@ -201,6 +201,11 @@ Gogo::Gogo(Backend* backend, int int_type_size, int pointer_size)
|
||||||
imag_type->set_is_varargs();
|
imag_type->set_is_varargs();
|
||||||
imag_type->set_is_builtin();
|
imag_type->set_is_builtin();
|
||||||
this->globals_->add_function_declaration("imag", NULL, imag_type, loc);
|
this->globals_->add_function_declaration("imag", NULL, imag_type, loc);
|
||||||
|
|
||||||
|
Function_type* delete_type = Type::make_function_type(NULL, NULL, NULL, loc);
|
||||||
|
delete_type->set_is_varargs();
|
||||||
|
delete_type->set_is_builtin();
|
||||||
|
this->globals_->add_function_declaration("delete", NULL, delete_type, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Munge name for use in an error message.
|
// Munge name for use in an error message.
|
||||||
|
|
|
@ -94,6 +94,9 @@ DEF_GO_RUNTIME(MAPACCESS2, "runtime.mapaccess2",
|
||||||
DEF_GO_RUNTIME(MAPASSIGN2, "runtime.mapassign2",
|
DEF_GO_RUNTIME(MAPASSIGN2, "runtime.mapassign2",
|
||||||
P4(MAP, POINTER, POINTER, BOOL), R0())
|
P4(MAP, POINTER, POINTER, BOOL), R0())
|
||||||
|
|
||||||
|
// Delete a key from a map.
|
||||||
|
DEF_GO_RUNTIME(MAPDELETE, "runtime.mapdelete", P2(MAP, POINTER), R0())
|
||||||
|
|
||||||
// Begin a range over a map.
|
// Begin a range over a map.
|
||||||
DEF_GO_RUNTIME(MAPITERINIT, "runtime.mapiterinit", P2(MAP, MAPITER), R0())
|
DEF_GO_RUNTIME(MAPITERINIT, "runtime.mapiterinit", P2(MAP, MAPITER), R0())
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ __go_map_delete (struct __go_map *map, const void *key)
|
||||||
void **pentry;
|
void **pentry;
|
||||||
|
|
||||||
if (map == NULL)
|
if (map == NULL)
|
||||||
__go_panic_msg ("assignment to entry in nil map");
|
__go_panic_msg ("deletion of entry in nil map");
|
||||||
|
|
||||||
descriptor = map->__descriptor;
|
descriptor = map->__descriptor;
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,12 @@ func mapassign2(h *Hmap, key *byte, val *byte, p bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Delete a key from a map. */
|
||||||
|
|
||||||
|
func mapdelete(h *Hmap, key *byte) {
|
||||||
|
__go_map_delete(h, key);
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize a range over a map. */
|
/* Initialize a range over a map. */
|
||||||
|
|
||||||
func mapiterinit(h *Hmap, it *hiter) {
|
func mapiterinit(h *Hmap, it *hiter) {
|
||||||
|
|
Loading…
Reference in New Issue