diff options
-rw-r--r-- | gcc/go/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/go/go-gcc.cc | 31 | ||||
-rw-r--r-- | gcc/go/gofrontend/backend.h | 6 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 42 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 5 |
5 files changed, 58 insertions, 32 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index a468bee..4e4afdb 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,9 @@ +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> * go-backend.c: #include "diagnostics.h". diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 0f3f44b..343661e 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -229,7 +229,7 @@ class Gcc_backend : public Backend var_expression(Bvariable* var, Location); Bexpression* - indirect_expression(Bexpression* expr, bool known_valid, Location); + indirect_expression(Btype*, Bexpression* expr, bool known_valid, Location); Bexpression* named_constant_expression(Btype* btype, const std::string& name, @@ -1147,14 +1147,26 @@ Gcc_backend::var_expression(Bvariable* var, Location) // An expression that indirectly references an expression. Bexpression* -Gcc_backend::indirect_expression(Bexpression* expr, bool known_valid, - Location location) +Gcc_backend::indirect_expression(Btype* btype, Bexpression* expr, + 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(), - expr->get_tree()); + expr_tree); if (known_valid) 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 @@ -2406,17 +2418,18 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock, Location location, Bstatement** pstatement) { + gcc_assert(function != NULL); + tree decl = function->get_tree(); tree type_tree = btype->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(); return this->error_variable(); } - gcc_assert(function != NULL); - tree decl = function->get_tree(); - tree var; // We can only use create_tmp_var if the type is not addressable. if (!TREE_ADDRESSABLE(type_tree)) diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index 786223f..e49cedf 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -253,9 +253,11 @@ class Backend // Create an expression that indirects through the pointer expression EXPR // (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* - 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 // constant value VAL in BTYPE. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index ec59354..b1d9bcc 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -760,16 +760,24 @@ Var_expression::do_get_tree(Translate_context* context) context->function()); bool is_in_heap; Location loc = this->location(); + Btype* btype; + Gogo* gogo = context->gogo(); 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()) - 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 go_unreachable(); Bexpression* ret = context->backend()->var_expression(bvar, loc); 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); } @@ -4168,20 +4176,7 @@ Unary_expression::do_get_tree(Translate_context* context) } } - - // 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); + ret = gogo->backend()->indirect_expression(pbtype, bexpr, false, loc); } break; @@ -10329,7 +10324,10 @@ Array_index_expression::do_get_tree(Translate_context* context) array_type->get_value_pointer(gogo, this->array_); Bexpression* ptr = tree_to_expr(valptr->get_tree(context)); 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); } @@ -10667,7 +10665,9 @@ String_index_expression::do_get_tree(Translate_context* context) Bexpression* bstart = tree_to_expr(start->get_tree(context)); Bexpression* ptr = tree_to_expr(bytes->get_tree(context)); 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); Bexpression* index_error = tree_to_expr(bad_index->get_tree(context)); @@ -13816,7 +13816,9 @@ Heap_expression::do_get_tree(Translate_context* context) gogo->backend()->temporary_variable(fndecl, context->bblock(), btype, space, true, loc, &decl); 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)); Bstatement* assn = gogo->backend()->assignment_statement(ref, bexpr, loc); diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index ab54f84..e0ddc2f 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -5210,7 +5210,10 @@ Function::return_value(Gogo* gogo, Named_object* named_function, Bvariable* bvar = no->get_backend_variable(gogo, named_function); Bexpression* val = gogo->backend()->var_expression(bvar, location); 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; } return gogo->backend()->return_statement(this->fndecl_, vals, location); |