Commit 3e7b0938 by Chris Manghane Committed by Ian Lance Taylor

compiler: Handle recursive pointer types for unary indirection.

	* go-gcc.cc (Gcc_backend::indirect_expression): Add btype
	parameter.
	(Gcc_backend::temporary_variable): Check for erroneous function.

From-SVN: r210087
parent e400f081
2014-05-05 Chris Manghane <cmang@google.com>
* go-gcc.cc (Gcc_backend::indirect_expression): Add btype
parameter.
(Gcc_backend::temporary_variable): Check for erroneous function.
2014-04-30 Chris Manghane <cmang@google.com> 2014-04-30 Chris Manghane <cmang@google.com>
* go-backend.c: #include "diagnostics.h". * go-backend.c: #include "diagnostics.h".
......
...@@ -229,7 +229,7 @@ class Gcc_backend : public Backend ...@@ -229,7 +229,7 @@ class Gcc_backend : public Backend
var_expression(Bvariable* var, Location); var_expression(Bvariable* var, Location);
Bexpression* Bexpression*
indirect_expression(Bexpression* expr, bool known_valid, Location); indirect_expression(Btype*, Bexpression* expr, bool known_valid, Location);
Bexpression* Bexpression*
named_constant_expression(Btype* btype, const std::string& name, named_constant_expression(Btype* btype, const std::string& name,
...@@ -1147,14 +1147,26 @@ Gcc_backend::var_expression(Bvariable* var, Location) ...@@ -1147,14 +1147,26 @@ Gcc_backend::var_expression(Bvariable* var, Location)
// An expression that indirectly references an expression. // An expression that indirectly references an expression.
Bexpression* Bexpression*
Gcc_backend::indirect_expression(Bexpression* expr, bool known_valid, Gcc_backend::indirect_expression(Btype* btype, Bexpression* expr,
Location location) bool known_valid, Location location)
{ {
tree expr_tree = expr->get_tree();
tree type_tree = btype->get_tree();
if (expr_tree == error_mark_node || type_tree == error_mark_node)
return this->error_expression();
// If the type of EXPR is a recursive pointer type, then we
// need to insert a cast before indirecting.
tree target_type_tree = TREE_TYPE(TREE_TYPE(expr_tree));
if (VOID_TYPE_P(target_type_tree))
expr_tree = fold_convert_loc(location.gcc_location(),
build_pointer_type(type_tree), expr_tree);
tree ret = build_fold_indirect_ref_loc(location.gcc_location(), tree ret = build_fold_indirect_ref_loc(location.gcc_location(),
expr->get_tree()); expr_tree);
if (known_valid) if (known_valid)
TREE_THIS_NOTRAP(ret) = 1; TREE_THIS_NOTRAP(ret) = 1;
return tree_to_expr(ret); return this->make_expression(ret);
} }
// Return an expression that declares a constant named NAME with the // Return an expression that declares a constant named NAME with the
...@@ -2406,17 +2418,18 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock, ...@@ -2406,17 +2418,18 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
Location location, Location location,
Bstatement** pstatement) Bstatement** pstatement)
{ {
gcc_assert(function != NULL);
tree decl = function->get_tree();
tree type_tree = btype->get_tree(); tree type_tree = btype->get_tree();
tree init_tree = binit == NULL ? NULL_TREE : binit->get_tree(); tree init_tree = binit == NULL ? NULL_TREE : binit->get_tree();
if (type_tree == error_mark_node || init_tree == error_mark_node) if (type_tree == error_mark_node
|| init_tree == error_mark_node
|| decl == error_mark_node)
{ {
*pstatement = this->error_statement(); *pstatement = this->error_statement();
return this->error_variable(); return this->error_variable();
} }
gcc_assert(function != NULL);
tree decl = function->get_tree();
tree var; tree var;
// We can only use create_tmp_var if the type is not addressable. // We can only use create_tmp_var if the type is not addressable.
if (!TREE_ADDRESSABLE(type_tree)) if (!TREE_ADDRESSABLE(type_tree))
......
...@@ -253,9 +253,11 @@ class Backend ...@@ -253,9 +253,11 @@ class Backend
// Create an expression that indirects through the pointer expression EXPR // Create an expression that indirects through the pointer expression EXPR
// (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer // (i.e., return the expression for *EXPR). KNOWN_VALID is true if the pointer
// is known to point to a valid memory location. // is known to point to a valid memory location. BTYPE is the expected type
// of the indirected EXPR.
virtual Bexpression* virtual Bexpression*
indirect_expression(Bexpression* expr, bool known_valid, Location) = 0; indirect_expression(Btype* btype, Bexpression* expr, bool known_valid,
Location) = 0;
// Return an expression that declares a constant named NAME with the // Return an expression that declares a constant named NAME with the
// constant value VAL in BTYPE. // constant value VAL in BTYPE.
......
...@@ -760,16 +760,24 @@ Var_expression::do_get_tree(Translate_context* context) ...@@ -760,16 +760,24 @@ Var_expression::do_get_tree(Translate_context* context)
context->function()); context->function());
bool is_in_heap; bool is_in_heap;
Location loc = this->location(); Location loc = this->location();
Btype* btype;
Gogo* gogo = context->gogo();
if (this->variable_->is_variable()) if (this->variable_->is_variable())
is_in_heap = this->variable_->var_value()->is_in_heap(); {
is_in_heap = this->variable_->var_value()->is_in_heap();
btype = this->variable_->var_value()->type()->get_backend(gogo);
}
else if (this->variable_->is_result_variable()) else if (this->variable_->is_result_variable())
is_in_heap = this->variable_->result_var_value()->is_in_heap(); {
is_in_heap = this->variable_->result_var_value()->is_in_heap();
btype = this->variable_->result_var_value()->type()->get_backend(gogo);
}
else else
go_unreachable(); go_unreachable();
Bexpression* ret = context->backend()->var_expression(bvar, loc); Bexpression* ret = context->backend()->var_expression(bvar, loc);
if (is_in_heap) if (is_in_heap)
ret = context->backend()->indirect_expression(ret, true, loc); ret = context->backend()->indirect_expression(btype, ret, true, loc);
return expr_to_tree(ret); return expr_to_tree(ret);
} }
...@@ -4168,20 +4176,7 @@ Unary_expression::do_get_tree(Translate_context* context) ...@@ -4168,20 +4176,7 @@ Unary_expression::do_get_tree(Translate_context* context)
} }
} }
ret = gogo->backend()->indirect_expression(pbtype, bexpr, false, loc);
// If the type of EXPR is a recursive pointer type, then we
// need to insert a cast before indirecting.
tree expr = expr_to_tree(bexpr);
tree target_type_tree = TREE_TYPE(TREE_TYPE(expr));
if (VOID_TYPE_P(target_type_tree))
{
tree ind = type_to_tree(pbtype);
expr = fold_convert_loc(loc.gcc_location(),
build_pointer_type(ind), expr);
bexpr = tree_to_expr(expr);
}
ret = gogo->backend()->indirect_expression(bexpr, false, loc);
} }
break; break;
...@@ -10329,7 +10324,10 @@ Array_index_expression::do_get_tree(Translate_context* context) ...@@ -10329,7 +10324,10 @@ Array_index_expression::do_get_tree(Translate_context* context)
array_type->get_value_pointer(gogo, this->array_); array_type->get_value_pointer(gogo, this->array_);
Bexpression* ptr = tree_to_expr(valptr->get_tree(context)); Bexpression* ptr = tree_to_expr(valptr->get_tree(context));
ptr = gogo->backend()->pointer_offset_expression(ptr, start, loc); ptr = gogo->backend()->pointer_offset_expression(ptr, start, loc);
ret = gogo->backend()->indirect_expression(ptr, true, loc);
Type* ele_type = this->array_->type()->array_type()->element_type();
Btype* ele_btype = ele_type->get_backend(gogo);
ret = gogo->backend()->indirect_expression(ele_btype, ptr, true, loc);
} }
return expr_to_tree(ret); return expr_to_tree(ret);
} }
...@@ -10667,7 +10665,9 @@ String_index_expression::do_get_tree(Translate_context* context) ...@@ -10667,7 +10665,9 @@ String_index_expression::do_get_tree(Translate_context* context)
Bexpression* bstart = tree_to_expr(start->get_tree(context)); Bexpression* bstart = tree_to_expr(start->get_tree(context));
Bexpression* ptr = tree_to_expr(bytes->get_tree(context)); Bexpression* ptr = tree_to_expr(bytes->get_tree(context));
ptr = gogo->backend()->pointer_offset_expression(ptr, bstart, loc); ptr = gogo->backend()->pointer_offset_expression(ptr, bstart, loc);
Bexpression* index = gogo->backend()->indirect_expression(ptr, true, loc); Btype* ubtype = Type::lookup_integer_type("uint8")->get_backend(gogo);
Bexpression* index =
gogo->backend()->indirect_expression(ubtype, ptr, true, loc);
Btype* byte_btype = bytes->type()->points_to()->get_backend(gogo); Btype* byte_btype = bytes->type()->points_to()->get_backend(gogo);
Bexpression* index_error = tree_to_expr(bad_index->get_tree(context)); Bexpression* index_error = tree_to_expr(bad_index->get_tree(context));
...@@ -13816,7 +13816,9 @@ Heap_expression::do_get_tree(Translate_context* context) ...@@ -13816,7 +13816,9 @@ Heap_expression::do_get_tree(Translate_context* context)
gogo->backend()->temporary_variable(fndecl, context->bblock(), btype, gogo->backend()->temporary_variable(fndecl, context->bblock(), btype,
space, true, loc, &decl); space, true, loc, &decl);
space = gogo->backend()->var_expression(space_temp, loc); space = gogo->backend()->var_expression(space_temp, loc);
Bexpression* ref = gogo->backend()->indirect_expression(space, true, loc); Btype* expr_btype = this->expr_->type()->get_backend(gogo);
Bexpression* ref =
gogo->backend()->indirect_expression(expr_btype, space, true, loc);
Bexpression* bexpr = tree_to_expr(this->expr_->get_tree(context)); Bexpression* bexpr = tree_to_expr(this->expr_->get_tree(context));
Bstatement* assn = gogo->backend()->assignment_statement(ref, bexpr, loc); Bstatement* assn = gogo->backend()->assignment_statement(ref, bexpr, loc);
......
...@@ -5210,7 +5210,10 @@ Function::return_value(Gogo* gogo, Named_object* named_function, ...@@ -5210,7 +5210,10 @@ Function::return_value(Gogo* gogo, Named_object* named_function,
Bvariable* bvar = no->get_backend_variable(gogo, named_function); Bvariable* bvar = no->get_backend_variable(gogo, named_function);
Bexpression* val = gogo->backend()->var_expression(bvar, location); Bexpression* val = gogo->backend()->var_expression(bvar, location);
if (no->result_var_value()->is_in_heap()) if (no->result_var_value()->is_in_heap())
val = gogo->backend()->indirect_expression(val, true, location); {
Btype* bt = no->result_var_value()->type()->get_backend(gogo);
val = gogo->backend()->indirect_expression(bt, val, true, location);
}
vals[i] = val; vals[i] = val;
} }
return gogo->backend()->return_statement(this->fndecl_, vals, location); return gogo->backend()->return_statement(this->fndecl_, vals, location);
......
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