This patch to the Go frontend by Cherry Zhang stack allocates a non-escaping make of a slice type with a constant length and capacity. Bootstrapped on x86_64-pc-linux-gnu. Committed to mainline.
Ian
Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 256403) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -91169ab206266361624236f0137668162ee8cb9b +b361bec95927fd6209c286906f98deeedcfe1da3 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: gcc/go/gofrontend/expressions.cc =================================================================== --- gcc/go/gofrontend/expressions.cc (revision 256403) +++ gcc/go/gofrontend/expressions.cc (working copy) @@ -7496,6 +7496,10 @@ Builtin_call_expression::lower_make(Stat Expression* cap_arg = NULL; bool cap_small = false; + Numeric_constant nclen; + Numeric_constant nccap; + unsigned long vlen; + unsigned long vcap; if (is_slice && parg != args->end()) { cap_arg = *parg; @@ -7503,10 +7507,6 @@ Builtin_call_expression::lower_make(Stat if (!this->check_int_value(cap_arg, false, &cap_small)) return Expression::make_error(this->location()); - Numeric_constant nclen; - Numeric_constant nccap; - unsigned long vlen; - unsigned long vcap; if (len_arg->numeric_constant_value(&nclen) && cap_arg->numeric_constant_value(&nccap) && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID @@ -7531,19 +7531,25 @@ Builtin_call_expression::lower_make(Stat Expression* call; if (is_slice) { - Type* et = type->array_type()->element_type(); - Expression* type_arg = Expression::make_type_descriptor(et, type_loc); if (cap_arg == NULL) { - Temporary_statement* temp = Statement::make_temporary(NULL, - len_arg, - loc); - inserter->insert(temp); - len_arg = Expression::make_temporary_reference(temp, loc); - cap_arg = Expression::make_temporary_reference(temp, loc); - cap_small = len_small; + cap_small = len_small; + if (len_arg->numeric_constant_value(&nclen) + && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID) + cap_arg = Expression::make_integer_ul(vlen, len_arg->type(), loc); + else + { + Temporary_statement* temp = Statement::make_temporary(NULL, + len_arg, + loc); + inserter->insert(temp); + len_arg = Expression::make_temporary_reference(temp, loc); + cap_arg = Expression::make_temporary_reference(temp, loc); + } } + Type* et = type->array_type()->element_type(); + Expression* type_arg = Expression::make_type_descriptor(et, type_loc); Runtime::Function code = Runtime::MAKESLICE; if (!len_small || !cap_small) code = Runtime::MAKESLICE64; Index: gcc/go/gofrontend/wb.cc =================================================================== --- gcc/go/gofrontend/wb.cc (revision 256403) +++ gcc/go/gofrontend/wb.cc (working copy) @@ -64,6 +64,47 @@ Mark_address_taken::expression(Expressio } aie->array()->address_taken(escapes); } + + // Rewrite non-escaping makeslice with constant size to stack allocation. + Unsafe_type_conversion_expression* uce = + expr->unsafe_conversion_expression(); + if (uce != NULL + && uce->type()->is_slice_type() + && Node::make_node(uce->expr())->encoding() == Node::ESCAPE_NONE + && uce->expr()->call_expression() != NULL) + { + Call_expression* call = uce->expr()->call_expression(); + if (call->fn()->func_expression() != NULL + && call->fn()->func_expression()->runtime_code() == Runtime::MAKESLICE) + { + Expression* len_arg = call->args()->at(1); + Expression* cap_arg = call->args()->at(2); + Numeric_constant nclen; + Numeric_constant nccap; + unsigned long vlen; + unsigned long vcap; + if (len_arg->numeric_constant_value(&nclen) + && cap_arg->numeric_constant_value(&nccap) + && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID + && nccap.to_unsigned_long(&vcap) == Numeric_constant::NC_UL_VALID) + { + // Turn it into a slice expression of an addressable array, + // which is allocated on stack. + Location loc = expr->location(); + Type* elmt_type = expr->type()->array_type()->element_type(); + Expression* len_expr = + Expression::make_integer_ul(vcap, cap_arg->type(), loc); + Type* array_type = Type::make_array_type(elmt_type, len_expr); + Expression* alloc = Expression::make_allocation(array_type, loc); + alloc->allocation_expression()->set_allocate_on_stack(); + Expression* array = Expression::make_unary(OPERATOR_MULT, alloc, loc); + Expression* zero = Expression::make_integer_ul(0, len_arg->type(), loc); + Expression* slice = + Expression::make_array_index(array, zero, len_arg, cap_arg, loc); + *pexpr = slice; + } + } + } return TRAVERSE_CONTINUE; }