compiler: support new language constructs in escape analysis
Previous CLs add new language constructs in Go 1.17, specifically, unsafe.Add, unsafe.Slice, and conversion from a slice to a pointer to an array. This CL handles them in the escape analysis. At the point of the escape analysis, unsafe.Add and unsafe.Slice are still builtin calls, so just handle them in data flow. Conversion from a slice to a pointer to an array has already been lowered to a combination of compound expression, conditional expression and slice info expressions, so handle them in the escape analysis. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/339671
This commit is contained in:
parent
fa1407c761
commit
22e40cc7fe
4 changed files with 134 additions and 50 deletions
|
@ -1,4 +1,4 @@
|
|||
2031f0be9c0b5fda6421d290a0261eb6bd1c8205
|
||||
616ee658a6238e7de53592ebda5997f6de6a00de
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
|
|
@ -2325,19 +2325,55 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
|
|||
}
|
||||
break;
|
||||
|
||||
case Expression::EXPRESSION_SLICE_INFO:
|
||||
{
|
||||
Slice_info_expression* sie = e->slice_info_expression();
|
||||
if (sie->info() == Expression::SLICE_INFO_VALUE_POINTER)
|
||||
{
|
||||
Node* slice = Node::make_node(sie->slice());
|
||||
this->assign(dst, slice);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Expression::EXPRESSION_CALL:
|
||||
{
|
||||
Call_expression* call = e->call_expression();
|
||||
if (call->is_builtin())
|
||||
{
|
||||
Builtin_call_expression* bce = call->builtin_call_expression();
|
||||
if (bce->code() == Builtin_call_expression::BUILTIN_APPEND)
|
||||
switch (bce->code())
|
||||
{
|
||||
// Append returns the first argument.
|
||||
// The subsequent arguments are already leaked because
|
||||
// they are operands to append.
|
||||
Node* appendee = Node::make_node(call->args()->front());
|
||||
this->assign(dst, appendee);
|
||||
case Builtin_call_expression::BUILTIN_APPEND:
|
||||
{
|
||||
// Append returns the first argument.
|
||||
// The subsequent arguments are already leaked because
|
||||
// they are operands to append.
|
||||
Node* appendee = Node::make_node(call->args()->front());
|
||||
this->assign(dst, appendee);
|
||||
}
|
||||
break;
|
||||
|
||||
case Builtin_call_expression::BUILTIN_ADD:
|
||||
{
|
||||
// unsafe.Add(p, off).
|
||||
// Flow p to result.
|
||||
Node* arg = Node::make_node(call->args()->front());
|
||||
this->assign(dst, arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case Builtin_call_expression::BUILTIN_SLICE:
|
||||
{
|
||||
// unsafe.Slice(p, len).
|
||||
// The resulting slice has the same backing store as p. Flow p to result.
|
||||
Node* arg = Node::make_node(call->args()->front());
|
||||
this->assign(dst, arg);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2592,6 +2628,21 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
|
|||
}
|
||||
break;
|
||||
|
||||
case Expression::EXPRESSION_CONDITIONAL:
|
||||
{
|
||||
Conditional_expression* ce = e->conditional_expression();
|
||||
this->assign(dst, Node::make_node(ce->then_expr()));
|
||||
this->assign(dst, Node::make_node(ce->else_expr()));
|
||||
}
|
||||
break;
|
||||
|
||||
case Expression::EXPRESSION_COMPOUND:
|
||||
{
|
||||
Compound_expression* ce = e->compound_expression();
|
||||
this->assign(dst, Node::make_node(ce->expr()));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// TODO(cmang): Add debug info here; this should not be reachable.
|
||||
// For now, just to be conservative, we'll just say dst flows to src.
|
||||
|
|
|
@ -18009,49 +18009,7 @@ Expression::make_type_info(Type* type, Type_info type_info)
|
|||
return new Type_info_expression(type, type_info);
|
||||
}
|
||||
|
||||
// An expression that evaluates to some characteristic of a slice.
|
||||
// This is used when indexing, bound-checking, or nil checking a slice.
|
||||
|
||||
class Slice_info_expression : public Expression
|
||||
{
|
||||
public:
|
||||
Slice_info_expression(Expression* slice, Slice_info slice_info,
|
||||
Location location)
|
||||
: Expression(EXPRESSION_SLICE_INFO, location),
|
||||
slice_(slice), slice_info_(slice_info)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
Type*
|
||||
do_type();
|
||||
|
||||
void
|
||||
do_determine_type(const Type_context*)
|
||||
{ }
|
||||
|
||||
Expression*
|
||||
do_copy()
|
||||
{
|
||||
return new Slice_info_expression(this->slice_->copy(), this->slice_info_,
|
||||
this->location());
|
||||
}
|
||||
|
||||
Bexpression*
|
||||
do_get_backend(Translate_context* context);
|
||||
|
||||
void
|
||||
do_dump_expression(Ast_dump_context*) const;
|
||||
|
||||
void
|
||||
do_issue_nil_check()
|
||||
{ this->slice_->issue_nil_check(); }
|
||||
|
||||
private:
|
||||
// The slice for which we are getting information.
|
||||
Expression* slice_;
|
||||
// What information we want.
|
||||
Slice_info slice_info_;
|
||||
};
|
||||
// Slice_info_expression.
|
||||
|
||||
// Return the type of the slice info.
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ class Type_guard_expression;
|
|||
class Heap_expression;
|
||||
class Receive_expression;
|
||||
class Slice_value_expression;
|
||||
class Slice_info_expression;
|
||||
class Conditional_expression;
|
||||
class Compound_expression;
|
||||
class Numeric_constant;
|
||||
|
@ -900,6 +901,14 @@ class Expression
|
|||
compound_expression()
|
||||
{ return this->convert<Compound_expression, EXPRESSION_COMPOUND>(); }
|
||||
|
||||
// If this is a slice info expression, return the
|
||||
// Slice_info_expression structure. Otherwise, return NULL.
|
||||
Slice_info_expression*
|
||||
slice_info_expression()
|
||||
{
|
||||
return this->convert<Slice_info_expression, EXPRESSION_SLICE_INFO>();
|
||||
}
|
||||
|
||||
// Return true if this is a composite literal.
|
||||
bool
|
||||
is_composite_literal() const;
|
||||
|
@ -4262,6 +4271,60 @@ class Slice_value_expression : public Expression
|
|||
Expression* cap_;
|
||||
};
|
||||
|
||||
// An expression that evaluates to some characteristic of a slice.
|
||||
// This is used when indexing, bound-checking, or nil checking a slice.
|
||||
|
||||
class Slice_info_expression : public Expression
|
||||
{
|
||||
public:
|
||||
Slice_info_expression(Expression* slice, Slice_info slice_info,
|
||||
Location location)
|
||||
: Expression(EXPRESSION_SLICE_INFO, location),
|
||||
slice_(slice), slice_info_(slice_info)
|
||||
{ }
|
||||
|
||||
// The slice operand of this slice info expression.
|
||||
Expression*
|
||||
slice() const
|
||||
{ return this->slice_; }
|
||||
|
||||
// The info this expression is about.
|
||||
Slice_info
|
||||
info() const
|
||||
{ return this->slice_info_; }
|
||||
|
||||
protected:
|
||||
Type*
|
||||
do_type();
|
||||
|
||||
void
|
||||
do_determine_type(const Type_context*)
|
||||
{ }
|
||||
|
||||
Expression*
|
||||
do_copy()
|
||||
{
|
||||
return new Slice_info_expression(this->slice_->copy(), this->slice_info_,
|
||||
this->location());
|
||||
}
|
||||
|
||||
Bexpression*
|
||||
do_get_backend(Translate_context* context);
|
||||
|
||||
void
|
||||
do_dump_expression(Ast_dump_context*) const;
|
||||
|
||||
void
|
||||
do_issue_nil_check()
|
||||
{ this->slice_->issue_nil_check(); }
|
||||
|
||||
private:
|
||||
// The slice for which we are getting information.
|
||||
Expression* slice_;
|
||||
// What information we want.
|
||||
Slice_info slice_info_;
|
||||
};
|
||||
|
||||
// Conditional expressions.
|
||||
|
||||
class Conditional_expression : public Expression
|
||||
|
@ -4277,6 +4340,14 @@ class Conditional_expression : public Expression
|
|||
condition() const
|
||||
{ return this->cond_; }
|
||||
|
||||
Expression*
|
||||
then_expr() const
|
||||
{ return this->then_; }
|
||||
|
||||
Expression*
|
||||
else_expr() const
|
||||
{ return this->else_; }
|
||||
|
||||
protected:
|
||||
int
|
||||
do_traverse(Traverse*);
|
||||
|
@ -4322,6 +4393,10 @@ class Compound_expression : public Expression
|
|||
init() const
|
||||
{ return this->init_; }
|
||||
|
||||
Expression*
|
||||
expr() const
|
||||
{ return this->expr_; }
|
||||
|
||||
protected:
|
||||
int
|
||||
do_traverse(Traverse*);
|
||||
|
|
Loading…
Add table
Reference in a new issue