Commit 6ddb6288 by Ian Lance Taylor

compiler: Use backend interface for slice info.

From-SVN: r206509
parent 7f003d83
......@@ -102,6 +102,7 @@ class Expression
EXPRESSION_RECEIVE,
EXPRESSION_TYPE_DESCRIPTOR,
EXPRESSION_TYPE_INFO,
EXPRESSION_SLICE_INFO,
EXPRESSION_STRUCT_FIELD_OFFSET,
EXPRESSION_MAP_DESCRIPTOR,
EXPRESSION_LABEL_ADDR
......@@ -339,6 +340,22 @@ class Expression
static Expression*
make_type_info(Type* type, Type_info);
// Make an expression that evaluates to some characteristic of a
// slice. For simplicity, the enum values must match the field indexes
// in the underlying struct.
enum Slice_info
{
// The underlying data of the slice.
SLICE_INFO_VALUE_POINTER,
// The length of the slice.
SLICE_INFO_LENGTH,
// The capacity of the slice.
SLICE_INFO_CAPACITY
};
static Expression*
make_slice_info(Expression* slice, Slice_info, Location);
// Make an expression which evaluates to the offset of a field in a
// struct. This is only used for type descriptors, so there is no
// location parameter.
......@@ -544,6 +561,10 @@ class Expression
bool
is_nonconstant_composite_literal() const;
// Return true if this is a variable or temporary variable.
bool
is_variable() const;
// Return true if this is a reference to a local variable.
bool
is_local_variable() const;
......
......@@ -2846,6 +2846,15 @@ Flatten::expression(Expression** pexpr)
return TRAVERSE_SKIP_COMPONENTS;
}
// Flatten a block.
void
Gogo::flatten_block(Named_object* function, Block* block)
{
Flatten flatten(this, function);
block->traverse(&flatten);
}
// Flatten an expression. INSERTER may be NULL, in which case the
// expression had better not need to create any temporaries.
......
......@@ -487,6 +487,10 @@ class Gogo
void
lower_constant(Named_object*);
// Flatten all the statements in a block.
void
flatten_block(Named_object* function, Block*);
// Flatten an expression.
void
flatten_expression(Named_object* function, Statement_inserter*, Expression**);
......
......@@ -2471,6 +2471,7 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
gogo->add_block(b, location);
gogo->lower_block(function, b);
gogo->flatten_block(function, b);
// We already ran the determine_types pass, so we need to run it
// just for the call statement now. The other types are known.
......
......@@ -6000,84 +6000,53 @@ Array_type::finish_backend_element(Gogo* gogo)
}
}
// Return a tree for a pointer to the values in ARRAY.
// Return an expression for a pointer to the values in ARRAY.
tree
Array_type::value_pointer_tree(Gogo*, tree array) const
Expression*
Array_type::get_value_pointer(Gogo*, Expression* array) const
{
tree ret;
if (this->length() != NULL)
{
// Fixed array.
ret = fold_convert(build_pointer_type(TREE_TYPE(TREE_TYPE(array))),
build_fold_addr_expr(array));
go_assert(array->type()->array_type() != NULL);
Type* etype = array->type()->array_type()->element_type();
array = Expression::make_unary(OPERATOR_AND, array, array->location());
return Expression::make_cast(Type::make_pointer_type(etype), array,
array->location());
}
else
{
// Open array.
tree field = TYPE_FIELDS(TREE_TYPE(array));
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)),
"__values") == 0);
ret = fold_build3(COMPONENT_REF, TREE_TYPE(field), array, field,
NULL_TREE);
}
if (TREE_CONSTANT(array))
TREE_CONSTANT(ret) = 1;
return ret;
// Open array.
return Expression::make_slice_info(array,
Expression::SLICE_INFO_VALUE_POINTER,
array->location());
}
// Return a tree for the length of the array ARRAY which has this
// Return an expression for the length of the array ARRAY which has this
// type.
tree
Array_type::length_tree(Gogo* gogo, tree array)
Expression*
Array_type::get_length(Gogo*, Expression* array) const
{
if (this->length_ != NULL)
{
if (TREE_CODE(array) == SAVE_EXPR)
return this->get_length_tree(gogo);
else
{
tree len = this->get_length_tree(gogo);
return omit_one_operand(TREE_TYPE(len), len, array);
}
}
return this->length_;
// This is an open array. We need to read the length field.
tree type = TREE_TYPE(array);
go_assert(TREE_CODE(type) == RECORD_TYPE);
tree field = DECL_CHAIN(TYPE_FIELDS(type));
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__count") == 0);
tree ret = build3(COMPONENT_REF, TREE_TYPE(field), array, field, NULL_TREE);
if (TREE_CONSTANT(array))
TREE_CONSTANT(ret) = 1;
return ret;
return Expression::make_slice_info(array, Expression::SLICE_INFO_LENGTH,
array->location());
}
// Return a tree for the capacity of the array ARRAY which has this
// Return an expression for the capacity of the array ARRAY which has this
// type.
tree
Array_type::capacity_tree(Gogo* gogo, tree array)
Expression*
Array_type::get_capacity(Gogo*, Expression* array) const
{
if (this->length_ != NULL)
{
tree len = this->get_length_tree(gogo);
return omit_one_operand(TREE_TYPE(len), len, array);
}
return this->length_;
// This is an open array. We need to read the capacity field.
tree type = TREE_TYPE(array);
go_assert(TREE_CODE(type) == RECORD_TYPE);
tree field = DECL_CHAIN(DECL_CHAIN(TYPE_FIELDS(type)));
go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__capacity") == 0);
return build3(COMPONENT_REF, TREE_TYPE(field), array, field, NULL_TREE);
return Expression::make_slice_info(array, Expression::SLICE_INFO_CAPACITY,
array->location());
}
// Export.
......
......@@ -2312,17 +2312,17 @@ class Array_type : public Type
array_has_hidden_fields(const Named_type* within, std::string* reason) const
{ return this->element_type_->has_hidden_fields(within, reason); }
// Return a tree for the pointer to the values in an array.
tree
value_pointer_tree(Gogo*, tree array) const;
// Return an expression for the pointer to the values in an array.
Expression*
get_value_pointer(Gogo*, Expression* array) const;
// Return a tree for the length of an array with this type.
tree
length_tree(Gogo*, tree array);
// Return an expression for the length of an array with this type.
Expression*
get_length(Gogo*, Expression* array) const;
// Return a tree for the capacity of an array with this type.
tree
capacity_tree(Gogo*, tree array);
// Return an expression for the capacity of an array with this type.
Expression*
get_capacity(Gogo*, Expression* array) const;
// Import an array type.
static Array_type*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment